From 25b6ed466cd28d196860a8419470d29556dc144e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Fri, 22 Nov 2024 22:35:46 +0100 Subject: [PATCH 1/7] Update packages - roave/security-advisories updated from dev-latest@9f1d9b2 to dev-latest@b33a18b See changes: https://github.com/Roave/SecurityAdvisories/compare/9f1d9b2...b33a18b - shipmonk/composer-dependency-analyser updated from 1.7.0 to 1.8.1 minor See changes: https://github.com/shipmonk-rnd/composer-dependency-analyser/compare/1.7.0...1.8.1 Release notes: https://github.com/shipmonk-rnd/composer-dependency-analyser/releases/tag/1.8.1 --- app/composer.lock | 50 ++-- app/vendor/composer/installed.json | 54 ++--- app/vendor/composer/installed.php | 8 +- .../composer-dependency-analyser/README.md | 18 +- .../bin/composer-dependency-analyser | 5 +- .../composer.json | 29 ++- .../src/Analyser.php | 217 +++++++++++++----- .../composer-dependency-analyser/src/Cli.php | 52 ++++- .../src/CliOptions.php | 5 + .../src/ComposerJson.php | 51 +++- .../src/Config/Configuration.php | 146 +++++++++++- .../src/Config/Ignore/IgnoreList.php | 44 ++-- .../src/Initializer.php | 7 + .../src/Printer.php | 14 +- .../src/UsedSymbolExtractor.php | 155 ++++++++++--- 15 files changed, 649 insertions(+), 206 deletions(-) diff --git a/app/composer.lock b/app/composer.lock index 643509b6c..fc42924cc 100644 --- a/app/composer.lock +++ b/app/composer.lock @@ -3651,12 +3651,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "9f1d9b2460cdd0422e8cfd58763bf3156ad7f487" + "reference": "b33a18b5d222c63472a4b41f6fa3e15e591c9595" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/9f1d9b2460cdd0422e8cfd58763bf3156ad7f487", - "reference": "9f1d9b2460cdd0422e8cfd58763bf3156ad7f487", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/b33a18b5d222c63472a4b41f6fa3e15e591c9595", + "reference": "b33a18b5d222c63472a4b41f6fa3e15e591c9595", "shasum": "" }, "conflict": { @@ -3702,7 +3702,7 @@ "azuracast/azuracast": "<0.18.3", "backdrop/backdrop": "<1.27.3|>=1.28,<1.28.2", "backpack/crud": "<3.4.9", - "backpack/filemanager": "<3.0.9", + "backpack/filemanager": "<2.0.2|>=3,<3.0.9", "bacula-web/bacula-web": "<8.0.0.0-RC2-dev", "badaso/core": "<2.7", "bagisto/bagisto": "<2.1", @@ -4034,7 +4034,7 @@ "mojo42/jirafeau": "<4.4", "mongodb/mongodb": ">=1,<1.9.2", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<4.3.6|>=4.4,<4.4.4", + "moodle/moodle": "<4.3.8|>=4.4,<4.4.4", "mos/cimage": "<0.7.19", "movim/moxl": ">=0.8,<=0.10", "movingbytes/social-network": "<=1.2.1", @@ -4122,7 +4122,7 @@ "phpmyfaq/phpmyfaq": "<3.2.5|==3.2.5", "phpoffice/common": "<0.2.9", "phpoffice/phpexcel": "<1.8.1", - "phpoffice/phpspreadsheet": "<1.29.2|>=2,<2.1.1|>=2.2,<2.3", + "phpoffice/phpspreadsheet": "<1.29.4|>=2,<2.1.3|>=2.2,<2.3.2|>=3.3,<3.4", "phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36", "phpservermon/phpservermon": "<3.6", "phpsysinfo/phpsysinfo": "<3.4.3", @@ -4176,7 +4176,7 @@ "rap2hpoutre/laravel-log-viewer": "<0.13", "react/http": ">=0.7,<1.9", "really-simple-plugins/complianz-gdpr": "<6.4.2", - "redaxo/source": "<=5.17.1", + "redaxo/source": "<5.18", "remdex/livehelperchat": "<4.29", "reportico-web/reportico": "<=8.1", "rhukster/dom-sanitizer": "<1.0.7", @@ -4232,7 +4232,7 @@ "slim/slim": "<2.6", "slub/slub-events": "<3.0.3", "smarty/smarty": "<4.5.3|>=5,<5.1.1", - "snipe/snipe-it": "<7.0.10", + "snipe/snipe-it": "<=7.0.13", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", "spatie/browsershot": "<3.57.4", @@ -4243,7 +4243,7 @@ "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", "ssddanbrown/bookstack": "<24.05.1", "starcitizentools/citizen-skin": ">=2.6.3,<2.31", - "statamic/cms": "<4.46|>=5.3,<5.6.2", + "statamic/cms": "<=5.16", "stormpath/sdk": "<9.9.99", "studio-42/elfinder": "<=2.1.64", "studiomitte/friendlycaptcha": "<0.1.4", @@ -4485,20 +4485,20 @@ "type": "tidelift" } ], - "time": "2024-11-13T19:05:18+00:00" + "time": "2024-11-19T21:04:39+00:00" }, { "name": "shipmonk/composer-dependency-analyser", - "version": "1.7.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/shipmonk-rnd/composer-dependency-analyser.git", - "reference": "bca862b2830a453734aee048eb0cdab82e5c9da3" + "reference": "0acd9d94be4d9397055ff012d0abf2ae88072e99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shipmonk-rnd/composer-dependency-analyser/zipball/bca862b2830a453734aee048eb0cdab82e5c9da3", - "reference": "bca862b2830a453734aee048eb0cdab82e5c9da3", + "url": "https://api.github.com/repos/shipmonk-rnd/composer-dependency-analyser/zipball/0acd9d94be4d9397055ff012d0abf2ae88072e99", + "reference": "0acd9d94be4d9397055ff012d0abf2ae88072e99", "shasum": "" }, "require": { @@ -4507,17 +4507,17 @@ "php": "^7.2 || ^8.0" }, "require-dev": { - "editorconfig-checker/editorconfig-checker": "^10.3.0", - "ergebnis/composer-normalize": "^2.19", + "editorconfig-checker/editorconfig-checker": "^10.6.0", + "ergebnis/composer-normalize": "^2.19.0", "ext-dom": "*", "ext-libxml": "*", - "phpcompatibility/php-compatibility": "^9.3", - "phpstan/phpstan": "^1.10.63", - "phpstan/phpstan-phpunit": "^1.1.1", - "phpstan/phpstan-strict-rules": "^1.2.3", - "phpunit/phpunit": "^8.5.28 || ^9.5.20", - "shipmonk/name-collision-detector": "^2.0.0", - "slevomat/coding-standard": "^8.0.1" + "phpcompatibility/php-compatibility": "^9.3.5", + "phpstan/phpstan": "^1.12.3", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "shipmonk/name-collision-detector": "^2.1.1", + "slevomat/coding-standard": "^8.15.0" }, "bin": [ "bin/composer-dependency-analyser" @@ -4549,9 +4549,9 @@ ], "support": { "issues": "https://github.com/shipmonk-rnd/composer-dependency-analyser/issues", - "source": "https://github.com/shipmonk-rnd/composer-dependency-analyser/tree/1.7.0" + "source": "https://github.com/shipmonk-rnd/composer-dependency-analyser/tree/1.8.1" }, - "time": "2024-08-08T08:12:32+00:00" + "time": "2024-11-18T12:58:21+00:00" }, { "name": "slevomat/coding-standard", diff --git a/app/vendor/composer/installed.json b/app/vendor/composer/installed.json index 5ae2bdbb4..08f49694c 100644 --- a/app/vendor/composer/installed.json +++ b/app/vendor/composer/installed.json @@ -2468,12 +2468,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "9f1d9b2460cdd0422e8cfd58763bf3156ad7f487" + "reference": "b33a18b5d222c63472a4b41f6fa3e15e591c9595" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/9f1d9b2460cdd0422e8cfd58763bf3156ad7f487", - "reference": "9f1d9b2460cdd0422e8cfd58763bf3156ad7f487", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/b33a18b5d222c63472a4b41f6fa3e15e591c9595", + "reference": "b33a18b5d222c63472a4b41f6fa3e15e591c9595", "shasum": "" }, "conflict": { @@ -2519,7 +2519,7 @@ "azuracast/azuracast": "<0.18.3", "backdrop/backdrop": "<1.27.3|>=1.28,<1.28.2", "backpack/crud": "<3.4.9", - "backpack/filemanager": "<3.0.9", + "backpack/filemanager": "<2.0.2|>=3,<3.0.9", "bacula-web/bacula-web": "<8.0.0.0-RC2-dev", "badaso/core": "<2.7", "bagisto/bagisto": "<2.1", @@ -2851,7 +2851,7 @@ "mojo42/jirafeau": "<4.4", "mongodb/mongodb": ">=1,<1.9.2", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<4.3.6|>=4.4,<4.4.4", + "moodle/moodle": "<4.3.8|>=4.4,<4.4.4", "mos/cimage": "<0.7.19", "movim/moxl": ">=0.8,<=0.10", "movingbytes/social-network": "<=1.2.1", @@ -2939,7 +2939,7 @@ "phpmyfaq/phpmyfaq": "<3.2.5|==3.2.5", "phpoffice/common": "<0.2.9", "phpoffice/phpexcel": "<1.8.1", - "phpoffice/phpspreadsheet": "<1.29.2|>=2,<2.1.1|>=2.2,<2.3", + "phpoffice/phpspreadsheet": "<1.29.4|>=2,<2.1.3|>=2.2,<2.3.2|>=3.3,<3.4", "phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36", "phpservermon/phpservermon": "<3.6", "phpsysinfo/phpsysinfo": "<3.4.3", @@ -2993,7 +2993,7 @@ "rap2hpoutre/laravel-log-viewer": "<0.13", "react/http": ">=0.7,<1.9", "really-simple-plugins/complianz-gdpr": "<6.4.2", - "redaxo/source": "<=5.17.1", + "redaxo/source": "<5.18", "remdex/livehelperchat": "<4.29", "reportico-web/reportico": "<=8.1", "rhukster/dom-sanitizer": "<1.0.7", @@ -3049,7 +3049,7 @@ "slim/slim": "<2.6", "slub/slub-events": "<3.0.3", "smarty/smarty": "<4.5.3|>=5,<5.1.1", - "snipe/snipe-it": "<7.0.10", + "snipe/snipe-it": "<=7.0.13", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", "spatie/browsershot": "<3.57.4", @@ -3060,7 +3060,7 @@ "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", "ssddanbrown/bookstack": "<24.05.1", "starcitizentools/citizen-skin": ">=2.6.3,<2.31", - "statamic/cms": "<4.46|>=5.3,<5.6.2", + "statamic/cms": "<=5.16", "stormpath/sdk": "<9.9.99", "studio-42/elfinder": "<=2.1.64", "studiomitte/friendlycaptcha": "<0.1.4", @@ -3266,7 +3266,7 @@ "zfr/zfr-oauth2-server-module": "<0.1.2", "zoujingli/thinkadmin": "<=6.1.53" }, - "time": "2024-11-13T19:05:18+00:00", + "time": "2024-11-19T21:04:39+00:00", "default-branch": true, "type": "metapackage", "notification-url": "https://packagist.org/downloads/", @@ -3307,17 +3307,17 @@ }, { "name": "shipmonk/composer-dependency-analyser", - "version": "1.7.0", - "version_normalized": "1.7.0.0", + "version": "1.8.1", + "version_normalized": "1.8.1.0", "source": { "type": "git", "url": "https://github.com/shipmonk-rnd/composer-dependency-analyser.git", - "reference": "bca862b2830a453734aee048eb0cdab82e5c9da3" + "reference": "0acd9d94be4d9397055ff012d0abf2ae88072e99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shipmonk-rnd/composer-dependency-analyser/zipball/bca862b2830a453734aee048eb0cdab82e5c9da3", - "reference": "bca862b2830a453734aee048eb0cdab82e5c9da3", + "url": "https://api.github.com/repos/shipmonk-rnd/composer-dependency-analyser/zipball/0acd9d94be4d9397055ff012d0abf2ae88072e99", + "reference": "0acd9d94be4d9397055ff012d0abf2ae88072e99", "shasum": "" }, "require": { @@ -3326,19 +3326,19 @@ "php": "^7.2 || ^8.0" }, "require-dev": { - "editorconfig-checker/editorconfig-checker": "^10.3.0", - "ergebnis/composer-normalize": "^2.19", + "editorconfig-checker/editorconfig-checker": "^10.6.0", + "ergebnis/composer-normalize": "^2.19.0", "ext-dom": "*", "ext-libxml": "*", - "phpcompatibility/php-compatibility": "^9.3", - "phpstan/phpstan": "^1.10.63", - "phpstan/phpstan-phpunit": "^1.1.1", - "phpstan/phpstan-strict-rules": "^1.2.3", - "phpunit/phpunit": "^8.5.28 || ^9.5.20", - "shipmonk/name-collision-detector": "^2.0.0", - "slevomat/coding-standard": "^8.0.1" - }, - "time": "2024-08-08T08:12:32+00:00", + "phpcompatibility/php-compatibility": "^9.3.5", + "phpstan/phpstan": "^1.12.3", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "shipmonk/name-collision-detector": "^2.1.1", + "slevomat/coding-standard": "^8.15.0" + }, + "time": "2024-11-18T12:58:21+00:00", "bin": [ "bin/composer-dependency-analyser" ], @@ -3370,7 +3370,7 @@ ], "support": { "issues": "https://github.com/shipmonk-rnd/composer-dependency-analyser/issues", - "source": "https://github.com/shipmonk-rnd/composer-dependency-analyser/tree/1.7.0" + "source": "https://github.com/shipmonk-rnd/composer-dependency-analyser/tree/1.8.1" }, "install-path": "../shipmonk/composer-dependency-analyser" }, diff --git a/app/vendor/composer/installed.php b/app/vendor/composer/installed.php index da3013274..a00a6511a 100644 --- a/app/vendor/composer/installed.php +++ b/app/vendor/composer/installed.php @@ -403,7 +403,7 @@ 'roave/security-advisories' => array( 'pretty_version' => 'dev-latest', 'version' => 'dev-latest', - 'reference' => '9f1d9b2460cdd0422e8cfd58763bf3156ad7f487', + 'reference' => 'b33a18b5d222c63472a4b41f6fa3e15e591c9595', 'type' => 'metapackage', 'install_path' => null, 'aliases' => array( @@ -412,9 +412,9 @@ 'dev_requirement' => true, ), 'shipmonk/composer-dependency-analyser' => array( - 'pretty_version' => '1.7.0', - 'version' => '1.7.0.0', - 'reference' => 'bca862b2830a453734aee048eb0cdab82e5c9da3', + 'pretty_version' => '1.8.1', + 'version' => '1.8.1.0', + 'reference' => '0acd9d94be4d9397055ff012d0abf2ae88072e99', 'type' => 'library', 'install_path' => __DIR__ . '/../shipmonk/composer-dependency-analyser', 'aliases' => array(), diff --git a/app/vendor/shipmonk/composer-dependency-analyser/README.md b/app/vendor/shipmonk/composer-dependency-analyser/README.md index 33c79ae38..3f1923671 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/README.md +++ b/app/vendor/shipmonk/composer-dependency-analyser/README.md @@ -5,7 +5,7 @@ - ⚙️ **Configurable:** Fine-grained ignores via PHP config - 🕸️ **Lightweight:** No composer dependencies - 🍰 **Easy-to-use:** No config needed for first try -- ✨ **Compatible:** PHP 7.2 - 8.3 +- ✨ **Compatible:** PHP 7.2 - 8.4 ## Comparison: @@ -49,7 +49,7 @@ Found unused dependencies! ``` ## Detected issues: -This tool reads your `composer.json` and scans all paths listed in `autoload` & `autoload-dev` sections while analysing: +This tool reads your `composer.json` and scans all paths listed in `autoload` & `autoload-dev` sections while analysing you dependencies (both **packages and PHP extensions**). ### Shadowed dependencies - Those are dependencies of your dependencies, which are not listed in `composer.json` @@ -84,6 +84,7 @@ This tool reads your `composer.json` and scans all paths listed in `autoload` & - `--verbose` to see more example classes & usages - `--show-all-usages` to see all usages - `--format` to use different output format, available are: `console` (default), `junit` +- `--disable-ext-analysis` to disable php extensions analysis (e.g. `ext-xml`) - `--ignore-unknown-classes` to globally ignore unknown classes - `--ignore-unknown-functions` to globally ignore unknown functions - `--ignore-shadow-deps` to globally ignore shadow dependencies @@ -128,6 +129,7 @@ return $config //// Adjust analysis ->enableAnalysisOfUnusedDevDependencies() // dev packages are often used only in CI, so this is not enabled by default ->disableReportingUnmatchedIgnores() // do not report ignores that never matched any error + ->disableExtensionsAnalysis() // do not analyse ext-* dependencies //// Use symbols from yaml/xml/neon files // - designed for DIC config files (see below) @@ -160,8 +162,14 @@ Another approach for DIC-only usages is to scan the generated php file, but that ### Scanning codebase located elsewhere: - This can be done by pointing `--composer-json` to `composer.json` of the other codebase -## Limitations: -- Extension dependencies are not analysed (e.g. `ext-json`) +### Disable colored output: +- Set `NO_COLOR` environment variable to disable colored output: +``` +NO_COLOR=1 vendor/bin/composer-dependency-analyser +``` + +## Recommendations: +- For precise `ext-*` analysis, your enabled extensions of your php runtime should be superset of those used in the scanned project ## Contributing: - Check your code by `composer check` @@ -169,5 +177,5 @@ Another approach for DIC-only usages is to scan the generated php file, but that - All functionality must be tested ## Supported PHP versions -- Runtime requires PHP 7.2 - 8.3 +- Runtime requires PHP 7.2 - 8.4 - Scanned codebase should use PHP >= 5.3 diff --git a/app/vendor/shipmonk/composer-dependency-analyser/bin/composer-dependency-analyser b/app/vendor/shipmonk/composer-dependency-analyser/bin/composer-dependency-analyser index 2e39d8171..a93a61d1a 100755 --- a/app/vendor/shipmonk/composer-dependency-analyser/bin/composer-dependency-analyser +++ b/app/vendor/shipmonk/composer-dependency-analyser/bin/composer-dependency-analyser @@ -27,9 +27,10 @@ spl_autoload_register(static function (string $class) use ($psr4Prefix): void { /** @var non-empty-string $cwd */ $cwd = getcwd(); +$noColor = getenv('NO_COLOR') !== false; -$stdOutPrinter = new Printer(STDOUT); -$stdErrPrinter = new Printer(STDERR); +$stdOutPrinter = new Printer(STDOUT, $noColor); +$stdErrPrinter = new Printer(STDERR, $noColor); $initializer = new Initializer($cwd, $stdOutPrinter, $stdErrPrinter); $stopwatch = new Stopwatch(); diff --git a/app/vendor/shipmonk/composer-dependency-analyser/composer.json b/app/vendor/shipmonk/composer-dependency-analyser/composer.json index c2af7b2e6..3e792f077 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/composer.json +++ b/app/vendor/shipmonk/composer-dependency-analyser/composer.json @@ -26,15 +26,15 @@ "require-dev": { "ext-dom": "*", "ext-libxml": "*", - "editorconfig-checker/editorconfig-checker": "^10.3.0", - "ergebnis/composer-normalize": "^2.19", - "phpcompatibility/php-compatibility": "^9.3", - "phpstan/phpstan": "^1.10.63", - "phpstan/phpstan-phpunit": "^1.1.1", - "phpstan/phpstan-strict-rules": "^1.2.3", - "phpunit/phpunit": "^8.5.28 || ^9.5.20", - "shipmonk/name-collision-detector": "^2.0.0", - "slevomat/coding-standard": "^8.0.1" + "editorconfig-checker/editorconfig-checker": "^10.6.0", + "ergebnis/composer-normalize": "^2.19.0", + "phpcompatibility/php-compatibility": "^9.3.5", + "phpstan/phpstan": "^1.12.3", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "shipmonk/name-collision-detector": "^2.1.1", + "slevomat/coding-standard": "^8.15.0" }, "autoload": { "psr-4": { @@ -67,15 +67,20 @@ "@check:types", "@check:tests", "@check:self", - "@check:collisions" + "@check:collisions", + "@check:scripts" ], "check:collisions": "detect-collisions src tests", - "check:composer": "composer normalize --dry-run --no-check-lock --no-update-lock", + "check:composer": [ + "composer normalize --dry-run --no-check-lock --no-update-lock", + "composer validate --strict" + ], "check:cs": "phpcs", "check:ec": "ec src tests", + "check:scripts": "phpstan analyse -vv --ansi --level=6 scripts/*.php", "check:self": "bin/composer-dependency-analyser", "check:tests": "phpunit -vvv tests", - "check:types": "phpstan analyse -vvv --ansi", + "check:types": "phpstan analyse -vv --ansi", "fix:cs": "phpcbf" } } diff --git a/app/vendor/shipmonk/composer-dependency-analyser/src/Analyser.php b/app/vendor/shipmonk/composer-dependency-analyser/src/Analyser.php index 2c984bd0e..d77416c6c 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/src/Analyser.php +++ b/app/vendor/shipmonk/composer-dependency-analyser/src/Analyser.php @@ -45,6 +45,24 @@ class Analyser { + /** + * Those are core PHP extensions, that can never be disabled + * There are more PHP "core" extensions, that are bundled by default, but PHP can be compiled without them + * You can check which are added conditionally in https://github.com/php/php-src/tree/master/ext (see config.w32 files) + */ + private const CORE_EXTENSIONS = [ + 'ext-core', + 'ext-date', + 'ext-json', + 'ext-hash', + 'ext-pcre', + 'ext-phar', + 'ext-reflection', + 'ext-spl', + 'ext-random', + 'ext-standard', + ]; + /** * @var Stopwatch */ @@ -73,7 +91,7 @@ class Analyser private $classmap = []; /** - * package name => is dev dependency + * package or ext-* => is dev dependency * * @var array */ @@ -87,15 +105,29 @@ class Analyser private $ignoredSymbols; /** - * function name => path + * custom function name => path * * @var array */ private $definedFunctions = []; + /** + * kind => [symbol name => ext-*] + * + * @var array> + */ + private $extensionSymbols = []; + + /** + * lowercase symbol name => kind + * + * @var array + */ + private $extensionSymbolKinds = []; + /** * @param array $classLoaders vendorDir => ClassLoader (e.g. result of \Composer\Autoload\ClassLoader::getRegisteredLoaders()) - * @param array $composerJsonDependencies package name => is dev dependency + * @param array $composerJsonDependencies package or ext-* => is dev dependency */ public function __construct( Stopwatch $stopwatch, @@ -107,11 +139,11 @@ public function __construct( { $this->stopwatch = $stopwatch; $this->config = $config; - $this->composerJsonDependencies = $composerJsonDependencies; + $this->composerJsonDependencies = $this->filterDependencies($composerJsonDependencies, $config); $this->vendorDirs = array_keys($classLoaders + [$defaultVendorDir => null]); $this->classLoaders = array_values($classLoaders); - $this->initExistingSymbols(); + $this->initExistingSymbols($config); } /** @@ -129,8 +161,8 @@ public function run(): AnalysisResult $prodOnlyInDevErrors = []; $unusedErrors = []; - $usedPackages = []; - $prodPackagesUsedInProdPath = []; + $usedDependencies = []; + $prodDependenciesUsedInProdPath = []; $usages = []; @@ -143,66 +175,71 @@ public function run(): AnalysisResult foreach ($usedSymbolsByKind as $kind => $usedSymbols) { foreach ($usedSymbols as $usedSymbol => $lineNumbers) { - $usedSymbolNameForIgnoreCheck = $kind === SymbolKind::FUNCTION ? strtolower($usedSymbol) : $usedSymbol; + $normalizedUsedSymbolName = $kind === SymbolKind::FUNCTION ? strtolower($usedSymbol) : $usedSymbol; - if (isset($this->ignoredSymbols[$usedSymbolNameForIgnoreCheck])) { + if (isset($this->ignoredSymbols[$normalizedUsedSymbolName])) { continue; } - $symbolPath = $this->getSymbolPath($usedSymbol, $kind); + if (isset($this->extensionSymbols[$kind][$normalizedUsedSymbolName])) { + $dependencyName = $this->extensionSymbols[$kind][$normalizedUsedSymbolName]; + + } else { + $symbolPath = $this->getSymbolPath($usedSymbol, $kind); - if ($symbolPath === null) { - if ($kind === SymbolKind::CLASSLIKE && !$ignoreList->shouldIgnoreUnknownClass($usedSymbol, $filePath)) { - foreach ($lineNumbers as $lineNumber) { - $unknownClassErrors[$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind); + if ($symbolPath === null) { + if ($kind === SymbolKind::CLASSLIKE && !$ignoreList->shouldIgnoreUnknownClass($usedSymbol, $filePath)) { + foreach ($lineNumbers as $lineNumber) { + $unknownClassErrors[$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind); + } } - } - if ($kind === SymbolKind::FUNCTION && !$ignoreList->shouldIgnoreUnknownFunction($usedSymbol, $filePath)) { - foreach ($lineNumbers as $lineNumber) { - $unknownFunctionErrors[$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind); + if ($kind === SymbolKind::FUNCTION && !$ignoreList->shouldIgnoreUnknownFunction($usedSymbol, $filePath)) { + foreach ($lineNumbers as $lineNumber) { + $unknownFunctionErrors[$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind); + } } + + continue; } - continue; - } + if (!$this->isVendorPath($symbolPath)) { + continue; // local class + } - if (!$this->isVendorPath($symbolPath)) { - continue; // local class + $dependencyName = $this->getPackageNameFromVendorPath($symbolPath); } - $packageName = $this->getPackageNameFromVendorPath($symbolPath); - if ( - $this->isShadowDependency($packageName) - && !$ignoreList->shouldIgnoreError(ErrorType::SHADOW_DEPENDENCY, $filePath, $packageName) + $this->isShadowDependency($dependencyName) + && !$ignoreList->shouldIgnoreError(ErrorType::SHADOW_DEPENDENCY, $filePath, $dependencyName) ) { foreach ($lineNumbers as $lineNumber) { - $shadowErrors[$packageName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind); + $shadowErrors[$dependencyName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind); } } if ( !$isDevFilePath - && $this->isDevDependency($packageName) - && !$ignoreList->shouldIgnoreError(ErrorType::DEV_DEPENDENCY_IN_PROD, $filePath, $packageName) + && $this->isDevDependency($dependencyName) + && !$ignoreList->shouldIgnoreError(ErrorType::DEV_DEPENDENCY_IN_PROD, $filePath, $dependencyName) ) { foreach ($lineNumbers as $lineNumber) { - $devInProdErrors[$packageName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind); + $devInProdErrors[$dependencyName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind); } } if ( !$isDevFilePath - && !$this->isDevDependency($packageName) + && !$this->isDevDependency($dependencyName) ) { - $prodPackagesUsedInProdPath[$packageName] = true; + $prodDependenciesUsedInProdPath[$dependencyName] = true; } - $usedPackages[$packageName] = true; + $usedDependencies[$dependencyName] = true; foreach ($lineNumbers as $lineNumber) { - $usages[$packageName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind); + $usages[$dependencyName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind); } } } @@ -215,19 +252,31 @@ public function run(): AnalysisResult continue; } - $symbolPath = $this->getSymbolPath($forceUsedSymbol, null); + if ( + isset($this->extensionSymbols[SymbolKind::FUNCTION][$forceUsedSymbol]) + || isset($this->extensionSymbols[SymbolKind::CONSTANT][$forceUsedSymbol]) + || isset($this->extensionSymbols[SymbolKind::CLASSLIKE][$forceUsedSymbol]) + ) { + $forceUsedDependency = $this->extensionSymbols[SymbolKind::FUNCTION][$forceUsedSymbol] + ?? $this->extensionSymbols[SymbolKind::CONSTANT][$forceUsedSymbol] + ?? $this->extensionSymbols[SymbolKind::CLASSLIKE][$forceUsedSymbol]; + } else { + $symbolPath = $this->getSymbolPath($forceUsedSymbol, null); + + if ($symbolPath === null || !$this->isVendorPath($symbolPath)) { + continue; + } - if ($symbolPath === null || !$this->isVendorPath($symbolPath)) { - continue; + $forceUsedDependency = $this->getPackageNameFromVendorPath($symbolPath); } - $forceUsedPackage = $this->getPackageNameFromVendorPath($symbolPath); - $usedPackages[$forceUsedPackage] = true; - $forceUsedPackages[$forceUsedPackage] = true; + $usedDependencies[$forceUsedDependency] = true; + $forceUsedPackages[$forceUsedDependency] = true; } if ($this->config->shouldReportUnusedDevDependencies()) { $dependenciesForUnusedAnalysis = array_keys($this->composerJsonDependencies); + } else { $dependenciesForUnusedAnalysis = array_keys(array_filter($this->composerJsonDependencies, static function (bool $devDependency) { return !$devDependency; // dev deps are typically used only in CI @@ -236,7 +285,8 @@ public function run(): AnalysisResult $unusedDependencies = array_diff( $dependenciesForUnusedAnalysis, - array_keys($usedPackages) + array_keys($usedDependencies), + self::CORE_EXTENSIONS ); foreach ($unusedDependencies as $unusedDependency) { @@ -250,9 +300,10 @@ public function run(): AnalysisResult })); $prodPackagesUsedOnlyInDev = array_diff( $prodDependencies, - array_keys($prodPackagesUsedInProdPath), + array_keys($prodDependenciesUsedInProdPath), array_keys($forceUsedPackages), // we dont know where are those used, lets not report them - $unusedDependencies + $unusedDependencies, + self::CORE_EXTENSIONS ); foreach ($prodPackagesUsedOnlyInDev as $prodPackageUsedOnlyInDev) { @@ -340,7 +391,9 @@ private function getUsedSymbolsInFile(string $filePath): array throw new InvalidPathException("Unable to get contents of '$filePath'"); } - return (new UsedSymbolExtractor($code))->parseUsedSymbols(); + return (new UsedSymbolExtractor($code))->parseUsedSymbols( + $this->extensionSymbolKinds + ); } /** @@ -450,7 +503,7 @@ private function normalizePath(string $filePath): string return Path::normalize($filePath); } - private function initExistingSymbols(): void + private function initExistingSymbols(Configuration $config): void { $this->ignoredSymbols = [ // built-in types @@ -485,9 +538,25 @@ private function initExistingSymbols(): void 'Composer\\Autoload\\ClassLoader' => true, ]; - /** @var string $constantName */ - foreach (get_defined_constants() as $constantName => $constantValue) { - $this->ignoredSymbols[$constantName] = true; + /** @var array> $definedConstants */ + $definedConstants = get_defined_constants(true); + + foreach ($definedConstants as $constantExtension => $constants) { + foreach ($constants as $constantName => $_) { + if ($constantExtension === 'user' || !$config->shouldAnalyseExtensions()) { + $this->ignoredSymbols[$constantName] = true; + + } else { + $extensionName = $this->getNormalizedExtensionName($constantExtension); + + if (in_array($extensionName, self::CORE_EXTENSIONS, true)) { + $this->ignoredSymbols[$constantName] = true; + } else { + $this->extensionSymbols[SymbolKind::CONSTANT][$constantName] = $extensionName; + $this->extensionSymbolKinds[strtolower($constantName)] = SymbolKind::CONSTANT; + } + } + } } foreach (get_defined_functions() as $functionNames) { @@ -495,10 +564,19 @@ private function initExistingSymbols(): void $reflectionFunction = new ReflectionFunction($functionName); $functionFilePath = $reflectionFunction->getFileName(); - if ($reflectionFunction->getExtension() === null && is_string($functionFilePath)) { - $this->definedFunctions[$functionName] = Path::normalize($functionFilePath); + if ($reflectionFunction->getExtension() === null) { + if (is_string($functionFilePath)) { + $this->definedFunctions[$functionName] = Path::normalize($functionFilePath); + } } else { - $this->ignoredSymbols[$functionName] = true; + $extensionName = $this->getNormalizedExtensionName($reflectionFunction->getExtension()->name); + + if (in_array($extensionName, self::CORE_EXTENSIONS, true) || !$config->shouldAnalyseExtensions()) { + $this->ignoredSymbols[$functionName] = true; + } else { + $this->extensionSymbols[SymbolKind::FUNCTION][$functionName] = $extensionName; + $this->extensionSymbolKinds[$functionName] = SymbolKind::FUNCTION; + } } } } @@ -511,11 +589,44 @@ private function initExistingSymbols(): void foreach ($classLikes as $classLikeNames) { foreach ($classLikeNames as $classLikeName) { - if ((new ReflectionClass($classLikeName))->getExtension() !== null) { - $this->ignoredSymbols[$classLikeName] = true; + $classReflection = new ReflectionClass($classLikeName); + + if ($classReflection->getExtension() !== null) { + $extensionName = $this->getNormalizedExtensionName($classReflection->getExtension()->name); + + if (in_array($extensionName, self::CORE_EXTENSIONS, true) || !$config->shouldAnalyseExtensions()) { + $this->ignoredSymbols[$classLikeName] = true; + } else { + $this->extensionSymbols[SymbolKind::CLASSLIKE][$classLikeName] = $extensionName; + $this->extensionSymbolKinds[strtolower($classLikeName)] = SymbolKind::CLASSLIKE; + } } } } } + private function getNormalizedExtensionName(string $extension): string + { + return 'ext-' . ComposerJson::normalizeExtensionName($extension); + } + + /** + * @param array $dependencies + * @return array + */ + private function filterDependencies(array $dependencies, Configuration $config): array + { + $filtered = []; + + foreach ($dependencies as $dependency => $isDevDependency) { + if (!$config->shouldAnalyseExtensions() && strpos($dependency, 'ext-') === 0) { + continue; + } + + $filtered[$dependency] = $isDevDependency; + } + + return $filtered; + } + } diff --git a/app/vendor/shipmonk/composer-dependency-analyser/src/Cli.php b/app/vendor/shipmonk/composer-dependency-analyser/src/Cli.php index f4d90edfa..ceb7f269a 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/src/Cli.php +++ b/app/vendor/shipmonk/composer-dependency-analyser/src/Cli.php @@ -3,11 +3,15 @@ namespace ShipMonk\ComposerDependencyAnalyser; use ShipMonk\ComposerDependencyAnalyser\Exception\InvalidCliException; +use function array_keys; use function array_slice; use function is_dir; use function is_file; +use function levenshtein; +use function strlen; use function strpos; use function substr; +use function trim; class Cli { @@ -16,6 +20,7 @@ class Cli 'version' => false, 'help' => false, 'verbose' => false, + 'disable-ext-analysis' => false, 'ignore-shadow-deps' => false, 'ignore-unused-deps' => false, 'ignore-dev-in-prod-deps' => false, @@ -54,7 +59,8 @@ public function __construct(string $cwd, array $argv) $startsWithDashDash = strpos($arg, '--') === 0; if ($startsWithDash && !$startsWithDashDash) { - throw new InvalidCliException("Unknown option $arg, see --help"); + $suggestedOption = $this->suggestOption($arg); + throw new InvalidCliException("Unknown option $arg, $suggestedOption"); } if (!$startsWithDashDash) { @@ -62,7 +68,8 @@ public function __construct(string $cwd, array $argv) throw new InvalidCliException("Cannot pass paths ($arg) to analyse as arguments, use --config instead."); } - throw new InvalidCliException("Unknown argument $arg, see --help"); + $suggestedOption = $this->suggestOption($arg); + throw new InvalidCliException("Unknown argument $arg, $suggestedOption"); } /** @var string $noDashesArg this is never false as we know it starts with -- */ @@ -70,7 +77,8 @@ public function __construct(string $cwd, array $argv) $optionName = $this->getKnownOptionName($noDashesArg); if ($optionName === null) { - throw new InvalidCliException("Unknown option $arg, see --help"); + $suggestedOption = $this->suggestOption($noDashesArg); + throw new InvalidCliException("Unknown option $arg, $suggestedOption"); } if ($this->isOptionWithRequiredValue($optionName)) { @@ -91,6 +99,10 @@ public function __construct(string $cwd, array $argv) $this->providedOptions[$optionName] = $optionArgument; } } else { + if ($this->getOptionArgumentAfterAssign($arg) !== null) { + throw new InvalidCliException("Option --$optionName does not accept arguments, see --help"); + } + $this->providedOptions[$optionName] = true; } } @@ -115,7 +127,10 @@ private function isOptionWithRequiredValue(string $optionName): bool private function getKnownOptionName(string $option): ?string { foreach (self::OPTIONS as $knownOption => $needsArgument) { - if (strpos($option, $knownOption) === 0) { + if ( + strpos($option, $knownOption) === 0 + && (strlen($option) === strlen($knownOption) || $option[strlen($knownOption)] === '=') + ) { return $knownOption; } } @@ -139,6 +154,10 @@ public function getProvidedOptions(): CliOptions $options->verbose = true; } + if (isset($this->providedOptions['disable-ext-analysis'])) { + $options->disableExtAnalysis = true; + } + if (isset($this->providedOptions['ignore-shadow-deps'])) { $options->ignoreShadowDeps = true; } @@ -186,4 +205,29 @@ public function getProvidedOptions(): CliOptions return $options; } + /** + * Params inspired by tracy/tracy + */ + private function suggestOption(string $input): string + { + $value = trim($input, '-'); + $options = array_keys(self::OPTIONS); + + $bestGuess = null; + $minDistance = (strlen($value) / 4 + 1) * 10 + .1; + + foreach ($options as $option) { + $distance = levenshtein($option, $value, 9, 11, 9); + + if ($distance > 0 && $distance < $minDistance) { + $minDistance = $distance; + $bestGuess = $option; + } + } + + return $bestGuess === null + ? 'see --help' + : "did you mean --$bestGuess?"; + } + } diff --git a/app/vendor/shipmonk/composer-dependency-analyser/src/CliOptions.php b/app/vendor/shipmonk/composer-dependency-analyser/src/CliOptions.php index 3656225ee..3eeaf15b5 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/src/CliOptions.php +++ b/app/vendor/shipmonk/composer-dependency-analyser/src/CliOptions.php @@ -20,6 +20,11 @@ class CliOptions */ public $verbose = null; + /** + * @var true|null + */ + public $disableExtAnalysis = null; + /** * @var true|null */ diff --git a/app/vendor/shipmonk/composer-dependency-analyser/src/ComposerJson.php b/app/vendor/shipmonk/composer-dependency-analyser/src/ComposerJson.php index 4e1d48f5c..a35149924 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/src/ComposerJson.php +++ b/app/vendor/shipmonk/composer-dependency-analyser/src/ComposerJson.php @@ -23,6 +23,7 @@ use function realpath; use function str_replace; use function strpos; +use function strtolower; use function strtr; use function trim; use const ARRAY_FILTER_USE_KEY; @@ -44,7 +45,7 @@ class ComposerJson public $composerAutoloadPath; /** - * Package => isDev + * Package or ext-* => isDev * * @readonly * @var array @@ -99,20 +100,54 @@ public function __construct( $this->extractAutoloadExcludeRegexes($basePath, $composerJsonData['autoload-dev']['exclude-from-classmap'] ?? [], true) ); + $filterExtensions = static function (string $dependency): bool { + return strpos($dependency, 'ext-') === 0; + }; $filterPackages = static function (string $package): bool { return strpos($package, '/') !== false; }; - $this->dependencies = array_merge( + $this->dependencies = $this->normalizeNames(array_merge( array_fill_keys(array_keys(array_filter($requiredPackages, $filterPackages, ARRAY_FILTER_USE_KEY)), false), - array_fill_keys(array_keys(array_filter($requiredDevPackages, $filterPackages, ARRAY_FILTER_USE_KEY)), true) - ); + array_fill_keys(array_keys(array_filter($requiredPackages, $filterExtensions, ARRAY_FILTER_USE_KEY)), false), + array_fill_keys(array_keys(array_filter($requiredDevPackages, $filterPackages, ARRAY_FILTER_USE_KEY)), true), + array_fill_keys(array_keys(array_filter($requiredDevPackages, $filterExtensions, ARRAY_FILTER_USE_KEY)), true) + )); if (count($this->dependencies) === 0) { - throw new InvalidConfigException("No packages found in $composerJsonPath file."); + throw new InvalidConfigException("No dependencies found in $composerJsonPath file."); } } + /** + * @param array $dependencies + * @return array + */ + private function normalizeNames(array $dependencies): array + { + $normalized = []; + + foreach ($dependencies as $dependency => $isDev) { + if (strpos($dependency, 'ext-') === 0) { + $key = self::normalizeExtensionName($dependency); + } else { + $key = $dependency; + } + + $normalized[$key] = $isDev; + } + + return $normalized; + } + + /** + * Zend Opcache -> zend-opcache + */ + public static function normalizeExtensionName(string $extension): string + { + return str_replace(' ', '-', strtolower($extension)); + } + /** * @param array> $autoload * @return array @@ -196,10 +231,8 @@ private function resolveAutoloadExclude(string $basePath, string $pathPattern): $path = preg_replace_callback( '{^((?:(?:\\\\\\.){1,2}+/)+)}', static function ($matches) use (&$updir): string { - if (isset($matches[1]) && $matches[1] !== '') { - // undo preg_quote for the matched string - $updir = str_replace('\\.', '.', $matches[1]); - } + // undo preg_quote for the matched string + $updir = str_replace('\\.', '.', $matches[1]); return ''; }, diff --git a/app/vendor/shipmonk/composer-dependency-analyser/src/Config/Configuration.php b/app/vendor/shipmonk/composer-dependency-analyser/src/Config/Configuration.php index 7fb72918c..8883145e5 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/src/Config/Configuration.php +++ b/app/vendor/shipmonk/composer-dependency-analyser/src/Config/Configuration.php @@ -14,6 +14,11 @@ class Configuration { + /** + * @var bool + */ + private $extensionsAnalysis = true; + /** * @var bool */ @@ -67,12 +72,12 @@ class Configuration /** * @var array> */ - private $ignoredErrorsOnPackage = []; + private $ignoredErrorsOnDependency = []; /** * @var array>> */ - private $ignoredErrorsOnPackageAndPath = []; + private $ignoredErrorsOnDependencyAndPath = []; /** * @var list @@ -94,6 +99,17 @@ class Configuration */ private $ignoredUnknownFunctionsRegexes = []; + /** + * Disable analysis of ext-* dependencies + * + * @return $this + */ + public function disableExtensionsAnalysis(): self + { + $this->extensionsAnalysis = false; + return $this; + } + /** * @return $this */ @@ -103,6 +119,9 @@ public function disableComposerAutoloadPathScan(): self return $this; } + /** + * @return $this + */ public function disableReportingUnmatchedIgnores(): self { $this->reportUnmatchedIgnores = false; @@ -277,13 +296,34 @@ public function ignoreErrorsOnPaths(array $paths, array $errorTypes): self public function ignoreErrorsOnPackage(string $packageName, array $errorTypes): self { $this->checkPackageName($packageName); - $this->checkAllowedErrorTypeForPackageIgnore($errorTypes); + $this->ignoreErrorsOnDependency($packageName, $errorTypes); + return $this; + } - $previousErrorTypes = $this->ignoredErrorsOnPackage[$packageName] ?? []; - $this->ignoredErrorsOnPackage[$packageName] = array_merge($previousErrorTypes, $errorTypes); + /** + * @param list $errorTypes + * @return $this + * @throws InvalidConfigException + */ + public function ignoreErrorsOnExtension(string $extension, array $errorTypes): self + { + $this->checkExtensionName($extension); + $this->ignoreErrorsOnDependency($extension, $errorTypes); return $this; } + /** + * @param list $errorTypes + * @throws InvalidConfigException + */ + private function ignoreErrorsOnDependency(string $dependency, array $errorTypes): void + { + $this->checkAllowedErrorTypeForPackageIgnore($errorTypes); + + $previousErrorTypes = $this->ignoredErrorsOnDependency[$dependency] ?? []; + $this->ignoredErrorsOnDependency[$dependency] = array_merge($previousErrorTypes, $errorTypes); + } + /** * @param list $packageNames * @param list $errorTypes @@ -299,6 +339,21 @@ public function ignoreErrorsOnPackages(array $packageNames, array $errorTypes): return $this; } + /** + * @param list $extensions + * @param list $errorTypes + * @return $this + * @throws InvalidConfigException + */ + public function ignoreErrorsOnExtensions(array $extensions, array $errorTypes): self + { + foreach ($extensions as $extension) { + $this->ignoreErrorsOnExtension($extension, $errorTypes); + } + + return $this; + } + /** * @param list $errorTypes * @return $this @@ -308,14 +363,37 @@ public function ignoreErrorsOnPackages(array $packageNames, array $errorTypes): public function ignoreErrorsOnPackageAndPath(string $packageName, string $path, array $errorTypes): self { $this->checkPackageName($packageName); + $this->ignoreErrorsOnDependencyAndPath($packageName, $path, $errorTypes); + return $this; + } + + /** + * @param list $errorTypes + * @return $this + * @throws InvalidPathException + * @throws InvalidConfigException + */ + public function ignoreErrorsOnExtensionAndPath(string $extension, string $path, array $errorTypes): self + { + $this->checkExtensionName($extension); + $this->ignoreErrorsOnDependencyAndPath($extension, $path, $errorTypes); + return $this; + } + + /** + * @param list $errorTypes + * @throws InvalidPathException + * @throws InvalidConfigException + */ + private function ignoreErrorsOnDependencyAndPath(string $dependency, string $path, array $errorTypes): void + { $this->checkAllowedErrorTypeForPathIgnore($errorTypes); $this->checkAllowedErrorTypeForPackageIgnore($errorTypes); $realpath = Path::realpath($path); - $previousErrorTypes = $this->ignoredErrorsOnPackageAndPath[$packageName][$realpath] ?? []; - $this->ignoredErrorsOnPackageAndPath[$packageName][$realpath] = array_merge($previousErrorTypes, $errorTypes); - return $this; + $previousErrorTypes = $this->ignoredErrorsOnDependencyAndPath[$dependency][$realpath] ?? []; + $this->ignoredErrorsOnDependencyAndPath[$dependency][$realpath] = array_merge($previousErrorTypes, $errorTypes); } /** @@ -334,6 +412,22 @@ public function ignoreErrorsOnPackageAndPaths(string $packageName, array $paths, return $this; } + /** + * @param list $paths + * @param list $errorTypes + * @return $this + * @throws InvalidPathException + * @throws InvalidConfigException + */ + public function ignoreErrorsOnExtensionAndPaths(string $extension, array $paths, array $errorTypes): self + { + foreach ($paths as $path) { + $this->ignoreErrorsOnExtensionAndPath($extension, $path, $errorTypes); + } + + return $this; + } + /** * @param list $packages * @param list $paths @@ -351,6 +445,23 @@ public function ignoreErrorsOnPackagesAndPaths(array $packages, array $paths, ar return $this; } + /** + * @param list $extensions + * @param list $paths + * @param list $errorTypes + * @return $this + * @throws InvalidPathException + * @throws InvalidConfigException + */ + public function ignoreErrorsOnExtensionsAndPaths(array $extensions, array $paths, array $errorTypes): self + { + foreach ($extensions as $extension) { + $this->ignoreErrorsOnExtensionAndPaths($extension, $paths, $errorTypes); + } + + return $this; + } + /** * @param list $classNames * @return $this @@ -406,8 +517,8 @@ public function getIgnoreList(): IgnoreList return new IgnoreList( $this->ignoredErrors, $this->ignoredErrorsOnPath, - $this->ignoredErrorsOnPackage, - $this->ignoredErrorsOnPackageAndPath, + $this->ignoredErrorsOnDependency, + $this->ignoredErrorsOnDependencyAndPath, $this->ignoredUnknownClasses, $this->ignoredUnknownClassesRegexes, $this->ignoredUnknownFunctions, @@ -439,6 +550,11 @@ public function getPathsToScan(): array return $this->pathsToScan; } + public function shouldAnalyseExtensions(): bool + { + return $this->extensionsAnalysis; + } + public function shouldScanComposerAutoloadPaths(): bool { return $this->scanComposerAutoloadPaths; @@ -476,6 +592,16 @@ private function isFilepathWithinPath(string $filePath, string $path): bool return strpos($filePath, $path) === 0; } + /** + * @throws InvalidConfigException + */ + private function checkExtensionName(string $extension): void + { + if (strpos($extension, 'ext-') !== 0) { + throw new InvalidConfigException("Invalid php extension dependency name '$extension', it is expected to start with ext-"); + } + } + /** * @throws InvalidConfigException */ diff --git a/app/vendor/shipmonk/composer-dependency-analyser/src/Config/Ignore/IgnoreList.php b/app/vendor/shipmonk/composer-dependency-analyser/src/Config/Ignore/IgnoreList.php index 59da5a544..92e3e8ac2 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/src/Config/Ignore/IgnoreList.php +++ b/app/vendor/shipmonk/composer-dependency-analyser/src/Config/Ignore/IgnoreList.php @@ -25,12 +25,12 @@ class IgnoreList /** * @var array> */ - private $ignoredErrorsOnPackage = []; + private $ignoredErrorsOnDependency = []; /** * @var array>> */ - private $ignoredErrorsOnPackageAndPath = []; + private $ignoredErrorsOnDependencyAndPath = []; /** * @var array @@ -55,8 +55,8 @@ class IgnoreList /** * @param list $ignoredErrors * @param array> $ignoredErrorsOnPath - * @param array> $ignoredErrorsOnPackage - * @param array>> $ignoredErrorsOnPackageAndPath + * @param array> $ignoredErrorsOnDependency + * @param array>> $ignoredErrorsOnDependencyAndPath * @param list $ignoredUnknownClasses * @param list $ignoredUnknownClassesRegexes * @param list $ignoredUnknownFunctions @@ -65,8 +65,8 @@ class IgnoreList public function __construct( array $ignoredErrors, array $ignoredErrorsOnPath, - array $ignoredErrorsOnPackage, - array $ignoredErrorsOnPackageAndPath, + array $ignoredErrorsOnDependency, + array $ignoredErrorsOnDependencyAndPath, array $ignoredUnknownClasses, array $ignoredUnknownClassesRegexes, array $ignoredUnknownFunctions, @@ -79,13 +79,13 @@ public function __construct( $this->ignoredErrorsOnPath[$path] = array_fill_keys($errorTypes, false); } - foreach ($ignoredErrorsOnPackage as $packageName => $errorTypes) { - $this->ignoredErrorsOnPackage[$packageName] = array_fill_keys($errorTypes, false); + foreach ($ignoredErrorsOnDependency as $dependency => $errorTypes) { + $this->ignoredErrorsOnDependency[$dependency] = array_fill_keys($errorTypes, false); } - foreach ($ignoredErrorsOnPackageAndPath as $packageName => $paths) { + foreach ($ignoredErrorsOnDependencyAndPath as $dependency => $paths) { foreach ($paths as $path => $errorTypes) { - $this->ignoredErrorsOnPackageAndPath[$packageName][$path] = array_fill_keys($errorTypes, false); + $this->ignoredErrorsOnDependencyAndPath[$dependency][$path] = array_fill_keys($errorTypes, false); } } @@ -116,7 +116,7 @@ public function getUnusedIgnores(): array } } - foreach ($this->ignoredErrorsOnPackage as $packageName => $errorTypes) { + foreach ($this->ignoredErrorsOnDependency as $packageName => $errorTypes) { foreach ($errorTypes as $errorType => $ignored) { if (!$ignored) { $unused[] = new UnusedErrorIgnore($errorType, null, $packageName); @@ -124,7 +124,7 @@ public function getUnusedIgnores(): array } } - foreach ($this->ignoredErrorsOnPackageAndPath as $packageName => $paths) { + foreach ($this->ignoredErrorsOnDependencyAndPath as $packageName => $paths) { foreach ($paths as $path => $errorTypes) { foreach ($errorTypes as $errorType => $ignored) { if (!$ignored) { @@ -240,12 +240,12 @@ private function shouldIgnoreUnknownFunctionByRegex(string $function): bool /** * @param ErrorType::SHADOW_DEPENDENCY|ErrorType::UNUSED_DEPENDENCY|ErrorType::DEV_DEPENDENCY_IN_PROD|ErrorType::PROD_DEPENDENCY_ONLY_IN_DEV $errorType */ - public function shouldIgnoreError(string $errorType, ?string $realPath, ?string $packageName): bool + public function shouldIgnoreError(string $errorType, ?string $realPath, ?string $dependency): bool { $ignoredGlobally = $this->shouldIgnoreErrorGlobally($errorType); $ignoredByPath = $realPath !== null && $this->shouldIgnoreErrorOnPath($errorType, $realPath); - $ignoredByPackage = $packageName !== null && $this->shouldIgnoreErrorOnPackage($errorType, $packageName); - $ignoredByPackageAndPath = $realPath !== null && $packageName !== null && $this->shouldIgnoreErrorOnPackageAndPath($errorType, $packageName, $realPath); + $ignoredByPackage = $dependency !== null && $this->shouldIgnoreErrorOnDependency($errorType, $dependency); + $ignoredByPackageAndPath = $realPath !== null && $dependency !== null && $this->shouldIgnoreErrorOnDependencyAndPath($errorType, $dependency, $realPath); return $ignoredGlobally || $ignoredByPackageAndPath || $ignoredByPath || $ignoredByPackage; } @@ -281,10 +281,10 @@ private function shouldIgnoreErrorOnPath(string $errorType, string $filePath): b /** * @param ErrorType::* $errorType */ - private function shouldIgnoreErrorOnPackage(string $errorType, string $packageName): bool + private function shouldIgnoreErrorOnDependency(string $errorType, string $dependency): bool { - if (isset($this->ignoredErrorsOnPackage[$packageName][$errorType])) { - $this->ignoredErrorsOnPackage[$packageName][$errorType] = true; + if (isset($this->ignoredErrorsOnDependency[$dependency][$errorType])) { + $this->ignoredErrorsOnDependency[$dependency][$errorType] = true; return true; } @@ -294,12 +294,12 @@ private function shouldIgnoreErrorOnPackage(string $errorType, string $packageNa /** * @param ErrorType::* $errorType */ - private function shouldIgnoreErrorOnPackageAndPath(string $errorType, string $packageName, string $filePath): bool + private function shouldIgnoreErrorOnDependencyAndPath(string $errorType, string $packageName, string $filePath): bool { - if (isset($this->ignoredErrorsOnPackageAndPath[$packageName])) { - foreach ($this->ignoredErrorsOnPackageAndPath[$packageName] as $path => $errorTypes) { + if (isset($this->ignoredErrorsOnDependencyAndPath[$packageName])) { + foreach ($this->ignoredErrorsOnDependencyAndPath[$packageName] as $path => $errorTypes) { if ($this->isFilepathWithinPath($filePath, $path) && isset($errorTypes[$errorType])) { - $this->ignoredErrorsOnPackageAndPath[$packageName][$path][$errorType] = true; + $this->ignoredErrorsOnDependencyAndPath[$packageName][$path][$errorType] = true; return true; } } diff --git a/app/vendor/shipmonk/composer-dependency-analyser/src/Initializer.php b/app/vendor/shipmonk/composer-dependency-analyser/src/Initializer.php index 8379b86f9..3c3e36c19 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/src/Initializer.php +++ b/app/vendor/shipmonk/composer-dependency-analyser/src/Initializer.php @@ -52,6 +52,8 @@ class Initializer --ignore-shadow-deps Ignore all shadow dependency issues --ignore-dev-in-prod-deps Ignore all dev dependency in production code issues --ignore-prod-only-in-dev-deps Ignore all prod dependency used only in dev paths issues + + --disable-ext-analysis Disable analysis of php extensions (e.g. ext-xml) EOD; /** @@ -116,6 +118,7 @@ public function initConfiguration( $config = new Configuration(); } + $disableExtAnalysis = $options->disableExtAnalysis === true; $ignoreUnknownClasses = $options->ignoreUnknownClasses === true; $ignoreUnknownFunctions = $options->ignoreUnknownFunctions === true; $ignoreUnused = $options->ignoreUnusedDeps === true; @@ -123,6 +126,10 @@ public function initConfiguration( $ignoreDevInProd = $options->ignoreDevInProdDeps === true; $ignoreProdOnlyInDev = $options->ignoreProdOnlyInDevDeps === true; + if ($disableExtAnalysis) { + $config->disableExtensionsAnalysis(); + } + if ($ignoreUnknownClasses) { $config->ignoreErrors([ErrorType::UNKNOWN_CLASS]); } diff --git a/app/vendor/shipmonk/composer-dependency-analyser/src/Printer.php b/app/vendor/shipmonk/composer-dependency-analyser/src/Printer.php index dc6684272..1bb9211ec 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/src/Printer.php +++ b/app/vendor/shipmonk/composer-dependency-analyser/src/Printer.php @@ -28,12 +28,18 @@ class Printer */ private $resource; + /** + * @var bool + */ + private $noColor; + /** * @param resource $resource */ - public function __construct($resource) + public function __construct($resource, bool $noColor) { $this->resource = $resource; + $this->noColor = $noColor; } public function printLine(string $string): void @@ -52,7 +58,11 @@ public function print(string $string): void private function colorize(string $string): string { - return str_replace(array_keys(self::COLORS), array_values(self::COLORS), $string); + return str_replace( + array_keys(self::COLORS), + $this->noColor ? '' : array_values(self::COLORS), + $string + ); } } diff --git a/app/vendor/shipmonk/composer-dependency-analyser/src/UsedSymbolExtractor.php b/app/vendor/shipmonk/composer-dependency-analyser/src/UsedSymbolExtractor.php index 8f386c85c..c2a5c54f4 100644 --- a/app/vendor/shipmonk/composer-dependency-analyser/src/UsedSymbolExtractor.php +++ b/app/vendor/shipmonk/composer-dependency-analyser/src/UsedSymbolExtractor.php @@ -8,6 +8,7 @@ use function ltrim; use function strlen; use function strpos; +use function strtolower; use function substr; use function token_get_all; use const PHP_VERSION_ID; @@ -19,14 +20,18 @@ use const T_CURLY_OPEN; use const T_DOC_COMMENT; use const T_DOLLAR_OPEN_CURLY_BRACES; +use const T_DOUBLE_COLON; use const T_ENUM; use const T_FUNCTION; +use const T_INSTEADOF; use const T_INTERFACE; use const T_NAME_FULLY_QUALIFIED; use const T_NAME_QUALIFIED; use const T_NAMESPACE; use const T_NEW; use const T_NS_SEPARATOR; +use const T_NULLSAFE_OBJECT_OPERATOR; +use const T_OBJECT_OPERATOR; use const T_STRING; use const T_TRAIT; use const T_USE; @@ -62,10 +67,13 @@ public function __construct(string $code) * It does not produce any local names in current namespace * - this results in very limited functionality in files without namespace * + * @param array $extensionSymbols * @return array>> * @license Inspired by https://github.com/doctrine/annotations/blob/2.0.0/lib/Doctrine/Common/Annotations/TokenParser.php */ - public function parseUsedSymbols(): array + public function parseUsedSymbols( + array $extensionSymbols + ): array { $usedSymbols = []; $useStatements = []; @@ -107,13 +115,16 @@ public function parseUsedSymbols(): array break; case PHP_VERSION_ID >= 80000 ? T_NAMESPACE : -1: + // namespace change $inGlobalScope = false; - $useStatements = []; // reset use statements on namespace change + $useStatements = []; + $useStatementKinds = []; break; case PHP_VERSION_ID >= 80000 ? T_NAME_FULLY_QUALIFIED : -1: $symbolName = $this->normalizeBackslash($token[1]); - $kind = $this->getFqnSymbolKind($this->pointer - 2, $this->pointer, $inAttributeSquareLevel !== null); + $lowerSymbolName = strtolower($symbolName); + $kind = $extensionSymbols[$lowerSymbolName] ?? $this->getFqnSymbolKind($this->pointer - 2, $this->pointer, $inAttributeSquareLevel !== null); $usedSymbols[$kind][$symbolName][] = $token[2]; break; @@ -122,24 +133,42 @@ public function parseUsedSymbols(): array if (isset($useStatements[$neededAlias])) { $symbolName = $useStatements[$neededAlias] . substr($token[1], strlen($neededAlias)); - $kind = $this->getFqnSymbolKind($this->pointer - 2, $this->pointer, $inAttributeSquareLevel !== null); - $usedSymbols[$kind][$symbolName][] = $token[2]; - } elseif ($inGlobalScope) { $symbolName = $token[1]; - $kind = $this->getFqnSymbolKind($this->pointer - 2, $this->pointer, $inAttributeSquareLevel !== null); - $usedSymbols[$kind][$symbolName][] = $token[2]; + } else { + break; } + $lowerSymbolName = strtolower($symbolName); + $kind = $extensionSymbols[$lowerSymbolName] ?? $this->getFqnSymbolKind($this->pointer - 2, $this->pointer, $inAttributeSquareLevel !== null); + $usedSymbols[$kind][$symbolName][] = $token[2]; + break; case PHP_VERSION_ID >= 80000 ? T_STRING : -1: $name = $token[1]; + $lowerName = strtolower($name); + $pointerBeforeName = $this->pointer - 2; + $pointerAfterName = $this->pointer; + + if (!$this->canBeSymbolName($pointerBeforeName, $pointerAfterName)) { + break; + } if (isset($useStatements[$name])) { $symbolName = $useStatements[$name]; $kind = $useStatementKinds[$name]; $usedSymbols[$kind][$symbolName][] = $token[2]; + + } elseif (isset($extensionSymbols[$lowerName])) { + $symbolName = $name; + $kind = $extensionSymbols[$lowerName]; + + if (!$inGlobalScope && $kind === SymbolKind::CLASSLIKE) { + break; // cannot use class-like symbols in non-global scope when not imported + } + + $usedSymbols[$kind][$symbolName][] = $token[2]; } break; @@ -149,8 +178,10 @@ public function parseUsedSymbols(): array $nextName = $this->parseNameForOldPhp(); if (substr($nextName, 0, 1) !== '\\') { // not a namespace-relative name, but a new namespace declaration - $useStatements = []; // reset use statements on namespace change + // namespace change $inGlobalScope = false; + $useStatements = []; + $useStatementKinds = []; } break; @@ -158,9 +189,10 @@ public function parseUsedSymbols(): array case PHP_VERSION_ID < 80000 ? T_NS_SEPARATOR : -1: $pointerBeforeName = $this->pointer - 2; $symbolName = $this->normalizeBackslash($this->parseNameForOldPhp()); + $lowerSymbolName = strtolower($symbolName); if ($symbolName !== '') { // e.g. \array (NS separator followed by not-a-name) - $kind = $this->getFqnSymbolKind($pointerBeforeName, $this->pointer - 1, false); + $kind = $extensionSymbols[$lowerSymbolName] ?? $this->getFqnSymbolKind($pointerBeforeName, $this->pointer - 1, false); $usedSymbols[$kind][$symbolName][] = $token[2]; } @@ -169,23 +201,39 @@ public function parseUsedSymbols(): array case PHP_VERSION_ID < 80000 ? T_STRING : -1: $pointerBeforeName = $this->pointer - 2; $name = $this->parseNameForOldPhp(); + $lowerName = strtolower($name); + $pointerAfterName = $this->pointer - 1; + + if (!$this->canBeSymbolName($pointerBeforeName, $pointerAfterName)) { + break; + } if (isset($useStatements[$name])) { // unqualified name $symbolName = $useStatements[$name]; $kind = $useStatementKinds[$name]; $usedSymbols[$kind][$symbolName][] = $token[2]; + } elseif (isset($extensionSymbols[$lowerName])) { + $symbolName = $name; + $kind = $extensionSymbols[$lowerName]; + + if (!$inGlobalScope && $kind === SymbolKind::CLASSLIKE) { + break; // cannot use class-like symbols in non-global scope when not imported + } + + $usedSymbols[$kind][$symbolName][] = $token[2]; + } else { [$neededAlias] = explode('\\', $name, 2); if (isset($useStatements[$neededAlias])) { // qualified name $symbolName = $useStatements[$neededAlias] . substr($name, strlen($neededAlias)); - $kind = $this->getFqnSymbolKind($pointerBeforeName, $this->pointer - 1, false); + $kind = $this->getFqnSymbolKind($pointerBeforeName, $pointerAfterName, false); $usedSymbols[$kind][$symbolName][] = $token[2]; } elseif ($inGlobalScope && strpos($name, '\\') !== false) { $symbolName = $name; - $kind = $this->getFqnSymbolKind($pointerBeforeName, $this->pointer - 1, false); + $kind = $this->getFqnSymbolKind($pointerBeforeName, $pointerAfterName, false); $usedSymbols[$kind][$symbolName][] = $token[2]; } } @@ -216,7 +264,7 @@ public function parseUsedSymbols(): array } } - return $usedSymbols; // @phpstan-ignore-line Not enough precise analysis "Offset 'kind' (1|2|3) does not accept type int<1, max>" + return $usedSymbols; } /** @@ -346,44 +394,89 @@ private function getFqnSymbolKind( return SymbolKind::CLASSLIKE; } + $tokenBeforeName = $this->getTokenBefore($pointerBeforeName); + $tokenAfterName = $this->getTokenAfter($pointerAfterName); + + if ( + $tokenAfterName === '(' + && $tokenBeforeName[0] !== T_NEW // eliminate new \ClassName( + ) { + return SymbolKind::FUNCTION; + } + + return SymbolKind::CLASSLIKE; // constant may fall here, this is eliminated later + } + + private function canBeSymbolName( + int $pointerBeforeName, + int $pointerAfterName + ): bool + { + $tokenBeforeName = $this->getTokenBefore($pointerBeforeName); + $tokenAfterName = $this->getTokenAfter($pointerAfterName); + + if ( + $tokenBeforeName[0] === T_DOUBLE_COLON + || $tokenBeforeName[0] === T_INSTEADOF + || $tokenBeforeName[0] === T_AS + || $tokenBeforeName[0] === T_FUNCTION + || $tokenBeforeName[0] === T_OBJECT_OPERATOR + || $tokenBeforeName[0] === T_NAMESPACE + || $tokenBeforeName[0] === (PHP_VERSION_ID > 80000 ? T_NULLSAFE_OBJECT_OPERATOR : -1) + || $tokenAfterName[0] === T_INSTEADOF + || $tokenAfterName[0] === T_AS + || $tokenAfterName === ':' + ) { + return false; + } + + return true; + } + + /** + * @return array{int, string}|string + */ + private function getTokenBefore(int $pointer) + { do { - $tokenBeforeName = $this->tokens[$pointerBeforeName]; + $token = $this->tokens[$pointer]; - if (!is_array($tokenBeforeName)) { + if (!is_array($token)) { break; } - if ($tokenBeforeName[0] === T_WHITESPACE || $tokenBeforeName[0] === T_COMMENT || $tokenBeforeName[0] === T_DOC_COMMENT) { - $pointerBeforeName--; + if ($token[0] === T_WHITESPACE || $token[0] === T_COMMENT || $token[0] === T_DOC_COMMENT) { + $pointer--; continue; } break; - } while ($pointerBeforeName >= 0); + } while ($pointer >= 0); + + return $token; + } + /** + * @return array{int, string}|string + */ + private function getTokenAfter(int $pointer) + { do { - $tokenAfterName = $this->tokens[$pointerAfterName]; + $token = $this->tokens[$pointer]; - if (!is_array($tokenAfterName)) { + if (!is_array($token)) { break; } - if ($tokenAfterName[0] === T_WHITESPACE || $tokenAfterName[0] === T_COMMENT || $tokenAfterName[0] === T_DOC_COMMENT) { - $pointerAfterName++; + if ($token[0] === T_WHITESPACE || $token[0] === T_COMMENT || $token[0] === T_DOC_COMMENT) { + $pointer++; continue; } break; - } while ($pointerAfterName < $this->numTokens); - - if ( - $tokenAfterName === '(' - && $tokenBeforeName[0] !== T_NEW // eliminate new \ClassName( - ) { - return SymbolKind::FUNCTION; - } + } while ($pointer < $this->numTokens); - return SymbolKind::CLASSLIKE; // constant may fall here, this is eliminated later + return $token; } } From 973d7c2f065779557f9e28e01a493f2732cdd51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Fri, 22 Nov 2024 22:46:25 +0100 Subject: [PATCH 2/7] As of PHP 7.2.0 ext-sodium is bundled with PHP --- app/composer.json | 1 - app/composer.lock | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/composer.json b/app/composer.json index a4f323e3a..14cd79823 100644 --- a/app/composer.json +++ b/app/composer.json @@ -16,7 +16,6 @@ "ext-pcntl": "*", "ext-pdo": "*", "ext-simplexml": "*", - "ext-sodium": "*", "composer/pcre": "^3.3.1", "contributte/translation": "^2.0", "latte/latte": "^3.0.3", diff --git a/app/composer.lock b/app/composer.lock index fc42924cc..ea5432cb0 100644 --- a/app/composer.lock +++ b/app/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ce19f674f584748cb60828e4e9b0f687", + "content-hash": "acd2d8cead8de73448f316f5f002fc08", "packages": [ { "name": "composer/pcre", @@ -4849,8 +4849,7 @@ "ext-openssl": "*", "ext-pcntl": "*", "ext-pdo": "*", - "ext-simplexml": "*", - "ext-sodium": "*" + "ext-simplexml": "*" }, "platform-dev": [], "plugin-api-version": "2.6.0" From 332ca112b6a4162d818e14aa8174c1d67d1e537d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Fri, 22 Nov 2024 23:52:02 +0100 Subject: [PATCH 3/7] Ignore errors because those extensions are used for something --- app/composer-dependency-analyser.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/composer-dependency-analyser.php b/app/composer-dependency-analyser.php index 817c82607..4ddb79aa7 100644 --- a/app/composer-dependency-analyser.php +++ b/app/composer-dependency-analyser.php @@ -15,6 +15,12 @@ // It's used, believe me ->ignoreErrorsOnPackage('latte/latte', [ErrorType::UNUSED_DEPENDENCY]) + ->ignoreErrorsOnExtensions([ + 'ext-gd', // Used by e.g. Nette\Http\FileUpload::toImage which is used by MichalSpacekCz\Media\VideoThumbnails::validateUpload() + 'ext-pcntl', // Used by latte/latte Latte\Tools\Linter and nette/tester's Tester\Runner\CliTester + 'ext-simplexml', // Used in MichalSpacekCz\Feed\ExportsTest + ], [ErrorType::UNUSED_DEPENDENCY]) + // TestCaseRunner is used only in tests ->ignoreErrorsOnPackageAndPath('nette/tester', __DIR__ . '/src/Test/TestCaseRunner.php', [ErrorType::DEV_DEPENDENCY_IN_PROD]) ; From 44903c81ae14e9496217e40070748188844981d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Fri, 22 Nov 2024 23:52:34 +0100 Subject: [PATCH 4/7] Ignore error caused by a bug --- app/composer-dependency-analyser.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/composer-dependency-analyser.php b/app/composer-dependency-analyser.php index 4ddb79aa7..41eb660b7 100644 --- a/app/composer-dependency-analyser.php +++ b/app/composer-dependency-analyser.php @@ -21,6 +21,9 @@ 'ext-simplexml', // Used in MichalSpacekCz\Feed\ExportsTest ], [ErrorType::UNUSED_DEPENDENCY]) + // shipmonk/composer-dependency-analyser#203 + ->ignoreErrorsOnExtensionAndPath('ext-session', 'src/EasterEgg/PhpInfoCookieSanitization.php', [ErrorType::SHADOW_DEPENDENCY]) + // TestCaseRunner is used only in tests ->ignoreErrorsOnPackageAndPath('nette/tester', __DIR__ . '/src/Test/TestCaseRunner.php', [ErrorType::DEV_DEPENDENCY_IN_PROD]) ; From 5e67c4c8b27e7b66a20cf2ef4c4f140a227de94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Sat, 23 Nov 2024 00:07:25 +0100 Subject: [PATCH 5/7] Dependency-check tests as well SimpleXML was used by ARES until #225, now only in tests, in MichalSpacekCz\Feed\ExportsTest --- app/composer-dependency-analyser.php | 4 +++- app/composer.json | 2 +- app/composer.lock | 7 ++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/composer-dependency-analyser.php b/app/composer-dependency-analyser.php index 41eb660b7..e4d584303 100644 --- a/app/composer-dependency-analyser.php +++ b/app/composer-dependency-analyser.php @@ -6,6 +6,9 @@ use ShipMonk\ComposerDependencyAnalyser\Config\ErrorType; return (new Configuration()) + ->setFileExtensions(['php', 'phpt']) + ->addPathToScan(__DIR__ . '/tests', true) + // Add classes from services.neon and extensions.neon ->addForceUsedSymbols(DiServices::getAllClasses()) @@ -18,7 +21,6 @@ ->ignoreErrorsOnExtensions([ 'ext-gd', // Used by e.g. Nette\Http\FileUpload::toImage which is used by MichalSpacekCz\Media\VideoThumbnails::validateUpload() 'ext-pcntl', // Used by latte/latte Latte\Tools\Linter and nette/tester's Tester\Runner\CliTester - 'ext-simplexml', // Used in MichalSpacekCz\Feed\ExportsTest ], [ErrorType::UNUSED_DEPENDENCY]) // shipmonk/composer-dependency-analyser#203 diff --git a/app/composer.json b/app/composer.json index 14cd79823..bd9c70f4b 100644 --- a/app/composer.json +++ b/app/composer.json @@ -15,7 +15,6 @@ "ext-openssl": "*", "ext-pcntl": "*", "ext-pdo": "*", - "ext-simplexml": "*", "composer/pcre": "^3.3.1", "contributte/translation": "^2.0", "latte/latte": "^3.0.3", @@ -55,6 +54,7 @@ "symfony/polyfill-mbstring": "*" }, "require-dev": { + "ext-simplexml": "*", "jetbrains/phpstorm-attributes": "^1.0", "nette/tester": "^2.4.3", "php-parallel-lint/php-console-highlighter": "^1.0", diff --git a/app/composer.lock b/app/composer.lock index ea5432cb0..7b73b6afa 100644 --- a/app/composer.lock +++ b/app/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "acd2d8cead8de73448f316f5f002fc08", + "content-hash": "12febb690a2d67b6820acf36b88b8415", "packages": [ { "name": "composer/pcre", @@ -4848,9 +4848,10 @@ "ext-mbstring": "*", "ext-openssl": "*", "ext-pcntl": "*", - "ext-pdo": "*", + "ext-pdo": "*" + }, + "platform-dev": { "ext-simplexml": "*" }, - "platform-dev": [], "plugin-api-version": "2.6.0" } From ace657b1883202990afedb316d0e72b3e4140c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Sat, 23 Nov 2024 00:32:47 +0100 Subject: [PATCH 6/7] Enable ext-simplexml for Psalm Psalm uses composer.json to enable extensions but doesn't use require-dev and ext-simplexml was used there recently. --- app/psalm.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/psalm.xml b/app/psalm.xml index 4dea9e9c8..10575a7eb 100644 --- a/app/psalm.xml +++ b/app/psalm.xml @@ -23,6 +23,9 @@ + + + From f89c2fc7866465ddf2943bf3fbb2846d718427e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Sat, 23 Nov 2024 00:25:22 +0100 Subject: [PATCH 7/7] libxml was used for libxml_disable_entity_loader() But the function is not required starting with PHP 8.0 and was removed from the codebase in 9af02f119887066a7f44ecedb28998b59c8062f7 --- app/composer.json | 1 - app/composer.lock | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/composer.json b/app/composer.json index bd9c70f4b..f2ece6a1f 100644 --- a/app/composer.json +++ b/app/composer.json @@ -10,7 +10,6 @@ "ext-fileinfo": "*", "ext-gd": "*", "ext-intl": "*", - "ext-libxml": "*", "ext-mbstring": "*", "ext-openssl": "*", "ext-pcntl": "*", diff --git a/app/composer.lock b/app/composer.lock index 7b73b6afa..3c220ef1e 100644 --- a/app/composer.lock +++ b/app/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "12febb690a2d67b6820acf36b88b8415", + "content-hash": "cd65d0895faaabd1296d4b6333ff4863", "packages": [ { "name": "composer/pcre", @@ -4844,7 +4844,6 @@ "ext-fileinfo": "*", "ext-gd": "*", "ext-intl": "*", - "ext-libxml": "*", "ext-mbstring": "*", "ext-openssl": "*", "ext-pcntl": "*",