Skip to content

Commit

Permalink
chore: Prep for Craft 5
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnynotsolucky committed Sep 25, 2024
1 parent 652e4a1 commit 567aac8
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 269 deletions.
59 changes: 59 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: CI

on:
workflow_dispatch:
push:
branches:
- main
- develop-craft5
pull_request:

jobs:
ecs:
name: ECS Check
runs-on: ubuntu-latest
env:
DEFAULT_COMPOSER_FLAGS: "--no-interaction --no-ansi --no-progress"
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: shivammathur/setup-php@v2
with:
php-version: ${{vars.PHP_VERSION}}
- run: composer install --prefer-dist --no-progress
- name: Run ecs check
run: |
vendor/bin/ecs --memory-limit=1G --no-progress-bar
rector:
name: Rector dry-run
runs-on: ubuntu-latest
env:
DEFAULT_COMPOSER_FLAGS: "--no-interaction --no-ansi --no-progress"
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: shivammathur/setup-php@v2
with:
php-version: ${{vars.PHP_VERSION}}
- run: composer install --prefer-dist --no-progress
- name: Run rector --dry-run
run: |
vendor/bin/rector --memory-limit=1G --no-progress-bar --dry-run
phpstan:
name: PHPStan
runs-on: ubuntu-latest
env:
DEFAULT_COMPOSER_FLAGS: "--no-interaction --no-ansi --no-progress"
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: shivammathur/setup-php@v2
with:
php-version: ${{vars.PHP_VERSION}}
- run: composer install --prefer-dist --no-progress
- name: Run phpstan
run: |
vendor/bin/phpstan --memory-limit=1G
9 changes: 4 additions & 5 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
includes:
- vendor/craftcms/phpstan/phpstan.neon
- vendor/craftcms/phpstan/phpstan.neon

parameters:
paths:
- src
level: 5

paths:
- src
level: 9
116 changes: 8 additions & 108 deletions src/EntryTypeRules.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
<?php
/**
* Entry Type Rules plugin for Craft CMS 5.x
*
* A Craft plugin that allows you to set rules on number of entry types in a Craft section and/or limit who can
* include entry type entries based on their user group.
*
* @link https://fostercommerce.com
* @copyright Copyright (c) 2022 Foster Commerce
*/

namespace fostercommerce\entrytyperules;

Expand All @@ -16,132 +7,48 @@
use craft\base\Model;

use craft\base\Plugin;
use craft\elements\Entry;
use craft\events\DefineHtmlEvent;
use craft\services\Plugins;
use craft\web\View;
use fostercommerce\entrytyperules\assetbundles\entrytyperules\EntryTypeRulesAsset;
use fostercommerce\entrytyperules\models\Settings;
use fostercommerce\entrytyperules\services\EntryTypeRulesService as EntryTypeRulesServiceService;
use yii\base\Event;
use yii\base\InvalidConfigException;

/**
* Craft plugins are very much like little applications in and of themselves. We’ve made
* it as simple as we can, but the training wheels are off. A little prior knowledge is
* going to be required to write a plugin.
*
* For the purposes of the plugin docs, we’re going to assume that you know PHP and SQL,
* as well as some semi-advanced concepts like object-oriented programming and PHP namespaces.
*
* https://docs.craftcms.com/v3/extend/
*
* @author Foster Commerce
* @package EntryTypeRules
* @since 1.0.0
*
* @property EntryTypeRulesServiceService $entryTypeRulesService
* @property Settings $settings
* @method Settings getSettings()
*/
class EntryTypeRules extends Plugin
{
// Static Properties
// =========================================================================

/**
* Static property that is an instance of this plugin class so that it can be accessed via
* EntryTypeRules::$plugin
*
* @var EntryTypeRules
*/
public static $plugin;

// Public Properties
// =========================================================================

/**
* To execute your plugin’s migrations, you’ll need to increase its schema version.
*/
public string $schemaVersion = '1.0.0';

/**
* Set to `true` if the plugin should have a settings view in the control panel.
*/
public bool $hasCpSettings = true;

/**
* Set to `true` if the plugin should have its own section (main nav item) in the control panel.
*/
public bool $hasCpSection = false;

// Public Methods
// =========================================================================

/**
* Set our $plugin static property to this class so that it can be accessed via
* EntryTypeRules::$plugin
*
* Called after the plugin class is instantiated; do any one-time initialization
* here such as hooks and events.
*
* If you have a '/vendor/autoload.php' file, it will be loaded for you automatically;
* you do not need to load it in your init() method.
* @throws InvalidConfigException
*/
public function init(): void
{
parent::init();
self::$plugin = $this;

Craft::setAlias('@plugin', $this->getBasePath());

Craft::$app->getView()->registerAssetBundle(EntryTypeRulesAsset::class, View::POS_END);
Craft::$app->getView()->registerJs('new Craft.EntryTypeRules();', View::POS_READY);

// Let's put our own data regarding the section into the entry edit page in the CP
Craft::$app->view->hook('cp.entries.edit.meta', function (array &$context): string {
$injectedHtml = '';
$entry = $context['entry'];
if ($entry !== null && $entry->section->type !== 'single') {
// Create the elements we are going to inject
$injectedHtml = '<div id="entryTypeRulesSectionId" data-value="' . $entry->section->id . '"></div>';
}

return $injectedHtml;
});

// Watch the template rendering to see if we are in an entry edit form
Event::on(
View::class,
View::EVENT_AFTER_RENDER_TEMPLATE,
function (): void {
// Check the segments to see if we are in an entry edit form, if so register the entry bundle
if (
Craft::$app->getRequest()->isCpRequest &&
Craft::$app->getRequest()->getSegment(1) === 'entries' &&
Craft::$app->getRequest()->getSegment(3) !== ''
) {
// Inject our asset bundle, and start it up with some JS
Craft::$app->getView()->registerAssetBundle(EntryTypeRulesAsset::class, View::POS_END);
Craft::$app->getView()->registerJs('new Craft.EntryTypeRules();', View::POS_READY);
}
}
);

// Watch the slide out element editor window to see if we are editing an entry in the slide-out
//
Event::on(
Element::class,
Element::EVENT_DEFINE_SIDEBAR_HTML,
function (DefineHtmlEvent $event): void {
$element = $event->sender;
// If the element is a Craft Entry
if (is_a($element, 'craft\elements\Entry')) {
if ($element instanceof Entry) {
// Get the section ID and section type the entry belongs to
$sectionId = $element->section->id;
$sectionId = $element->section?->id;
// If it is not a single, inject out fields and register the slideout bundle
if ($element->section->type !== 'single') {
if ($element->section?->type !== 'single') {
// Get the views namespace
$viewNamespace = Craft::$app->getView()->namespace;
// Create the elements we are going to inject (Note: the ID's will automatically be namespaced for the view by Craft)
$injectedHtml = '<div id="entryTypeRulesSectionId" data-value="' . $sectionId . '"></div>';
$injectedHtml = "<input type=\"hidden\" id=\"entryTypeRulesSectionId\" value=\"{$sectionId}\"/>";
// Inject the elements, our asset bundle, and start it up with some JS
$event->html = $injectedHtml . $event->html;
Craft::$app->getView()->registerAssetBundle(EntryTypeRulesAsset::class, View::POS_END);
Expand Down Expand Up @@ -202,13 +109,6 @@ public function getSettingsResponse(): mixed
);
}


// Protected Methods
// =========================================================================

/**
* Creates and returns the model used to store the plugin’s settings.
*/
protected function createSettingsModel(): ?Model
{
return new Settings();
Expand Down
24 changes: 18 additions & 6 deletions src/assetbundles/entrytyperules/dist/js/EntryTypeRules.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Craft.EntryTypeRules = Garnish.Base.extend({
sectionId: null,
selectedType: null,
typeButton: null,
createButton: null,
elementId: false,

init: function(namespace) {
const self = this;
Expand All @@ -12,15 +14,22 @@ Craft.EntryTypeRules = Garnish.Base.extend({

// If we have a namespace it means we are in a HUD or Craft Slide-out, if not we are in a regular entry edit page
if (self.namespace) {
self.sectionId = document.getElementById(self.namespace + '-entryTypeRulesSectionId')?.dataset?.value;
let sectionIdElement = document.getElementById(self.namespace + '-entryTypeRulesSectionId');
self.sectionId = sectionIdElement?.value;
self.selectedType = document.getElementById(self.namespace + '-entryType-input');
self.typeButton = jQuery('#' + self.namespace + '-entryType-button').data('menubtn');
self.elementId = document.getElementsByName(self.namespace + '[elementId]')[0]?.value;
self.createButton = sectionIdElement?.closest('form').querySelector('button[type="submit"]');
} else {
self.sectionId = document.getElementById('entryTypeRulesSectionId')?.dataset?.value;
let sectionIdElement = document.getElementById('entryTypeRulesSectionId');
self.sectionId = sectionIdElement?.value;
self.selectedType = document.getElementById('entryType-input');
self.typeButton = jQuery('#entryType-button').data('menubtn');
self.createButton = sectionIdElement?.closest('form').querySelector('button[type="submit"]')?.parentElement;
self.elementId = document.getElementsByName('elementId')[0]?.value;
}

// sectionId will be null if we are not editing an entry
if (self.sectionId === null || self.selectedType === null) {
return;
}
Expand All @@ -33,7 +42,9 @@ Craft.EntryTypeRules = Garnish.Base.extend({
lockEntryTypes: function() {
const self = this;

fetch("/actions/entry-type-rules/default?sectionId=" + parseInt(self.sectionId, 10))
let sectionId = parseInt(self.sectionId, 10);
let elementId = parseInt(self.elementId, 10);
fetch(`/actions/entry-type-rules/default?entryId=${elementId}&sectionId=${sectionId}`)
.then(response => response.json())
.then(response => {
if (!response.lockedEntryTypes) {
Expand All @@ -58,9 +69,9 @@ Craft.EntryTypeRules = Garnish.Base.extend({

// Find out if we are on the new entry (URL param "fresh" is present)
const urlParams = new URLSearchParams(window.location.search);
const canChangeSelection = !self.namespace && urlParams.has('fresh');

if (canChangeSelection) {
// We only want to prevent folks from changing the type if the entry is new
if (! response.entryExists) {
// If there is an available option
if (firstEnabledOption !== null) {
// And if the currently selected type is locked
Expand All @@ -70,8 +81,9 @@ Craft.EntryTypeRules = Garnish.Base.extend({
self.typeButton.onOptionSelect(firstEnabledOption);
}
} else {
// TODO we need to disable saving at this point because the user cannot select a type.
self.typeButton.disable();
self.createButton.disabled = true;
self.createButton.classList.add('disabled');
}
}
});
Expand Down
29 changes: 22 additions & 7 deletions src/controllers/DefaultController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@

use Craft;

use craft\elements\Entry;
use craft\web\Application;
use craft\web\Controller;
use fostercommerce\entrytyperules\services\EntryTypeRulesService;
use craft\web\User;
use fostercommerce\entrytyperules\EntryTypeRules;

/**
* Default Controller
Expand Down Expand Up @@ -48,23 +51,35 @@ class DefaultController extends Controller
/**
* Handle a request going to our plugin's index action URL,
* e.g.: actions/entry-type-rules/default
*
* @throws \Throwable
*/
public function actionIndex(): mixed
{
/** @var Application $app */
$app = Craft::$app;
// Get the section ID from a query param we will include in the ajax request
/** @var int $sectionId */
$sectionId = $app->request->getQueryParam('sectionId');
$entryId = $app->request->getQueryParam('entryId');

$result = [
'sectionId' => 0,
'lockedEntryTypes' => [],
'entryExists' => Entry::find()->id($entryId)->exists(),
];

// Get the section ID from a query param we will include in the ajax request
$sectionId = Craft::$app->request->getQueryParam('sectionId');

if ($sectionId) {
$result['sectionId'] = $sectionId;
$result['lockedEntryTypes'] = EntryTypeRulesService::instance()->getLockedEntryTypes($sectionId);
return json_encode($result);

/** @var User $user */
$user = Craft::$app->getUser();

$result['lockedEntryTypes'] = EntryTypeRules::getInstance()
?->entryTypeRulesService
->getLockedEntryTypes($sectionId, $user);
}

return $result;
return $this->asJson($result);
}
}
Loading

0 comments on commit 567aac8

Please sign in to comment.