diff --git a/.github/workflows/diagnostics.yml b/.github/workflows/diagnostics.yml index 029084a..92fa04a 100644 --- a/.github/workflows/diagnostics.yml +++ b/.github/workflows/diagnostics.yml @@ -14,11 +14,6 @@ jobs: fail-fast: false matrix: include: - - name: '8.2 prefer-lowest' - php: '8.2' - phpcq_install: 'update' - phpcq_flags: '--exit-0' - composer_install: 'update --prefer-lowest' - name: '8.2' php: '8.2' phpcq_install: 'update' @@ -34,6 +29,11 @@ jobs: phpcq_install: 'update' phpcq_flags: '' composer_install: 'update' + - name: '8.5' + php: '8.5' + phpcq_install: 'update' + phpcq_flags: '' + composer_install: 'update' steps: - name: PHP ${{ matrix.php }} Pull source uses: actions/checkout@v6 @@ -77,7 +77,7 @@ jobs: run: ./vendor/bin/phpcq run -v -o github-action -o default ${{ matrix.phpcq_flags }} - name: PHP ${{ matrix.php }} Upload build directory to artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 if: ${{ success() }} || ${{ failure() }} with: name: phpcq-builds-php-${{ matrix.php }} diff --git a/.phpcq.lock b/.phpcq.lock index 86d60c3..2d695cc 100644 --- a/.phpcq.lock +++ b/.phpcq.lock @@ -1 +1 @@ -{"plugins":{"doctrine-coding-standard":{"api-version":"1.0.0","version":"1.0.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/doctrine-coding-standard/doctrine-coding-standard-1.0.0.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0","ext-dom":"*"},"composer":{"doctrine/coding-standard":"^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0"}},"checksum":{"type":"sha-512","value":"00fab498a6575bf07930e078fd616c0481714570bc1c61ebae4fa277d64c0cb28575aba9190c9731c7bda9f97f57c113516e1eb2920c3b9b7b295e0078be3159"},"tools":{},"composerLock":"{\n \"_readme\": [\n \"This file locks the dependencies of your project to a known state\",\n \"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies\",\n \"This file is @generated automatically\"\n ],\n \"content-hash\": \"e6054cafc39eba4b0e4ca4ca45683799\",\n \"packages\": [\n {\n \"name\": \"dealerdirect/phpcodesniffer-composer-installer\",\n \"version\": \"v1.2.0\",\n \"source\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/PHPCSStandards/composer-installer.git\",\n \"reference\": \"845eb62303d2ca9b289ef216356568ccc075ffd1\"\n },\n \"dist\": {\n \"type\": \"zip\",\n \"url\": \"https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/845eb62303d2ca9b289ef216356568ccc075ffd1\",\n \"reference\": \"845eb62303d2ca9b289ef216356568ccc075ffd1\",\n \"shasum\": \"\"\n },\n \"require\": {\n \"composer-plugin-api\": \"^2.2\",\n \"php\": \">=5.4\",\n \"squizlabs/php_codesniffer\": \"^3.1.0 || ^4.0\"\n },\n \"require-dev\": {\n \"composer/composer\": \"^2.2\",\n \"ext-json\": \"*\",\n \"ext-zip\": \"*\",\n \"php-parallel-lint/php-parallel-lint\": \"^1.4.0\",\n \"phpcompatibility/php-compatibility\": \"^9.0 || ^10.0.0@dev\",\n \"yoast/phpunit-polyfills\": \"^1.0\"\n },\n \"type\": \"composer-plugin\",\n \"extra\": {\n \"class\": \"PHPCSStandards\\\\Composer\\\\Plugin\\\\Installers\\\\PHPCodeSniffer\\\\Plugin\"\n },\n \"autoload\": {\n \"psr-4\": {\n \"PHPCSStandards\\\\Composer\\\\Plugin\\\\Installers\\\\PHPCodeSniffer\\\\\": \"src/\"\n }\n },\n \"notification-url\": \"https://packagist.org/downloads/\",\n \"license\": [\n \"MIT\"\n ],\n \"authors\": [\n {\n \"name\": \"Franck Nijhof\",\n \"email\": \"opensource@frenck.dev\",\n \"homepage\": \"https://frenck.dev\",\n \"role\": \"Open source developer\"\n },\n {\n \"name\": \"Contributors\",\n \"homepage\": \"https://github.com/PHPCSStandards/composer-installer/graphs/contributors\"\n }\n ],\n \"description\": \"PHP_CodeSniffer Standards Composer Installer Plugin\",\n \"keywords\": [\n \"PHPCodeSniffer\",\n \"PHP_CodeSniffer\",\n \"code quality\",\n \"codesniffer\",\n \"composer\",\n \"installer\",\n \"phpcbf\",\n \"phpcs\",\n \"plugin\",\n \"qa\",\n \"quality\",\n \"standard\",\n \"standards\",\n \"style guide\",\n \"stylecheck\",\n \"tests\"\n ],\n \"support\": {\n \"issues\": \"https://github.com/PHPCSStandards/composer-installer/issues\",\n \"security\": \"https://github.com/PHPCSStandards/composer-installer/security/policy\",\n \"source\": \"https://github.com/PHPCSStandards/composer-installer\"\n },\n \"funding\": [\n {\n \"url\": \"https://github.com/PHPCSStandards\",\n \"type\": \"github\"\n },\n {\n \"url\": \"https://github.com/jrfnl\",\n \"type\": \"github\"\n },\n {\n \"url\": \"https://opencollective.com/php_codesniffer\",\n \"type\": \"open_collective\"\n },\n {\n \"url\": \"https://thanks.dev/u/gh/phpcsstandards\",\n \"type\": \"thanks_dev\"\n }\n ],\n \"time\": \"2025-11-11T04:32:07+00:00\"\n },\n {\n \"name\": \"doctrine/coding-standard\",\n \"version\": \"13.0.1\",\n \"source\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/doctrine/coding-standard.git\",\n \"reference\": \"0affd62169186f32de725ca612e6129e81186a21\"\n },\n \"dist\": {\n \"type\": \"zip\",\n \"url\": \"https://api.github.com/repos/doctrine/coding-standard/zipball/0affd62169186f32de725ca612e6129e81186a21\",\n \"reference\": \"0affd62169186f32de725ca612e6129e81186a21\",\n \"shasum\": \"\"\n },\n \"require\": {\n \"dealerdirect/phpcodesniffer-composer-installer\": \"^0.6.2 || ^0.7 || ^1.0.0\",\n \"php\": \"^7.4 || ^8.0\",\n \"slevomat/coding-standard\": \"^8.16\",\n \"squizlabs/php_codesniffer\": \"^3.7\"\n },\n \"type\": \"phpcodesniffer-standard\",\n \"notification-url\": \"https://packagist.org/downloads/\",\n \"license\": [\n \"MIT\"\n ],\n \"authors\": [\n {\n \"name\": \"Benjamin Eberlei\",\n \"email\": \"kontakt@beberlei.de\"\n },\n {\n \"name\": \"Steve Müller\",\n \"email\": \"st.mueller@dzh-online.de\"\n }\n ],\n \"description\": \"The Doctrine Coding Standard is a set of PHPCS rules applied to all Doctrine projects.\",\n \"homepage\": \"https://www.doctrine-project.org/projects/coding-standard.html\",\n \"keywords\": [\n \"checks\",\n \"code\",\n \"coding\",\n \"cs\",\n \"dev\",\n \"doctrine\",\n \"rules\",\n \"sniffer\",\n \"sniffs\",\n \"standard\",\n \"style\"\n ],\n \"support\": {\n \"issues\": \"https://github.com/doctrine/coding-standard/issues\",\n \"source\": \"https://github.com/doctrine/coding-standard/tree/13.0.1\"\n },\n \"time\": \"2025-05-14T10:54:19+00:00\"\n },\n {\n \"name\": \"phpstan/phpdoc-parser\",\n \"version\": \"2.3.0\",\n \"source\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/phpstan/phpdoc-parser.git\",\n \"reference\": \"1e0cd5370df5dd2e556a36b9c62f62e555870495\"\n },\n \"dist\": {\n \"type\": \"zip\",\n \"url\": \"https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495\",\n \"reference\": \"1e0cd5370df5dd2e556a36b9c62f62e555870495\",\n \"shasum\": \"\"\n },\n \"require\": {\n \"php\": \"^7.4 || ^8.0\"\n },\n \"require-dev\": {\n \"doctrine/annotations\": \"^2.0\",\n \"nikic/php-parser\": \"^5.3.0\",\n \"php-parallel-lint/php-parallel-lint\": \"^1.2\",\n \"phpstan/extension-installer\": \"^1.0\",\n \"phpstan/phpstan\": \"^2.0\",\n \"phpstan/phpstan-phpunit\": \"^2.0\",\n \"phpstan/phpstan-strict-rules\": \"^2.0\",\n \"phpunit/phpunit\": \"^9.6\",\n \"symfony/process\": \"^5.2\"\n },\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"PHPStan\\\\PhpDocParser\\\\\": [\n \"src/\"\n ]\n }\n },\n \"notification-url\": \"https://packagist.org/downloads/\",\n \"license\": [\n \"MIT\"\n ],\n \"description\": \"PHPDoc parser with support for nullable, intersection and generic types\",\n \"support\": {\n \"issues\": \"https://github.com/phpstan/phpdoc-parser/issues\",\n \"source\": \"https://github.com/phpstan/phpdoc-parser/tree/2.3.0\"\n },\n \"time\": \"2025-08-30T15:50:23+00:00\"\n },\n {\n \"name\": \"slevomat/coding-standard\",\n \"version\": \"8.22.1\",\n \"source\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/slevomat/coding-standard.git\",\n \"reference\": \"1dd80bf3b93692bedb21a6623c496887fad05fec\"\n },\n \"dist\": {\n \"type\": \"zip\",\n \"url\": \"https://api.github.com/repos/slevomat/coding-standard/zipball/1dd80bf3b93692bedb21a6623c496887fad05fec\",\n \"reference\": \"1dd80bf3b93692bedb21a6623c496887fad05fec\",\n \"shasum\": \"\"\n },\n \"require\": {\n \"dealerdirect/phpcodesniffer-composer-installer\": \"^0.6.2 || ^0.7 || ^1.1.2\",\n \"php\": \"^7.4 || ^8.0\",\n \"phpstan/phpdoc-parser\": \"^2.3.0\",\n \"squizlabs/php_codesniffer\": \"^3.13.4\"\n },\n \"require-dev\": {\n \"phing/phing\": \"3.0.1|3.1.0\",\n \"php-parallel-lint/php-parallel-lint\": \"1.4.0\",\n \"phpstan/phpstan\": \"2.1.24\",\n \"phpstan/phpstan-deprecation-rules\": \"2.0.3\",\n \"phpstan/phpstan-phpunit\": \"2.0.7\",\n \"phpstan/phpstan-strict-rules\": \"2.0.6\",\n \"phpunit/phpunit\": \"9.6.8|10.5.48|11.4.4|11.5.36|12.3.10\"\n },\n \"type\": \"phpcodesniffer-standard\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"8.x-dev\"\n }\n },\n \"autoload\": {\n \"psr-4\": {\n \"SlevomatCodingStandard\\\\\": \"SlevomatCodingStandard/\"\n }\n },\n \"notification-url\": \"https://packagist.org/downloads/\",\n \"license\": [\n \"MIT\"\n ],\n \"description\": \"Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.\",\n \"keywords\": [\n \"dev\",\n \"phpcs\"\n ],\n \"support\": {\n \"issues\": \"https://github.com/slevomat/coding-standard/issues\",\n \"source\": \"https://github.com/slevomat/coding-standard/tree/8.22.1\"\n },\n \"funding\": [\n {\n \"url\": \"https://github.com/kukulich\",\n \"type\": \"github\"\n },\n {\n \"url\": \"https://tidelift.com/funding/github/packagist/slevomat/coding-standard\",\n \"type\": \"tidelift\"\n }\n ],\n \"time\": \"2025-09-13T08:53:30+00:00\"\n },\n {\n \"name\": \"squizlabs/php_codesniffer\",\n \"version\": \"3.13.5\",\n \"source\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer.git\",\n \"reference\": \"0ca86845ce43291e8f5692c7356fccf3bcf02bf4\"\n },\n \"dist\": {\n \"type\": \"zip\",\n \"url\": \"https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4\",\n \"reference\": \"0ca86845ce43291e8f5692c7356fccf3bcf02bf4\",\n \"shasum\": \"\"\n },\n \"require\": {\n \"ext-simplexml\": \"*\",\n \"ext-tokenizer\": \"*\",\n \"ext-xmlwriter\": \"*\",\n \"php\": \">=5.4.0\"\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4\"\n },\n \"bin\": [\n \"bin/phpcbf\",\n \"bin/phpcs\"\n ],\n \"type\": \"library\",\n \"notification-url\": \"https://packagist.org/downloads/\",\n \"license\": [\n \"BSD-3-Clause\"\n ],\n \"authors\": [\n {\n \"name\": \"Greg Sherwood\",\n \"role\": \"Former lead\"\n },\n {\n \"name\": \"Juliette Reinders Folmer\",\n \"role\": \"Current lead\"\n },\n {\n \"name\": \"Contributors\",\n \"homepage\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors\"\n }\n ],\n \"description\": \"PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.\",\n \"homepage\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer\",\n \"keywords\": [\n \"phpcs\",\n \"standards\",\n \"static analysis\"\n ],\n \"support\": {\n \"issues\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer/issues\",\n \"security\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy\",\n \"source\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer\",\n \"wiki\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki\"\n },\n \"funding\": [\n {\n \"url\": \"https://github.com/PHPCSStandards\",\n \"type\": \"github\"\n },\n {\n \"url\": \"https://github.com/jrfnl\",\n \"type\": \"github\"\n },\n {\n \"url\": \"https://opencollective.com/php_codesniffer\",\n \"type\": \"open_collective\"\n },\n {\n \"url\": \"https://thanks.dev/u/gh/phpcsstandards\",\n \"type\": \"thanks_dev\"\n }\n ],\n \"time\": \"2025-11-04T16:30:35+00:00\"\n }\n ],\n \"packages-dev\": [],\n \"aliases\": [],\n \"minimum-stability\": \"stable\",\n \"stability-flags\": {},\n \"prefer-stable\": false,\n \"prefer-lowest\": false,\n \"platform\": {},\n \"platform-dev\": {},\n \"plugin-api-version\": \"2.6.0\"\n}\n"},"composer-normalize":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/composer-normalize/composer-normalize-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-json":"*"},"tool":{"composer-normalize":"^2.1"}},"checksum":{"type":"sha-512","value":"d9abda440b85d501c58abf9c81bf76f417594b397129215ffa8b777e9bb5e5eda37d7661d661db3c8d11c24f20345bc6fbe56f013b3b9435d459d2b94f086e0f"},"tools":{"composer-normalize":{"version":"2.48.2","url":"https://github.com/ergebnis/composer-normalize/releases/download/2.48.2/composer-normalize.phar","requirements":{"php":{"php":"~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0","ext-json":"*"}},"checksum":null,"signature":"https://github.com/ergebnis/composer-normalize/releases/download/2.48.2/composer-normalize.phar.asc"}},"composerLock":null},"composer-require-checker":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/composer-require-checker/composer-require-checker-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0"},"tool":{"composer-require-checker":"^3.8 || ^4.0"}},"checksum":{"type":"sha-512","value":"d5415bddfe024c5749d894034583882aee4e5c3e1087815d9fdd81cb5e71630f631a0e35de0ff84b97fbbf738c16ece5f83bd8c00695913eb846aa6f04577dc2"},"tools":{"composer-require-checker":{"version":"4.19.0","url":"https://github.com/maglnet/ComposerRequireChecker/releases/download/4.19.0/composer-require-checker.phar","requirements":{"php":{"php":"~8.3.0 || ~8.4.0 || ~8.5.0","ext-phar":"*"}},"checksum":null,"signature":"https://github.com/maglnet/ComposerRequireChecker/releases/download/4.19.0/composer-require-checker.phar.asc"}},"composerLock":null},"phpcpd":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpcpd/phpcpd-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpcpd":"^6.0"}},"checksum":{"type":"sha-512","value":"1189ce0bf3fade4cb4241f1d96f915ef8fc7651f4450dc79fdf464ee3d6be3009316f0d423ce2d4af9d76ad50807b7fdf4d77bfa6d9ee2c91d6eda32ea214433"},"tools":{"phpcpd":{"version":"6.0.3","url":"https://phar.phpunit.de/phpcpd-6.0.3.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*"}},"checksum":{"type":"sha-256","value":"2cbaea7cfda1bb4299d863eb075e977c3f49055dd16d88529fae5150d48a84cb"},"signature":"https://phar.phpunit.de/phpcpd-6.0.3.phar.asc"}},"composerLock":null},"phploc":{"api-version":"1.0.0","version":"1.0.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phploc/phploc-1.0.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*","ext-json":"*"},"tool":{"phploc":"^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0"}},"checksum":{"type":"sha-512","value":"f67b02d494796adf553cb3dd13ec06c1cb8e53c799954061749424251379541637538199afb3afa3c7a01cabd1cb6f1c53eb621f015dff9644c6c7cbf10c56d1"},"tools":{"phploc":{"version":"7.0.2","url":"https://phar.phpunit.de/phploc-7.0.2.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*","ext-json":"*"}},"checksum":{"type":"sha-256","value":"3d59778ec86faf25fd00e3a329b2f9ad4a3c751ca91601ea7dab70f887b0bf46"},"signature":"https://phar.phpunit.de/phploc-7.0.2.phar.asc"}},"composerLock":null},"phpmd":{"api-version":"1.0.0","version":"1.0.2.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpmd/phpmd-1.0.2.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpmd":"^2.6.1"}},"checksum":{"type":"sha-512","value":"f22280a6dec8dbdd2ec1d83b294f23237fe32c34f4a298e52038e0a7a0074d541635b2b488b1a6098a42d8418a6cd8eb804406ea82b91e362be2b5d11a0915b0"},"tools":{"phpmd":{"version":"2.15.0","url":"https://github.com/phpmd/phpmd/releases/download/2.15.0/phpmd.phar","requirements":{"php":{"php":">=5.3.9","ext-xml":"*"}},"checksum":null,"signature":"https://github.com/phpmd/phpmd/releases/download/2.15.0/phpmd.phar.asc"}},"composerLock":null},"psalm":{"api-version":"1.0.0","version":"1.3.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/psalm/psalm-1.3.0.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0","ext-dom":"*"},"tool":{"psalm":"^3.0 || ^4.0 || ^5.0 || ^6.0"}},"checksum":{"type":"sha-512","value":"4a550c9226d7bca582d7c10bd87cce01190c96398936b1613421640c83df62ed1c6e0d44c1b39635414ea8cf4a892a6458d27590793238add24e7cb5547e6ffd"},"tools":{"psalm":{"version":"6.13.1","url":"https://github.com/vimeo/psalm/releases/download/6.13.1/psalm.phar","requirements":{"php":{"php":"~8.2.27 || ~8.3.16 || ~8.4.3","ext-SimpleXML":"*","ext-ctype":"*","ext-dom":"*","ext-json":"*","ext-libxml":"*","ext-mbstring":"*","ext-tokenizer":"*"}},"checksum":null,"signature":"https://github.com/vimeo/psalm/releases/download/6.13.1/psalm.phar.asc"}},"composerLock":null},"phpcs":{"api-version":"1.0.0","version":"1.2.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpcs/phpcs-1.2.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpcs":"^3.0 || ^2.0","phpcbf":"^3.0 || ^2.0"}},"checksum":{"type":"sha-512","value":"b6ed00306e76068a6af5e3b1dec837724f9e1900ef1049ce88e7ce195b0583524ca33a73613fba13244307a7ca853b6ddaa14ded69f651c3f184ac130bd1aaad"},"tools":{"phpcs":{"version":"3.13.5","url":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.13.5/phpcs.phar","requirements":{"php":{"php":">=5.4.0","ext-simplexml":"*","ext-tokenizer":"*","ext-xmlwriter":"*"}},"checksum":null,"signature":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.13.5/phpcs.phar.asc"},"phpcbf":{"version":"3.13.5","url":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.13.5/phpcbf.phar","requirements":{"php":{"php":">=5.4.0","ext-simplexml":"*","ext-tokenizer":"*","ext-xmlwriter":"*"}},"checksum":null,"signature":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/3.13.5/phpcbf.phar.asc"}},"composerLock":null}},"tools":[]} \ No newline at end of file +{"plugins":{"doctrine-coding-standard":{"api-version":"1.0.0","version":"1.0.2.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/doctrine-coding-standard/doctrine-coding-standard-1.0.2.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0","ext-dom":"*"},"composer":{"doctrine/coding-standard":"^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0 || ^14.0"}},"checksum":{"type":"sha-512","value":"00fab498a6575bf07930e078fd616c0481714570bc1c61ebae4fa277d64c0cb28575aba9190c9731c7bda9f97f57c113516e1eb2920c3b9b7b295e0078be3159"},"tools":{},"composerLock":"{\n \"_readme\": [\n \"This file locks the dependencies of your project to a known state\",\n \"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies\",\n \"This file is @generated automatically\"\n ],\n \"content-hash\": \"40b84043be9c25e6feb38a9e014f1a9f\",\n \"packages\": [\n {\n \"name\": \"dealerdirect/phpcodesniffer-composer-installer\",\n \"version\": \"v1.2.0\",\n \"source\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/PHPCSStandards/composer-installer.git\",\n \"reference\": \"845eb62303d2ca9b289ef216356568ccc075ffd1\"\n },\n \"dist\": {\n \"type\": \"zip\",\n \"url\": \"https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/845eb62303d2ca9b289ef216356568ccc075ffd1\",\n \"reference\": \"845eb62303d2ca9b289ef216356568ccc075ffd1\",\n \"shasum\": \"\"\n },\n \"require\": {\n \"composer-plugin-api\": \"^2.2\",\n \"php\": \">=5.4\",\n \"squizlabs/php_codesniffer\": \"^3.1.0 || ^4.0\"\n },\n \"require-dev\": {\n \"composer/composer\": \"^2.2\",\n \"ext-json\": \"*\",\n \"ext-zip\": \"*\",\n \"php-parallel-lint/php-parallel-lint\": \"^1.4.0\",\n \"phpcompatibility/php-compatibility\": \"^9.0 || ^10.0.0@dev\",\n \"yoast/phpunit-polyfills\": \"^1.0\"\n },\n \"type\": \"composer-plugin\",\n \"extra\": {\n \"class\": \"PHPCSStandards\\\\Composer\\\\Plugin\\\\Installers\\\\PHPCodeSniffer\\\\Plugin\"\n },\n \"autoload\": {\n \"psr-4\": {\n \"PHPCSStandards\\\\Composer\\\\Plugin\\\\Installers\\\\PHPCodeSniffer\\\\\": \"src/\"\n }\n },\n \"notification-url\": \"https://packagist.org/downloads/\",\n \"license\": [\n \"MIT\"\n ],\n \"authors\": [\n {\n \"name\": \"Franck Nijhof\",\n \"email\": \"opensource@frenck.dev\",\n \"homepage\": \"https://frenck.dev\",\n \"role\": \"Open source developer\"\n },\n {\n \"name\": \"Contributors\",\n \"homepage\": \"https://github.com/PHPCSStandards/composer-installer/graphs/contributors\"\n }\n ],\n \"description\": \"PHP_CodeSniffer Standards Composer Installer Plugin\",\n \"keywords\": [\n \"PHPCodeSniffer\",\n \"PHP_CodeSniffer\",\n \"code quality\",\n \"codesniffer\",\n \"composer\",\n \"installer\",\n \"phpcbf\",\n \"phpcs\",\n \"plugin\",\n \"qa\",\n \"quality\",\n \"standard\",\n \"standards\",\n \"style guide\",\n \"stylecheck\",\n \"tests\"\n ],\n \"support\": {\n \"issues\": \"https://github.com/PHPCSStandards/composer-installer/issues\",\n \"security\": \"https://github.com/PHPCSStandards/composer-installer/security/policy\",\n \"source\": \"https://github.com/PHPCSStandards/composer-installer\"\n },\n \"funding\": [\n {\n \"url\": \"https://github.com/PHPCSStandards\",\n \"type\": \"github\"\n },\n {\n \"url\": \"https://github.com/jrfnl\",\n \"type\": \"github\"\n },\n {\n \"url\": \"https://opencollective.com/php_codesniffer\",\n \"type\": \"open_collective\"\n },\n {\n \"url\": \"https://thanks.dev/u/gh/phpcsstandards\",\n \"type\": \"thanks_dev\"\n }\n ],\n \"time\": \"2025-11-11T04:32:07+00:00\"\n },\n {\n \"name\": \"doctrine/coding-standard\",\n \"version\": \"14.0.0\",\n \"source\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/doctrine/coding-standard.git\",\n \"reference\": \"897a7dc209e49ee6cf04e689c41112df17967130\"\n },\n \"dist\": {\n \"type\": \"zip\",\n \"url\": \"https://api.github.com/repos/doctrine/coding-standard/zipball/897a7dc209e49ee6cf04e689c41112df17967130\",\n \"reference\": \"897a7dc209e49ee6cf04e689c41112df17967130\",\n \"shasum\": \"\"\n },\n \"require\": {\n \"dealerdirect/phpcodesniffer-composer-installer\": \"^0.6.2 || ^0.7 || ^1.0.0\",\n \"php\": \"^7.4 || ^8.0\",\n \"slevomat/coding-standard\": \"^8.23\",\n \"squizlabs/php_codesniffer\": \"^4\"\n },\n \"type\": \"phpcodesniffer-standard\",\n \"notification-url\": \"https://packagist.org/downloads/\",\n \"license\": [\n \"MIT\"\n ],\n \"authors\": [\n {\n \"name\": \"Benjamin Eberlei\",\n \"email\": \"kontakt@beberlei.de\"\n },\n {\n \"name\": \"Steve Müller\",\n \"email\": \"st.mueller@dzh-online.de\"\n }\n ],\n \"description\": \"The Doctrine Coding Standard is a set of PHPCS rules applied to all Doctrine projects.\",\n \"homepage\": \"https://www.doctrine-project.org/projects/coding-standard.html\",\n \"keywords\": [\n \"checks\",\n \"code\",\n \"coding\",\n \"cs\",\n \"dev\",\n \"doctrine\",\n \"rules\",\n \"sniffer\",\n \"sniffs\",\n \"standard\",\n \"style\"\n ],\n \"support\": {\n \"issues\": \"https://github.com/doctrine/coding-standard/issues\",\n \"source\": \"https://github.com/doctrine/coding-standard/tree/14.0.0\"\n },\n \"time\": \"2025-09-21T18:21:47+00:00\"\n },\n {\n \"name\": \"phpstan/phpdoc-parser\",\n \"version\": \"2.3.2\",\n \"source\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/phpstan/phpdoc-parser.git\",\n \"reference\": \"a004701b11273a26cd7955a61d67a7f1e525a45a\"\n },\n \"dist\": {\n \"type\": \"zip\",\n \"url\": \"https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a\",\n \"reference\": \"a004701b11273a26cd7955a61d67a7f1e525a45a\",\n \"shasum\": \"\"\n },\n \"require\": {\n \"php\": \"^7.4 || ^8.0\"\n },\n \"require-dev\": {\n \"doctrine/annotations\": \"^2.0\",\n \"nikic/php-parser\": \"^5.3.0\",\n \"php-parallel-lint/php-parallel-lint\": \"^1.2\",\n \"phpstan/extension-installer\": \"^1.0\",\n \"phpstan/phpstan\": \"^2.0\",\n \"phpstan/phpstan-phpunit\": \"^2.0\",\n \"phpstan/phpstan-strict-rules\": \"^2.0\",\n \"phpunit/phpunit\": \"^9.6\",\n \"symfony/process\": \"^5.2\"\n },\n \"type\": \"library\",\n \"autoload\": {\n \"psr-4\": {\n \"PHPStan\\\\PhpDocParser\\\\\": [\n \"src/\"\n ]\n }\n },\n \"notification-url\": \"https://packagist.org/downloads/\",\n \"license\": [\n \"MIT\"\n ],\n \"description\": \"PHPDoc parser with support for nullable, intersection and generic types\",\n \"support\": {\n \"issues\": \"https://github.com/phpstan/phpdoc-parser/issues\",\n \"source\": \"https://github.com/phpstan/phpdoc-parser/tree/2.3.2\"\n },\n \"time\": \"2026-01-25T14:56:51+00:00\"\n },\n {\n \"name\": \"slevomat/coding-standard\",\n \"version\": \"8.28.1\",\n \"source\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/slevomat/coding-standard.git\",\n \"reference\": \"66151cfbd25b50e8becd9f809fb704f01fd4d6f2\"\n },\n \"dist\": {\n \"type\": \"zip\",\n \"url\": \"https://api.github.com/repos/slevomat/coding-standard/zipball/66151cfbd25b50e8becd9f809fb704f01fd4d6f2\",\n \"reference\": \"66151cfbd25b50e8becd9f809fb704f01fd4d6f2\",\n \"shasum\": \"\"\n },\n \"require\": {\n \"dealerdirect/phpcodesniffer-composer-installer\": \"^0.7 || ^1.2.0\",\n \"php\": \"^7.4 || ^8.0\",\n \"phpstan/phpdoc-parser\": \"^2.3.2\",\n \"squizlabs/php_codesniffer\": \"^4.0.1\"\n },\n \"require-dev\": {\n \"phing/phing\": \"3.0.1|3.1.2\",\n \"php-parallel-lint/php-parallel-lint\": \"1.4.0\",\n \"phpstan/phpstan\": \"2.1.42\",\n \"phpstan/phpstan-deprecation-rules\": \"2.0.4\",\n \"phpstan/phpstan-phpunit\": \"2.0.16\",\n \"phpstan/phpstan-strict-rules\": \"2.0.10\",\n \"phpunit/phpunit\": \"9.6.34|10.5.63|11.4.4|11.5.50|12.5.14\"\n },\n \"type\": \"phpcodesniffer-standard\",\n \"extra\": {\n \"branch-alias\": {\n \"dev-master\": \"8.x-dev\"\n }\n },\n \"autoload\": {\n \"psr-4\": {\n \"SlevomatCodingStandard\\\\\": \"SlevomatCodingStandard/\"\n }\n },\n \"notification-url\": \"https://packagist.org/downloads/\",\n \"license\": [\n \"MIT\"\n ],\n \"description\": \"Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.\",\n \"keywords\": [\n \"dev\",\n \"phpcs\"\n ],\n \"support\": {\n \"issues\": \"https://github.com/slevomat/coding-standard/issues\",\n \"source\": \"https://github.com/slevomat/coding-standard/tree/8.28.1\"\n },\n \"funding\": [\n {\n \"url\": \"https://github.com/kukulich\",\n \"type\": \"github\"\n },\n {\n \"url\": \"https://tidelift.com/funding/github/packagist/slevomat/coding-standard\",\n \"type\": \"tidelift\"\n }\n ],\n \"time\": \"2026-03-22T17:22:38+00:00\"\n },\n {\n \"name\": \"squizlabs/php_codesniffer\",\n \"version\": \"4.0.1\",\n \"source\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer.git\",\n \"reference\": \"0525c73950de35ded110cffafb9892946d7771b5\"\n },\n \"dist\": {\n \"type\": \"zip\",\n \"url\": \"https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0525c73950de35ded110cffafb9892946d7771b5\",\n \"reference\": \"0525c73950de35ded110cffafb9892946d7771b5\",\n \"shasum\": \"\"\n },\n \"require\": {\n \"ext-simplexml\": \"*\",\n \"ext-tokenizer\": \"*\",\n \"ext-xmlwriter\": \"*\",\n \"php\": \">=7.2.0\"\n },\n \"require-dev\": {\n \"phpunit/phpunit\": \"^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31\"\n },\n \"bin\": [\n \"bin/phpcbf\",\n \"bin/phpcs\"\n ],\n \"type\": \"library\",\n \"notification-url\": \"https://packagist.org/downloads/\",\n \"license\": [\n \"BSD-3-Clause\"\n ],\n \"authors\": [\n {\n \"name\": \"Greg Sherwood\",\n \"role\": \"Former lead\"\n },\n {\n \"name\": \"Juliette Reinders Folmer\",\n \"role\": \"Current lead\"\n },\n {\n \"name\": \"Contributors\",\n \"homepage\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors\"\n }\n ],\n \"description\": \"PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.\",\n \"homepage\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer\",\n \"keywords\": [\n \"phpcs\",\n \"standards\",\n \"static analysis\"\n ],\n \"support\": {\n \"issues\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer/issues\",\n \"security\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy\",\n \"source\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer\",\n \"wiki\": \"https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki\"\n },\n \"funding\": [\n {\n \"url\": \"https://github.com/PHPCSStandards\",\n \"type\": \"github\"\n },\n {\n \"url\": \"https://github.com/jrfnl\",\n \"type\": \"github\"\n },\n {\n \"url\": \"https://opencollective.com/php_codesniffer\",\n \"type\": \"open_collective\"\n },\n {\n \"url\": \"https://thanks.dev/u/gh/phpcsstandards\",\n \"type\": \"thanks_dev\"\n }\n ],\n \"time\": \"2025-11-10T16:43:36+00:00\"\n }\n ],\n \"packages-dev\": [],\n \"aliases\": [],\n \"minimum-stability\": \"stable\",\n \"stability-flags\": {},\n \"prefer-stable\": false,\n \"prefer-lowest\": false,\n \"platform\": {},\n \"platform-dev\": {},\n \"plugin-api-version\": \"2.6.0\"\n}\n"},"composer-normalize":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/composer-normalize/composer-normalize-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-json":"*"},"tool":{"composer-normalize":"^2.1"}},"checksum":{"type":"sha-512","value":"d9abda440b85d501c58abf9c81bf76f417594b397129215ffa8b777e9bb5e5eda37d7661d661db3c8d11c24f20345bc6fbe56f013b3b9435d459d2b94f086e0f"},"tools":{"composer-normalize":{"version":"2.50.0","url":"https://github.com/ergebnis/composer-normalize/releases/download/2.50.0/composer-normalize.phar","requirements":{"php":{"php":"~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0","ext-json":"*"}},"checksum":null,"signature":"https://github.com/ergebnis/composer-normalize/releases/download/2.50.0/composer-normalize.phar.asc"}},"composerLock":null},"composer-require-checker":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/composer-require-checker/composer-require-checker-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0"},"tool":{"composer-require-checker":"^3.8 || ^4.0"}},"checksum":{"type":"sha-512","value":"d5415bddfe024c5749d894034583882aee4e5c3e1087815d9fdd81cb5e71630f631a0e35de0ff84b97fbbf738c16ece5f83bd8c00695913eb846aa6f04577dc2"},"tools":{"composer-require-checker":{"version":"4.24.0","url":"https://github.com/maglnet/ComposerRequireChecker/releases/download/4.24.0/composer-require-checker.phar","requirements":{"php":{"php":"~8.4.0 || ~8.5.0","ext-phar":"*"}},"checksum":null,"signature":"https://github.com/maglnet/ComposerRequireChecker/releases/download/4.24.0/composer-require-checker.phar.asc"}},"composerLock":null},"phpcpd":{"api-version":"1.0.0","version":"1.1.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpcpd/phpcpd-1.1.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpcpd":"^6.0"}},"checksum":{"type":"sha-512","value":"1189ce0bf3fade4cb4241f1d96f915ef8fc7651f4450dc79fdf464ee3d6be3009316f0d423ce2d4af9d76ad50807b7fdf4d77bfa6d9ee2c91d6eda32ea214433"},"tools":{"phpcpd":{"version":"6.0.3","url":"https://phar.phpunit.de/phpcpd-6.0.3.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*"}},"checksum":{"type":"sha-256","value":"2cbaea7cfda1bb4299d863eb075e977c3f49055dd16d88529fae5150d48a84cb"},"signature":"https://phar.phpunit.de/phpcpd-6.0.3.phar.asc"}},"composerLock":null},"phploc":{"api-version":"1.0.0","version":"1.0.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phploc/phploc-1.0.0.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*","ext-json":"*"},"tool":{"phploc":"^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0"}},"checksum":{"type":"sha-512","value":"f67b02d494796adf553cb3dd13ec06c1cb8e53c799954061749424251379541637538199afb3afa3c7a01cabd1cb6f1c53eb621f015dff9644c6c7cbf10c56d1"},"tools":{"phploc":{"version":"7.0.2","url":"https://phar.phpunit.de/phploc-7.0.2.phar","requirements":{"php":{"php":">=7.3","ext-dom":"*","ext-json":"*"}},"checksum":{"type":"sha-256","value":"3d59778ec86faf25fd00e3a329b2f9ad4a3c751ca91601ea7dab70f887b0bf46"},"signature":"https://phar.phpunit.de/phploc-7.0.2.phar.asc"}},"composerLock":null},"phpmd":{"api-version":"1.0.0","version":"1.0.2.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpmd/phpmd-1.0.2.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpmd":"^2.6.1"}},"checksum":{"type":"sha-512","value":"f22280a6dec8dbdd2ec1d83b294f23237fe32c34f4a298e52038e0a7a0074d541635b2b488b1a6098a42d8418a6cd8eb804406ea82b91e362be2b5d11a0915b0"},"tools":{"phpmd":{"version":"2.15.0","url":"https://github.com/phpmd/phpmd/releases/download/2.15.0/phpmd.phar","requirements":{"php":{"php":">=5.3.9","ext-xml":"*"}},"checksum":null,"signature":"https://github.com/phpmd/phpmd/releases/download/2.15.0/phpmd.phar.asc"}},"composerLock":null},"psalm":{"api-version":"1.0.0","version":"1.3.0.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/psalm/psalm-1.3.0.0.php","signature":null,"requirements":{"php":{"php":"^7.4 || ^8.0","ext-dom":"*"},"tool":{"psalm":"^3.0 || ^4.0 || ^5.0 || ^6.0"}},"checksum":{"type":"sha-512","value":"4a550c9226d7bca582d7c10bd87cce01190c96398936b1613421640c83df62ed1c6e0d44c1b39635414ea8cf4a892a6458d27590793238add24e7cb5547e6ffd"},"tools":{"psalm":{"version":"6.16.1","url":"https://github.com/vimeo/psalm/releases/download/6.16.1/psalm.phar","requirements":{"php":{"php":"~8.2.27 || ~8.3.16 || ~8.4.3 || ~8.5.0","ext-SimpleXML":"*","ext-ctype":"*","ext-dom":"*","ext-json":"*","ext-libxml":"*","ext-mbstring":"*","ext-tokenizer":"*"}},"checksum":null,"signature":"https://github.com/vimeo/psalm/releases/download/6.16.1/psalm.phar.asc"}},"composerLock":null},"phpcs":{"api-version":"1.0.0","version":"1.2.1.0","type":"php-file","url":"https://phpcq.github.io/repository/plugin/phpcs/phpcs-1.2.1.0.php","signature":null,"requirements":{"php":{"php":"^7.3 || ^8.0","ext-dom":"*"},"tool":{"phpcs":"^4.0 || ^3.0 || ^2.0","phpcbf":"^4.0 || ^3.0 || ^2.0"}},"checksum":{"type":"sha-512","value":"03f1c6c2d94b79d0e8cbd42996382e0d100c7e07f84c3138fa3a8b394e814ec18ce05cbbd257e527913219b2264f062522e4cf3e3bd402b907b9437d96982b44"},"tools":{"phpcs":{"version":"4.0.1","url":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/4.0.1/phpcs.phar","requirements":{"php":{"php":">=7.2.0","ext-simplexml":"*","ext-tokenizer":"*","ext-xmlwriter":"*"}},"checksum":null,"signature":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/4.0.1/phpcs.phar.asc"},"phpcbf":{"version":"4.0.1","url":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/4.0.1/phpcbf.phar","requirements":{"php":{"php":">=7.2.0","ext-simplexml":"*","ext-tokenizer":"*","ext-xmlwriter":"*"}},"checksum":null,"signature":"https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/download/4.0.1/phpcbf.phar.asc"}},"composerLock":null}},"tools":[]} \ No newline at end of file diff --git a/.phpcq.yaml.dist b/.phpcq.yaml.dist index 23a6f99..cb80fbd 100644 --- a/.phpcq.yaml.dist +++ b/.phpcq.yaml.dist @@ -1,7 +1,6 @@ phpcq: repositories: - 'https://phpcq.github.io/repository/repository.json' - - vendor/netzmacht/phpspec-phpcq-plugin/repository.json directories: - src artifact: .phpcq/build @@ -11,7 +10,7 @@ phpcq: signed: false requirements: composer: - doctrine/coding-standard: ^13.0 + doctrine/coding-standard: ^14.0 composer-normalize: version: ^1.0 signed: false @@ -34,6 +33,7 @@ phpcq: version: ^1.0 signed: false trusted-keys: + - 6659B17090D6C5D3 - C00543248C87FB13 - 033E5F8D801A2F8D - D2CCAC42F6295E7D @@ -41,6 +41,7 @@ phpcq: - 9093F8B32E4815AA - 8A03EA3B385DBAA1 - 12CE0F1D262429A5 + - 99BF4D9A33D65E1E - 31C7E470E2138192 - 5E6DDE998AB73B8E - A978220305CD5C32 diff --git a/CHANGELOG.md b/CHANGELOG.md index b2b4c27..feb553f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ Changelog [Unreleased] ------------ +### Added + +- Add support for nested fragments + 3.0.5 (2025-03-02) ------------------ diff --git a/README.md b/README.md index a185717..f5db945 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,11 @@ This extension provides Bootstrap 5 grid tools for Contao CMS. Features -------- - - Manage grid definition in your theme settings - - Content elements - - Form elements - - Grid module - - Import/Export with your theme settings - +- Manage grid definition in your theme settings +- Content elements +- Form elements +- Grid module +- Import/Export with your theme settings Changelog --------- @@ -32,7 +31,6 @@ Requirements - PHP ^8.1 - Contao ^4.13 || ^5.3 - Install ------- @@ -73,3 +71,10 @@ class AppKernel } ``` + +Migration +------- + +To automatically migrate your grid from Start- and Stop-Wrappers to nested fragments. You have to enbale the Migration +by adding `BS_GRID_WRAPPER_MIGRATION=true` parameter to your .env.local. Afterwards you can run the migration in the +contao manager over by cli. diff --git a/composer.json b/composer.json index 34be493..f490b7e 100644 --- a/composer.json +++ b/composer.json @@ -30,28 +30,26 @@ "source": "https://github.com/contao-bootstrap/grid" }, "require": { - "php": "^8.1", + "php": "^8.2", "ext-dom": "*", "ext-pdo": "*", "contao-bootstrap/core": "^3.0", "contao-community-alliance/meta-palettes": "^2.0", - "contao/core-bundle": "^4.13 || ^5.3", + "contao/core-bundle": "^5.3", "doctrine/dbal": "^3.4", "mvo/contao-group-widget": "^1.4", "netzmacht/contao-toolkit": "^3.8 || ^4.0", - "symfony/config": "^5.4 || ^6.4 || ^7.0", - "symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0", - "symfony/http-foundation": "^5.4 || ^6.4 || ^7.0", - "symfony/http-kernel": "^5.4 || ^6.4 || ^7.0", - "symfony/routing": "^5.4 || ^6.4 || ^7.0", - "symfony/security-bundle": "^5.4 || ^6.4 || ^7.0", - "symfony/security-core": "^5.4 || ^6.4 || ^7.0", - "symfony/translation-contracts": "^1.0 || ^2.0 || ^3.0" + "symfony/config": "^6.4 || ^7.4", + "symfony/dependency-injection": "^6.4 || ^7.4", + "symfony/http-foundation": "^6.4 || ^7.4", + "symfony/http-kernel": "^6.4 || ^7.4", + "symfony/routing": "^6.4 || ^7.4", + "symfony/security-core": "^6.4 || ^7.4", + "symfony/translation-contracts": "^3.0" }, "require-dev": { "contao/manager-plugin": "^2.1", - "contao/news-bundle": "^4.13 || ^5.3", - "netzmacht/phpspec-phpcq-plugin": "@dev", + "contao/news-bundle": "^5.3", "phpcq/runner-bootstrap": "@dev" }, "conflict": { diff --git a/phpcs.xml.dist b/phpcs.xml.dist index c4eef57..80247f0 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -7,7 +7,7 @@ - vendor/autoload.php + .phpcq/plugins/doctrine-coding-standard/vendor/autoload.php @@ -30,8 +30,4 @@ src/Resources/contao/languages/* - - - spec/.*\.php - diff --git a/psalm.xml b/psalm.xml index b901408..4499dac 100644 --- a/psalm.xml +++ b/psalm.xml @@ -32,6 +32,8 @@ + + diff --git a/src/Component/ContentElement/GridSeparatorElementController.php b/src/Component/ContentElement/GridSeparatorElementController.php index b0bcc83..3356525 100644 --- a/src/Component/ContentElement/GridSeparatorElementController.php +++ b/src/Component/ContentElement/GridSeparatorElementController.php @@ -89,7 +89,7 @@ protected function getIterator(ContentModel $model): GridIterator|null if ($parent) { try { - $iterator = $provider->getIterator('ce:' . $parent->id, (int) $parent->bs_grid); + $iterator = $provider->getIterator('ce:' . $parent->id, (int)$parent->bs_grid); $this->tagResponse('contao.db.tl_bs_grid.' . $parent->bs_grid); return $iterator; @@ -110,6 +110,10 @@ protected function getIterator(ContentModel $model): GridIterator|null */ protected function getParent(ContentModel $model): ContentModel|null { - return $this->repositories->getRepository(ContentModel::class)->find((int) $model->bs_grid_parent); + if ($model->ptable === 'tl_content') { + return $this->repositories->getRepository(ContentModel::class)->find($model->pid); + } + + return $this->repositories->getRepository(ContentModel::class)->find((int)$model->bs_grid_parent); } } diff --git a/src/Component/ContentElement/GridWrapperElementController.php b/src/Component/ContentElement/GridWrapperElementController.php new file mode 100644 index 0000000..2bb9889 --- /dev/null +++ b/src/Component/ContentElement/GridWrapperElementController.php @@ -0,0 +1,58 @@ +isBackendScope($request)) { + $template->setName('backend/grid_wildcard'); + + $template->set('title', $model->bs_grid_name); + $template->set('color', $this->colorRotate->getColor('ce:' . $model->id)); + + return $template->getResponse(); + } + + $template->set('iterator', $this->getIterator($model)); + + return $template->getResponse(); + } + + protected function getIterator(ContentModel $model): GridIterator|null + { + try { + $iterator = $this->provider->getIterator('ce:' . $model->id, (int)$model->bs_grid); + $this->tagResponse('contao.db.tl_bs_grid.' . $model->bs_grid); + + return $iterator; + } catch (GridNotFound) { + // Do nothing. In backend view an error is shown anyway. + return null; + } + } +} diff --git a/src/Listener/Dca/ContentListener.php b/src/Listener/Dca/ContentListener.php index 66498f1..4bf9212 100644 --- a/src/Listener/Dca/ContentListener.php +++ b/src/Listener/Dca/ContentListener.php @@ -8,6 +8,7 @@ use Contao\Config; use Contao\ContentModel; use Contao\Controller; +use Contao\CoreBundle\DataContainer\PaletteManipulator; use Contao\CoreBundle\Framework\ContaoFramework; use Contao\CoreBundle\Image\ImageSizes; use Contao\Database\Result; @@ -18,9 +19,9 @@ use ContaoBootstrap\Core\Environment; use Netzmacht\Contao\Toolkit\Data\Model\RepositoryManager; use Override; -use stdClass; - use function sprintf; + +use stdClass; use function time; /** @@ -31,10 +32,10 @@ final class ContentListener extends AbstractWrapperDcaListener { /** - * @param Environment $environment Bootstrap environment. - * @param ContaoFramework $framework Contao framework. - * @param ImageSizes $imageSizes Image sizes. - * @param BackendUser $user Contao backend user. + * @param Environment $environment Bootstrap environment. + * @param ContaoFramework $framework Contao framework. + * @param ImageSizes $imageSizes Image sizes. + * @param BackendUser $user Contao backend user. */ public function __construct( Environment $environment, @@ -70,6 +71,22 @@ public function initializeDca(): void ]; } + public function updatePaletteOnNestedParent(DataContainer $dataContainer): void + { + $input = $this->framework->getAdapter(Input::class); + $currentRecord = $dataContainer->getCurrentRecord(); + + if ($input->get('act') !== 'edit' || $currentRecord === null) { + return; + } + + if ($currentRecord['type'] !== 'bs_gridSeparator' || $currentRecord['ptable'] !== 'tl_content') { + return; + } + + PaletteManipulator::create()->removeField('bs_grid_parent')->applyToPalette('bs_gridSeparator', 'tl_content'); + } + /** * Get all grid parent options. * @@ -123,7 +140,7 @@ public function getGalleryTemplates(): array /** * Dynamically add flags to the "multiSRC" field. * - * @param mixed $value Given value. + * @param mixed $value Given value. * @param DataContainer $dataContainer Data Container driver. * * @SuppressWarnings(PHPMD.Superglobals) diff --git a/src/Listener/Dca/ParentFixContentParentRelationsListener.php b/src/Listener/Dca/ParentFixContentParentRelationsListener.php index a612321..30b2df9 100644 --- a/src/Listener/Dca/ParentFixContentParentRelationsListener.php +++ b/src/Listener/Dca/ParentFixContentParentRelationsListener.php @@ -11,8 +11,8 @@ use Contao\Model\Collection; use Doctrine\DBAL\Connection; use Netzmacht\Contao\Toolkit\Data\Model\RepositoryManager; -use Netzmacht\Contao\Toolkit\Dca\Definition; use Netzmacht\Contao\Toolkit\Dca\DcaManager; +use Netzmacht\Contao\Toolkit\Dca\Definition; use function array_unique; use function time; diff --git a/src/Listener/Hook/RegisterFixContentParentRelationsFixerListener.php b/src/Listener/Hook/RegisterFixContentParentRelationsFixerListener.php index 8616aaa..33d0a82 100644 --- a/src/Listener/Hook/RegisterFixContentParentRelationsFixerListener.php +++ b/src/Listener/Hook/RegisterFixContentParentRelationsFixerListener.php @@ -6,8 +6,8 @@ use ContaoBootstrap\Grid\Listener\Dca\ParentFixContentParentRelationsListener; use Netzmacht\Contao\Toolkit\Assertion\AssertionFailed; -use Netzmacht\Contao\Toolkit\Dca\Definition; use Netzmacht\Contao\Toolkit\Dca\DcaManager; +use Netzmacht\Contao\Toolkit\Dca\Definition; use function in_array; use function is_array; diff --git a/src/Migration/GridWrapperMigration.php b/src/Migration/GridWrapperMigration.php new file mode 100644 index 0000000..ffd8472 --- /dev/null +++ b/src/Migration/GridWrapperMigration.php @@ -0,0 +1,128 @@ +enableMigration === false) { + return false; + } + + $schemaManager = $this->connection->createSchemaManager(); + if (! $schemaManager->tablesExist(['tl_bs_grid', 'tl_content'])) { + return false; + } + + $queryBuilder = $this->connection->createQueryBuilder(); + + return $queryBuilder + ->select('COUNT(tc.id) as count') + ->from('tl_content', 'tc') + ->where($queryBuilder->expr()->eq('tc.type', ':type')) + ->setParameter('type', 'bs_gridStart') + ->executeQuery() + ->fetchOne() > 0; + } + + #[Override] + public function run(): MigrationResult + { + $sql = << grid_start.sorting + ORDER BY grid_stop.sorting ASC + LIMIT 1 + ) AS grid_stop_id + FROM tl_content grid_start + LEFT JOIN tl_content el + ON el.pid = grid_start.pid + AND el.ptable = grid_start.ptable + AND el.sorting > grid_start.sorting + AND el.sorting < ( + SELECT MIN(grid_stop.sorting) + FROM tl_content grid_stop + WHERE grid_stop.pid = grid_start.pid + AND grid_stop.ptable = grid_start.ptable + AND grid_stop.type = 'bs_gridStop' + AND grid_stop.sorting > grid_start.sorting + ) + WHERE grid_start.type = 'bs_gridStart' + ORDER BY grid_start.pid, grid_start.ptable, grid_start.sorting, el.sorting +SQL; + + $contentElements = $this->connection->executeQuery($sql)->fetchAllAssociative(); + + $gridContainers = array_reduce($contentElements, function (array $carry, array $row) { + $startId = $row['grid_start_id']; + + $carry[$startId] ??= [ + 'start_id' => $startId, + 'stop_id' => $row['grid_stop_id'], + 'elements' => [], + ]; + + if ($row['element_id'] !== null) { + $carry[$startId]['elements'][] = $row; + } + + return $carry; + }, []); + + $elementCount = array_sum( + array_map( + static fn (array $gridContainer) => count($gridContainer['elements']), + $gridContainers + ) + ); + + foreach ($gridContainers as $gridContainer) { + $this->connection->update( + 'tl_content', + ['type' => 'bs_grid_wrapper'], + ['id' => $gridContainer['start_id']] + ); + + foreach ($gridContainer['elements'] as $element) { + $this->connection->update( + 'tl_content', + ['pid' => $gridContainer['start_id'], 'ptable' => 'tl_content'], + ['id' => $element['element_id']] + ); + } + + $this->connection->delete('tl_content', ['id' => $gridContainer['stop_id']]); + } + + return $this->createResult( + true, + 'Migrated ' . count($gridContainers) . ' grid containers and ' . $elementCount . ' elements.' + ); + } +} diff --git a/src/Resources/config/config.yaml b/src/Resources/config/config.yaml index a72bdf7..bf6b0ef 100644 --- a/src/Resources/config/config.yaml +++ b/src/Resources/config/config.yaml @@ -4,3 +4,5 @@ parameters: - 'Multilingual' - 'Contao\DC_Table' - 'Terminal42\DcMultilingualBundle\Driver' + + contao_bootstrap.grid.enable_wrapper_migration: '%env(bool:default::BS_GRID_WRAPPER_MIGRATION)%' diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml index e4a64df..cb28f80 100644 --- a/src/Resources/config/services.yaml +++ b/src/Resources/config/services.yaml @@ -1,4 +1,7 @@ services: + _defaults: + autowire: true + autoconfigure: true contao_bootstrap.grid.grid_builder: class: ContaoBootstrap\Grid\GridBuilder arguments: @@ -10,6 +13,11 @@ services: arguments: - '@contao_bootstrap.grid.grid_builder' + ContaoBootstrap\Grid\Component\ContentElement\GridWrapperElementController: + arguments: + - '@contao_bootstrap.grid.grid_provider' + - '@contao_bootstrap.core.helper.color_rotate' + ContaoBootstrap\Grid\Component\ContentElement\GridStartElementController: arguments: - '@netzmacht.contao_toolkit.template_renderer' @@ -96,3 +104,10 @@ services: - '@database_connection' tags: - { name: 'contao.migration' } + + ContaoBootstrap\Grid\Migration\GridWrapperMigration: + arguments: + - '@database_connection' + - '%contao_bootstrap.grid.enable_wrapper_migration%' + tags: + - { name: 'contao.migration' } diff --git a/src/Resources/contao/dca/tl_content.php b/src/Resources/contao/dca/tl_content.php index 89348bc..80cffcd 100644 --- a/src/Resources/contao/dca/tl_content.php +++ b/src/Resources/contao/dca/tl_content.php @@ -13,6 +13,11 @@ 'initializeDca', ]; +$GLOBALS['TL_DCA']['tl_content']['config']['onload_callback'][] = [ + 'contao_bootstrap.grid.listeners.dca.content', + 'updatePaletteOnNestedParent', +]; + $GLOBALS['TL_DCA']['tl_content']['config']['oncopy_callback'][] = [ ContentFixParentRelationListener::class, 'onCopy', @@ -27,6 +32,20 @@ * Palettes */ +$GLOBALS['TL_DCA']['tl_content']['metapalettes']['bs_grid_wrapper'] = [ + 'type' => [ + 'title', + 'headline', + 'type', + 'bs_grid', + 'bs_grid_name', + ], + 'template' => [':hide', 'customTpl'], + 'protected' => [':hide', 'protected'], + 'expert' => [':hide', 'guests', 'cssID'], + 'invisible' => ['invisible', 'start', 'stop'], +]; + $GLOBALS['TL_DCA']['tl_content']['metapalettes']['bs_gridStart'] = [ 'type' => [ 'type', diff --git a/src/Resources/contao/languages/de/modules.php b/src/Resources/contao/languages/de/modules.php index eeed6fd..21d4c8e 100644 --- a/src/Resources/contao/languages/de/modules.php +++ b/src/Resources/contao/languages/de/modules.php @@ -3,6 +3,8 @@ declare(strict_types=1); $GLOBALS['TL_LANG']['CTE']['bs_grid'] = 'Grid'; +$GLOBALS['TL_LANG']['CTE']['bs_grid_wrapper'][0] = 'Grid'; +$GLOBALS['TL_LANG']['CTE']['bs_grid_wrapper'][1] = 'Grid mit verschachtelten Elementen'; $GLOBALS['TL_LANG']['CTE']['bs_gridSeparator']['0'] = 'Grid-Trennung'; $GLOBALS['TL_LANG']['CTE']['bs_gridSeparator']['1'] = 'Grid-Trennelement'; $GLOBALS['TL_LANG']['CTE']['bs_gridStart']['0'] = 'Grid-Start'; diff --git a/src/Resources/contao/languages/en/modules.php b/src/Resources/contao/languages/en/modules.php index a9d53af..19f7c28 100644 --- a/src/Resources/contao/languages/en/modules.php +++ b/src/Resources/contao/languages/en/modules.php @@ -4,6 +4,8 @@ $GLOBALS['TL_LANG']['CTE']['bs_grid'] = 'Grid'; +$GLOBALS['TL_LANG']['CTE']['bs_grid_wrapper'][0] = 'Grid'; +$GLOBALS['TL_LANG']['CTE']['bs_grid_wrapper'][1] = 'Grid with nested elements'; $GLOBALS['TL_LANG']['CTE']['bs_gridStart'][0] = 'Grid Start'; $GLOBALS['TL_LANG']['CTE']['bs_gridStart'][1] = 'Grid Start Element'; $GLOBALS['TL_LANG']['CTE']['bs_gridSeparator'][0] = 'Grid Separator'; diff --git a/src/Resources/contao/templates/twig/.twig-root b/src/Resources/contao/templates/twig/.twig-root new file mode 100644 index 0000000..e69de29 diff --git a/src/Resources/contao/templates/twig/backend/grid_wildcard.html.twig b/src/Resources/contao/templates/twig/backend/grid_wildcard.html.twig new file mode 100644 index 0000000..5c4bae3 --- /dev/null +++ b/src/Resources/contao/templates/twig/backend/grid_wildcard.html.twig @@ -0,0 +1,7 @@ +{% trans_default_domain 'contao_modules' %} + + + ### {{ ('CTE.bootstrap')|trans }}: {{ ('CTE.' ~ type ~ '.0')|trans }} ### + + {{ title }} + diff --git a/src/Resources/contao/templates/twig/content_element/bs_grid_wrapper.html.twig b/src/Resources/contao/templates/twig/content_element/bs_grid_wrapper.html.twig new file mode 100644 index 0000000..51b135b --- /dev/null +++ b/src/Resources/contao/templates/twig/content_element/bs_grid_wrapper.html.twig @@ -0,0 +1,18 @@ +{% extends "@Contao/content_element/_base.html.twig" %} + +{% block content %} + {% if iterator is not null %} + + + {% for fragment in nested_fragments %} + {{ content_element(fragment) }} + {% endfor %} + + + {% else %} + {{ 'ERR.bsGridParentMissing'|trans({}, 'contao_default') }} + {% for fragment in nested_fragments %} + {{ content_element(fragment) }} + {% endfor %} + {% endif %} +{% endblock %}