diff --git a/.gitattributes b/.gitattributes index 36c08e2..2bcebd8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,7 +2,6 @@ /.gitattributes export-ignore /.github/ export-ignore /.gitignore export-ignore -/codeception.yml export-ignore /ecs.php export-ignore /phpstan.neon export-ignore diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml new file mode 100644 index 0000000..fc50801 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -0,0 +1,42 @@ +name: Bug Report +description: Create a bug report for this plugin. +labels: + - bug +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to submit a bug report! To ensure this hasn’t already been reported, please first search existing issues. + + To rule out that this isn’t a setup or configuration issue, please read the docs. + + If you still believe you’ve found a bug, please provide a clear and concise description, including: + - What is happening and what you expected to happen. + - Steps to reproduce the issue. + - Screenshots, if applicable. + - type: textarea + id: body + attributes: + label: Bug Report + description: Please provide a clear and concise description of the bug. + validations: + required: true + - type: input + id: pluginVersion + attributes: + label: Plugin Version + description: Provide the plugin version that this relates to, ideally the latest version. + validations: + required: true + - type: input + id: craftVersion + attributes: + label: Craft CMS Version + description: Provide the version of Craft that is installed. + validations: + required: true + - type: input + id: phpVersion + attributes: + label: PHP Version + description: Provide the PHP version, if applicable. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 2a45da2..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: Bug report -about: Create a bug report for this plugin. -title: '' -labels: bug -assignees: '' - ---- - -Please provide a clear and concise description of what the bug is, including: -- Steps to reproduce the issue. -- A clear and concise description of what you expected to happen. -- If applicable, add screenshots to help explain your problem. -- The plugin and Craft version numbers. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3ba13e0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature-request.yaml b/.github/ISSUE_TEMPLATE/feature-request.yaml new file mode 100644 index 0000000..12c2c68 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yaml @@ -0,0 +1,25 @@ +name: Feature Request +description: Suggest a new feature for this plugin. +labels: + - enhancement +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to submit a feature request! To ensure this isn’t already on our radar, please first search existing issues. + + If you still believe you have a new suggestion, please provide a clear and concise description, including: + - What problem you believe your feature request can solve. + - Any alternative solutions or features you have already considered. + - type: textarea + id: body + attributes: + label: Feature Request + description: Please provide a clear and concise suggestion for a feature. + validations: + required: true + - type: input + id: pluginVersion + attributes: + label: Plugin Version + description: Provide the plugin version that this relates to, ideally the latest version. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bd44c9d..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Feature request -about: Suggest a feature for this plugin. -title: '' -labels: enhancement -assignees: '' - ---- - -Please provide a clear and concise description of your feature request, including: -- What the problem is and what you would like to have happen. -- Any alternative solutions or features you have considered. diff --git a/.github/ISSUE_TEMPLATE/support-request.md b/.github/ISSUE_TEMPLATE/support-request.md deleted file mode 100644 index 5a675ed..0000000 --- a/.github/ISSUE_TEMPLATE/support-request.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Support request -about: Ask a question about this plugin. -title: '' -labels: question -assignees: '' - ---- - -Please provide a clear and concise question. We are diligent about documentation, so please check whether your question is answered by the plugin docs before submitting. diff --git a/.github/ISSUE_TEMPLATE/support-request.yaml b/.github/ISSUE_TEMPLATE/support-request.yaml new file mode 100644 index 0000000..688f303 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/support-request.yaml @@ -0,0 +1,23 @@ +name: Support Request +description: Ask a question about this plugin. +labels: + - question +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to submit a support request! To ensure your question hasn’t already been asked and answered, please first search existing issues. + + If your question is still unanswered, please provide a clear and concise description. Note that we are diligent about documentation, so please check whether your question is answered by the plugin docs before submitting. + - type: textarea + id: body + attributes: + label: Support Request + description: Please provide a clear and concise question. + validations: + required: true + - type: input + id: pluginVersion + attributes: + label: Plugin Version + description: Provide the plugin version that this relates to, ideally the latest version. diff --git a/.github/workflows/code-analysis.yaml b/.github/workflows/code-analysis.yaml new file mode 100644 index 0000000..043d81d --- /dev/null +++ b/.github/workflows/code-analysis.yaml @@ -0,0 +1,41 @@ +name: Code Analysis + +on: + pull_request: null + push: + branches: + - develop + - v3 + workflow_dispatch: +permissions: + contents: read +jobs: + code_analysis: + strategy: + fail-fast: false + matrix: + actions: + - name: 'PHPStan' + run: composer phpstan + - name: 'Coding Standards' + run: composer fix-cs + name: ${{ matrix.actions.name }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: /tmp/composer-cache + key: ${{ runner.os }}-${{ hashFiles('**/composer.lock') }} + - name: Setup PHP + id: setup-php + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + extensions: 'ctype,curl,dom,iconv,imagick,intl,json,mbstring,openssl,pcre,pdo,reflection,spl,zip' + ini-values: post_max_size=256M, max_execution_time=180, memory_limit=512M + tools: composer:v2 + - name: Install Composer dependencies + run: composer install --no-interaction --no-ansi --no-progress + - run: ${{ matrix.actions.run }} diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 0000000..8e33492 --- /dev/null +++ b/.github/workflows/create-release.yml @@ -0,0 +1,21 @@ +name: Create Release +run-name: Create release for ${{ github.event.client_payload.version }} + +on: + repository_dispatch: + types: + - craftcms/new-release + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: ncipollo/release-action@v1 + with: + body: ${{ github.event.client_payload.notes }} + makeLatest: ${{ github.event.client_payload.latest }} + name: ${{ github.event.client_payload.version }} + prerelease: ${{ github.event.client_payload.prerelease }} + tag: ${{ github.event.client_payload.tag }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e7ad9d..7cd8923 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,11 @@ # Release Notes for Elements Panel -## 2.0.0 - 2022-05-04 -- Added compatibility with Craft 4. +## 3.0.0-beta.1 - 2024-03-21 -## 1.1.1 - 2020-10-30 ### Added -- Added a field handle column to the eager-loading panel. -## 1.1.0 - 2020-06-29 -### Added -- Added support for eager-loading matrix fields. -- Added support for eager-loading relation fields within matrix fields ([#3](https://github.com/putyourlightson/craft-elements-panel/issues/3)). +- Added compatibility with Craft 5. + +### Changed -## 1.0.0 - 2020-06-11 -- Initial release. +- Changed the license from MIT to a proprietary license. diff --git a/LICENSE.md b/LICENSE.md index 11f2e96..e93dbf4 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,40 @@ Copyright © PutYourLightsOn -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted to any person obtaining a copy of this software +(the “Software”) to use, copy, modify, merge, publish and/or distribute copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +1. **Don’t plagiarize.** The above copyright notice and this license shall be + included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +2. **Don’t use the same license on more than one project.** Each licensed copy + of the Software shall be actively installed in no more than one production + environment at a time. + +3. **Don’t mess with the licensing features.** Software features related to + licensing shall not be altered or circumvented in any way, including (but + not limited to) license validation, payment prompts, feature restrictions, + and update eligibility. + +4. **Pay up.** Payment shall be made immediately upon receipt of any notice, + prompt, reminder, or other message indicating that a payment is owed. + +5. **Follow the law.** All use of the Software shall not violate any applicable + law or regulation, nor infringe the rights of any other person or entity. + +Failure to comply with the foregoing conditions will automatically and +immediately result in termination of the permission granted hereby. This +license does not include any right to receive updates to the Software or +technical support. Licensees bear all risk related to the quality and +performance of the Software and any modifications made or obtained to it, +including liability for actual and consequential harm, such as loss or +corruption of data, and any necessary service, repair, or correction. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER +LIABILITY, INCLUDING SPECIAL, INCIDENTAL AND CONSEQUENTIAL DAMAGES, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 5224ae2..6a711b2 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@ Learn more and read the documentation at [putyourlightson.com/plugins/elements-p ## License -This plugin is licensed for free under the MIT License. +This plugin requires a free commercial license available through the [Craft Plugin Store](https://plugins.craftcms.com/elements-panel). ## Requirements -This plugin requires [Craft CMS](https://craftcms.com/) 3.0.0 or later, or 4.0.0 or later. +This plugin requires [Craft CMS](https://craftcms.com/) 3.0.0 or later, or 4.0.0 or later, or 5.0.0 or later. ## Installation diff --git a/composer.json b/composer.json index ecf549c..caa230f 100644 --- a/composer.json +++ b/composer.json @@ -1,30 +1,48 @@ { - "name": "putyourlightson/craft-elements-panel", - "description": "Adds an Elements and an Eager-Loading panel to the debug toolbar.", - "version": "2.0.0", - "type": "craft-plugin", - "license": "mit", - "require": { - "php": "^8.0.2", - "craftcms/cms": "^4.0.0" - }, - "autoload": { - "psr-4": { - "putyourlightson\\elementspanel\\": "src/" - } - }, - "support": { - "docs": "https://putyourlightson.com/plugins/elements-panel", - "source": "https://github.com/putyourlightson/craft-elements-panel", - "issues": "https://github.com/putyourlightson/craft-elements-panel/issues" - }, - "extra": { - "name": "Elements Panel", - "handle": "elements-panel", - "developer": "PutYourLightsOn", - "developerUrl": "https://putyourlightson.com/", - "documentationUrl": "https://putyourlightson.com/plugins/elements-panel", - "changelogUrl": "https://raw.githubusercontent.com/putyourlightson/craft-elements-panel/v2/CHANGELOG.md", - "class": "putyourlightson\\elementspanel\\ElementsPanel" + "name": "putyourlightson/craft-elements-panel", + "description": "Adds an Elements and an Eager-Loading panel to the debug toolbar.", + "version": "3.0.0-beta.1", + "type": "craft-plugin", + "license": "proprietary", + "require": { + "php": "^8.2", + "craftcms/cms": "^5.0.0-beta.1" + }, + "require-dev": { + "craftcms/ecs": "dev-main", + "craftcms/phpstan": "dev-main" + }, + "autoload": { + "psr-4": { + "putyourlightson\\elementspanel\\": "src/" } + }, + "scripts": { + "phpstan": "phpstan --ansi --memory-limit=1G", + "check-cs": "ecs check --ansi", + "fix-cs": "ecs check --fix --ansi" + }, + "config": { + "allow-plugins": { + "craftcms/plugin-installer": true, + "pestphp/pest-plugin": true, + "yiisoft/yii2-composer": true + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "support": { + "docs": "https://putyourlightson.com/plugins/elements-panel", + "source": "https://github.com/putyourlightson/craft-elements-panel", + "issues": "https://github.com/putyourlightson/craft-elements-panel/issues" + }, + "extra": { + "name": "Elements Panel", + "handle": "elements-panel", + "developer": "PutYourLightsOn", + "developerUrl": "https://putyourlightson.com/", + "documentationUrl": "https://putyourlightson.com/plugins/elements-panel", + "changelogUrl": "https://raw.githubusercontent.com/putyourlightson/craft-elements-panel/v3/CHANGELOG.md", + "class": "putyourlightson\\elementspanel\\ElementsPanel" + } } diff --git a/ecs.php b/ecs.php index ff09fdd..85860c2 100644 --- a/ecs.php +++ b/ecs.php @@ -4,11 +4,10 @@ use Symplify\EasyCodingStandard\Config\ECSConfig; return static function(ECSConfig $ecsConfig): void { - $ecsConfig->parallel(); $ecsConfig->paths([ __DIR__ . '/src', __FILE__, ]); - + $ecsConfig->parallel(); $ecsConfig->sets([SetList::CRAFT_CMS_4]); }; diff --git a/src/debug/EagerLoadingPanel.php b/src/debug/EagerLoadingPanel.php index 87a13da..1d950a3 100644 --- a/src/debug/EagerLoadingPanel.php +++ b/src/debug/EagerLoadingPanel.php @@ -8,7 +8,6 @@ use Craft; use craft\base\Field; use craft\elements\db\ElementQuery; -use craft\elements\db\MatrixBlockQuery; use craft\events\CancelableEvent; use yii\base\Event; use yii\debug\Panel; @@ -18,12 +17,12 @@ class EagerLoadingPanel extends Panel /** * @var array */ - private array $_queries = []; + private array $queries = []; /** * @var string */ - private string $_viewPath = '@putyourlightson/elementspanel/views/eager-loading/'; + private string $viewPath = '@putyourlightson/elementspanel/views/eager-loading/'; /** * @inheritdoc @@ -33,15 +32,10 @@ public function init(): void parent::init(); Event::on(ElementQuery::class, ElementQuery::EVENT_BEFORE_PREPARE, - function (CancelableEvent $event) { + function(CancelableEvent $event) { /** @var ElementQuery $elementQuery */ $elementQuery = $event->sender; - - if ($elementQuery instanceof MatrixBlockQuery) { - $this->_checkMatrixRelations($elementQuery); - } else { - $this->_checkBaseRelations($elementQuery); - } + $this->checkElementQuery($elementQuery); } ); } @@ -59,7 +53,7 @@ public function getName(): string */ public function getSummary(): string { - return Craft::$app->getView()->render($this->_viewPath . 'summary', ['panel' => $this]); + return Craft::$app->getView()->render($this->viewPath . 'summary', ['panel' => $this]); } /** @@ -67,7 +61,7 @@ public function getSummary(): string */ public function getDetail(): string { - return Craft::$app->getView()->render($this->_viewPath . 'detail', ['panel' => $this]); + return Craft::$app->getView()->render($this->viewPath . 'detail', ['panel' => $this]); } /** @@ -79,10 +73,10 @@ public function save(): array $queries = []; $fields = Craft::$app->getFields(); - foreach ($this->_queries as $fieldId => $sourceIds) { + foreach ($this->queries as $fieldId => $sourceIds) { $duplicates = 0; - foreach ($sourceIds as $sourceId => $count) { + foreach ($sourceIds as $count) { $total++; if ($count > 1) { @@ -108,65 +102,47 @@ public function save(): array } /** - * Checks base relations. + * Checks for opportunities to eager-load elements. + * Based on the `HintsService::checkElementQuery` method in Blitz, with permission. * - * @see BaseRelationField::normalizeValue + * @see \putyourlightson\blitz\services\HintsService::checkElementQuery */ - private function _checkBaseRelations(ElementQuery $elementQuery) + private function checkElementQuery(ElementQuery $elementQuery): void { - $join = $elementQuery->join[0] ?? null; - - if ($join === null) { + if ($elementQuery->wasEagerLoaded() + || $elementQuery->eagerLoadHandle === null + || $elementQuery->id !== null + ) { return; } - $relationTypes = [ - ['relations' => '{{%relations}}'], - '{{%relations}} relations', - ]; - - if ($join[0] == 'INNER JOIN' && in_array($join[1], $relationTypes)) { - $fieldId = $join[2][2]['relations.fieldId'] ?? null; - $sourceId = $join[2][2]['relations.sourceId'] ?? null; - - if ($fieldId === null || $sourceId === null) { - return; - } - - $this->_addQuery($fieldId, $sourceId); + /** @see ElementQuery::wasEagerLoaded() */ + $planHandle = $elementQuery->eagerLoadHandle; + if (str_contains($planHandle, ':')) { + $planHandle = explode(':', $planHandle, 2)[1]; } - } - /** - * Checks matrix relations. - * - * @see MatrixBlockQuery::beforePrepare - */ - private function _checkMatrixRelations(MatrixBlockQuery $elementQuery) - { - if (empty($elementQuery->fieldId) || empty($elementQuery->ownerId)) { + $field = Craft::$app->getFields()->getFieldByHandle($planHandle); + if ($field === null) { return; } - $fieldId = is_array($elementQuery->fieldId) ? $elementQuery->fieldId[0] : $elementQuery->fieldId; - $ownerId = is_array($elementQuery->ownerId) ? $elementQuery->ownerId[0] : $elementQuery->ownerId; - - $this->_addQuery($fieldId, $ownerId); + $this->addQuery($field->id, $elementQuery->eagerLoadSourceElement->id); } /** * Adds a query that could be eager-loaded. */ - private function _addQuery(int $fieldId, int $sourceId) + private function addQuery(int $fieldId, int $sourceId): void { - if (empty($this->_queries[$fieldId])) { - $this->_queries[$fieldId] = []; + if (empty($this->queries[$fieldId])) { + $this->queries[$fieldId] = []; } - if (empty($this->_queries[$fieldId][$sourceId])) { - $this->_queries[$fieldId][$sourceId] = 0; + if (empty($this->queries[$fieldId][$sourceId])) { + $this->queries[$fieldId][$sourceId] = 0; } - $this->_queries[$fieldId][$sourceId]++; + $this->queries[$fieldId][$sourceId]++; } } diff --git a/src/debug/ElementPanel.php b/src/debug/ElementPanel.php index b8a8a25..cf6b76e 100644 --- a/src/debug/ElementPanel.php +++ b/src/debug/ElementPanel.php @@ -17,12 +17,12 @@ class ElementPanel extends Panel /** * @var array */ - private array $_elements = []; + private array $elements = []; /** * @var string */ - private string $_viewPath = '@vendor/putyourlightson/craft-elements-panel/src/views/element/'; + private string $viewPath = '@vendor/putyourlightson/craft-elements-panel/src/views/element/'; /** * @inheritdoc @@ -33,7 +33,7 @@ public function init(): void Event::on(ElementQuery::class, ElementQuery::EVENT_AFTER_POPULATE_ELEMENT, function(PopulateElementEvent $event) { - $this->_addElement($event->element); + $this->addElement($event->element); } ); } @@ -51,7 +51,7 @@ public function getName(): string */ public function getSummary(): string { - return Craft::$app->getView()->render($this->_viewPath . 'summary', ['panel' => $this]); + return Craft::$app->getView()->render($this->viewPath . 'summary', ['panel' => $this]); } /** @@ -59,7 +59,7 @@ public function getSummary(): string */ public function getDetail(): string { - return Craft::$app->getView()->render($this->_viewPath . 'detail', ['panel' => $this]); + return Craft::$app->getView()->render($this->viewPath . 'detail', ['panel' => $this]); } /** @@ -70,10 +70,10 @@ public function save(): array $total = 0; $elements = []; - foreach ($this->_elements as $elementType => $elementIds) { + foreach ($this->elements as $elementType => $elementIds) { $duplicates = 0; - foreach ($elementIds as $elementId => $count) { + foreach ($elementIds as $count) { $total++; if ($count > 1) { @@ -97,18 +97,18 @@ public function save(): array /** * Adds populated element count. */ - private function _addElement(ElementInterface $element) + private function addElement(ElementInterface $element): void { $elementType = get_class($element); - if (empty($this->_elements[$elementType])) { - $this->_elements[$elementType] = []; + if (empty($this->elements[$elementType])) { + $this->elements[$elementType] = []; } - if (empty($this->_elements[$elementType][$element->getId()])) { - $this->_elements[$elementType][$element->getId()] = 0; + if (empty($this->elements[$elementType][$element->getId()])) { + $this->elements[$elementType][$element->getId()] = 0; } - $this->_elements[$elementType][$element->getId()]++; + $this->elements[$elementType][$element->getId()]++; } } diff --git a/src/views/eager-loading/detail.php b/src/views/eager-loading/detail.php index 70982b2..2e63f4b 100644 --- a/src/views/eager-loading/detail.php +++ b/src/views/eager-loading/detail.php @@ -2,18 +2,21 @@ /** * @var \putyourlightson\elementspanel\debug\ElementPanel $panel */ + ?>
- = Craft::t('elements-panel', 'No opportunities for eager-loading elements were detected.') ?> + = Craft::t('elements-panel', 'No opportunities for eager-loading elements were detected.') ?>
- +- = Craft::t('elements-panel', 'Opportunities for eager-loading elements were detected on this page.') ?> + = Craft::t('elements-panel', 'Opportunities for eager-loading elements were detected on this page.') ?>