diff --git a/.phive/phars.xml b/.phive/phars.xml index 24c7b5b..6a0059c 100644 --- a/.phive/phars.xml +++ b/.phive/phars.xml @@ -1,5 +1,5 @@ - + diff --git a/tools/.phpstan/composer.json b/tools/.phpstan/composer.json index 8e13d13..a79f73b 100644 --- a/tools/.phpstan/composer.json +++ b/tools/.phpstan/composer.json @@ -1,10 +1,10 @@ { "require-dev": { - "phpstan/phpstan": "^2.1.33", + "phpstan/phpstan": "^2.1.54", "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan-strict-rules": "^2.0.7", + "phpstan/phpstan-strict-rules": "^2.0.11", "tomasvotruba/type-coverage": "^2.1.0", - "ergebnis/phpstan-rules": "^2.12.0" + "ergebnis/phpstan-rules": "^2.13.1" }, "config": { "allow-plugins": { diff --git a/tools/.phpstan/composer.lock b/tools/.phpstan/composer.lock index 774d693..2a13142 100644 --- a/tools/.phpstan/composer.lock +++ b/tools/.phpstan/composer.lock @@ -4,40 +4,40 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4409cdc49212f7e878b14b7ae9285bb2", + "content-hash": "5352dc46c7b6a0ee40e2263c4eac895f", "packages": [], "packages-dev": [ { "name": "ergebnis/phpstan-rules", - "version": "2.12.0", + "version": "2.13.1", "source": { "type": "git", "url": "https://github.com/ergebnis/phpstan-rules.git", - "reference": "c4e0121a937b3b551f800a86e7d78794da2783ea" + "reference": "f69db86b98595c34fc1f61c89fe3b380141aa519" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/c4e0121a937b3b551f800a86e7d78794da2783ea", - "reference": "c4e0121a937b3b551f800a86e7d78794da2783ea", + "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/f69db86b98595c34fc1f61c89fe3b380141aa519", + "reference": "f69db86b98595c34fc1f61c89fe3b380141aa519", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "phpstan/phpstan": "^2.1.8" + "phpstan/phpstan": "^2.1.35" }, "require-dev": { "codeception/codeception": "^4.0.0 || ^5.0.0", "doctrine/orm": "^2.20.0 || ^3.3.0", - "ergebnis/composer-normalize": "^2.47.0", - "ergebnis/license": "^2.6.0", - "ergebnis/php-cs-fixer-config": "^6.54.0", + "ergebnis/composer-normalize": "^2.49.0", + "ergebnis/license": "^2.7.0", + "ergebnis/php-cs-fixer-config": "^6.59.0", "ergebnis/phpunit-slow-test-detector": "^2.20.0", "fakerphp/faker": "^1.24.1", "phpstan/extension-installer": "^1.4.3", "phpstan/phpstan-deprecation-rules": "^2.0.3", - "phpstan/phpstan-phpunit": "^2.0.7", - "phpstan/phpstan-strict-rules": "^2.0.6", + "phpstan/phpstan-phpunit": "^2.0.12", + "phpstan/phpstan-strict-rules": "^2.0.8", "phpunit/phpunit": "^9.6.21", "psr/container": "^2.0.2", "symfony/finder": "^5.4.45", @@ -78,20 +78,20 @@ "security": "https://github.com/ergebnis/phpstan-rules/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/phpstan-rules" }, - "time": "2025-09-07T13:31:33+00:00" + "time": "2026-01-27T17:13:06+00:00" }, { "name": "nette/utils", - "version": "v4.1.1", + "version": "v4.1.4", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72" + "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72", - "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72", + "url": "https://api.github.com/repos/nette/utils/zipball/7da6c396d7ebe142bc857c20479d5e70a5e1aac7", + "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7", "shasum": "" }, "require": { @@ -103,8 +103,10 @@ }, "require-dev": { "jetbrains/phpstorm-attributes": "^1.2", + "nette/phpstan-rules": "^1.0", "nette/tester": "^2.5", - "phpstan/phpstan-nette": "^2.0@stable", + "phpstan/extension-installer": "^1.4@stable", + "phpstan/phpstan": "^2.1@stable", "tracy/tracy": "^2.9" }, "suggest": { @@ -165,9 +167,9 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.1" + "source": "https://github.com/nette/utils/tree/v4.1.4" }, - "time": "2025-12-22T12:14:32+00:00" + "time": "2026-05-11T20:49:54+00:00" }, { "name": "phpstan/extension-installer", @@ -219,11 +221,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.33", + "version": "2.1.54", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f", - "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8be50c3992107dc837b17da4d140fbbdf9a5c5bd", + "reference": "8be50c3992107dc837b17da4d140fbbdf9a5c5bd", "shasum": "" }, "require": { @@ -268,25 +270,25 @@ "type": "github" } ], - "time": "2025-12-05T10:24:31+00:00" + "time": "2026-04-29T13:31:09+00:00" }, { "name": "phpstan/phpstan-strict-rules", - "version": "2.0.7", + "version": "2.0.11", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "d6211c46213d4181054b3d77b10a5c5cb0d59538" + "reference": "9b000a578b85b32945b358b172c7b20e91189024" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/d6211c46213d4181054b3d77b10a5c5cb0d59538", - "reference": "d6211c46213d4181054b3d77b10a5c5cb0d59538", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/9b000a578b85b32945b358b172c7b20e91189024", + "reference": "9b000a578b85b32945b358b172c7b20e91189024", "shasum": "" }, "require": { "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.29" + "phpstan/phpstan": "^2.1.39" }, "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.2", @@ -312,11 +314,14 @@ "MIT" ], "description": "Extra strict and opinionated rules for PHPStan", + "keywords": [ + "static analysis" + ], "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.7" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.11" }, - "time": "2025-09-26T11:19:08+00:00" + "time": "2026-05-02T06:54:10+00:00" }, { "name": "tomasvotruba/type-coverage", diff --git a/tools/.phpstan/vendor/composer/autoload_classmap.php b/tools/.phpstan/vendor/composer/autoload_classmap.php index c66a950..348b3ff 100644 --- a/tools/.phpstan/vendor/composer/autoload_classmap.php +++ b/tools/.phpstan/vendor/composer/autoload_classmap.php @@ -49,6 +49,9 @@ return array( 'Nette\\Utils\\JsonException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', 'Nette\\Utils\\ObjectHelpers' => $vendorDir . '/nette/utils/src/Utils/ObjectHelpers.php', 'Nette\\Utils\\Paginator' => $vendorDir . '/nette/utils/src/Utils/Paginator.php', + 'Nette\\Utils\\Process' => $vendorDir . '/nette/utils/src/Utils/Process.php', + 'Nette\\Utils\\ProcessFailedException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\ProcessTimeoutException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', 'Nette\\Utils\\Random' => $vendorDir . '/nette/utils/src/Utils/Random.php', 'Nette\\Utils\\Reflection' => $vendorDir . '/nette/utils/src/Utils/Reflection.php', 'Nette\\Utils\\ReflectionMethod' => $vendorDir . '/nette/utils/src/Utils/ReflectionMethod.php', diff --git a/tools/.phpstan/vendor/composer/autoload_static.php b/tools/.phpstan/vendor/composer/autoload_static.php index b66b499..1ad0d18 100644 --- a/tools/.phpstan/vendor/composer/autoload_static.php +++ b/tools/.phpstan/vendor/composer/autoload_static.php @@ -97,6 +97,9 @@ class ComposerStaticInitf9e7218f71d5874b5632927df4f72bd7 'Nette\\Utils\\JsonException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', 'Nette\\Utils\\ObjectHelpers' => __DIR__ . '/..' . '/nette/utils/src/Utils/ObjectHelpers.php', 'Nette\\Utils\\Paginator' => __DIR__ . '/..' . '/nette/utils/src/Utils/Paginator.php', + 'Nette\\Utils\\Process' => __DIR__ . '/..' . '/nette/utils/src/Utils/Process.php', + 'Nette\\Utils\\ProcessFailedException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', + 'Nette\\Utils\\ProcessTimeoutException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php', 'Nette\\Utils\\Random' => __DIR__ . '/..' . '/nette/utils/src/Utils/Random.php', 'Nette\\Utils\\Reflection' => __DIR__ . '/..' . '/nette/utils/src/Utils/Reflection.php', 'Nette\\Utils\\ReflectionMethod' => __DIR__ . '/..' . '/nette/utils/src/Utils/ReflectionMethod.php', diff --git a/tools/.phpstan/vendor/composer/installed.json b/tools/.phpstan/vendor/composer/installed.json index 5d61f48..1bac664 100644 --- a/tools/.phpstan/vendor/composer/installed.json +++ b/tools/.phpstan/vendor/composer/installed.json @@ -2,42 +2,42 @@ "packages": [ { "name": "ergebnis/phpstan-rules", - "version": "2.12.0", - "version_normalized": "2.12.0.0", + "version": "2.13.1", + "version_normalized": "2.13.1.0", "source": { "type": "git", "url": "https://github.com/ergebnis/phpstan-rules.git", - "reference": "c4e0121a937b3b551f800a86e7d78794da2783ea" + "reference": "f69db86b98595c34fc1f61c89fe3b380141aa519" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/c4e0121a937b3b551f800a86e7d78794da2783ea", - "reference": "c4e0121a937b3b551f800a86e7d78794da2783ea", + "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/f69db86b98595c34fc1f61c89fe3b380141aa519", + "reference": "f69db86b98595c34fc1f61c89fe3b380141aa519", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "phpstan/phpstan": "^2.1.8" + "phpstan/phpstan": "^2.1.35" }, "require-dev": { "codeception/codeception": "^4.0.0 || ^5.0.0", "doctrine/orm": "^2.20.0 || ^3.3.0", - "ergebnis/composer-normalize": "^2.47.0", - "ergebnis/license": "^2.6.0", - "ergebnis/php-cs-fixer-config": "^6.54.0", + "ergebnis/composer-normalize": "^2.49.0", + "ergebnis/license": "^2.7.0", + "ergebnis/php-cs-fixer-config": "^6.59.0", "ergebnis/phpunit-slow-test-detector": "^2.20.0", "fakerphp/faker": "^1.24.1", "phpstan/extension-installer": "^1.4.3", "phpstan/phpstan-deprecation-rules": "^2.0.3", - "phpstan/phpstan-phpunit": "^2.0.7", - "phpstan/phpstan-strict-rules": "^2.0.6", + "phpstan/phpstan-phpunit": "^2.0.12", + "phpstan/phpstan-strict-rules": "^2.0.8", "phpunit/phpunit": "^9.6.21", "psr/container": "^2.0.2", "symfony/finder": "^5.4.45", "symfony/process": "^5.4.47" }, - "time": "2025-09-07T13:31:33+00:00", + "time": "2026-01-27T17:13:06+00:00", "type": "phpstan-extension", "extra": { "phpstan": { @@ -78,17 +78,17 @@ }, { "name": "nette/utils", - "version": "v4.1.1", - "version_normalized": "4.1.1.0", + "version": "v4.1.4", + "version_normalized": "4.1.4.0", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72" + "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72", - "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72", + "url": "https://api.github.com/repos/nette/utils/zipball/7da6c396d7ebe142bc857c20479d5e70a5e1aac7", + "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7", "shasum": "" }, "require": { @@ -100,8 +100,10 @@ }, "require-dev": { "jetbrains/phpstorm-attributes": "^1.2", + "nette/phpstan-rules": "^1.0", "nette/tester": "^2.5", - "phpstan/phpstan-nette": "^2.0@stable", + "phpstan/extension-installer": "^1.4@stable", + "phpstan/phpstan": "^2.1@stable", "tracy/tracy": "^2.9" }, "suggest": { @@ -112,7 +114,7 @@ "ext-mbstring": "to use Strings::lower() etc...", "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" }, - "time": "2025-12-22T12:14:32+00:00", + "time": "2026-05-11T20:49:54+00:00", "type": "library", "extra": { "branch-alias": { @@ -164,7 +166,7 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.1" + "source": "https://github.com/nette/utils/tree/v4.1.4" }, "install-path": "../nette/utils" }, @@ -221,12 +223,12 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.33", - "version_normalized": "2.1.33.0", + "version": "2.1.54", + "version_normalized": "2.1.54.0", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f", - "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8be50c3992107dc837b17da4d140fbbdf9a5c5bd", + "reference": "8be50c3992107dc837b17da4d140fbbdf9a5c5bd", "shasum": "" }, "require": { @@ -235,7 +237,7 @@ "conflict": { "phpstan/phpstan-shim": "*" }, - "time": "2025-12-05T10:24:31+00:00", + "time": "2026-04-29T13:31:09+00:00", "bin": [ "phpstan", "phpstan.phar" @@ -277,22 +279,22 @@ }, { "name": "phpstan/phpstan-strict-rules", - "version": "2.0.7", - "version_normalized": "2.0.7.0", + "version": "2.0.11", + "version_normalized": "2.0.11.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "d6211c46213d4181054b3d77b10a5c5cb0d59538" + "reference": "9b000a578b85b32945b358b172c7b20e91189024" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/d6211c46213d4181054b3d77b10a5c5cb0d59538", - "reference": "d6211c46213d4181054b3d77b10a5c5cb0d59538", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/9b000a578b85b32945b358b172c7b20e91189024", + "reference": "9b000a578b85b32945b358b172c7b20e91189024", "shasum": "" }, "require": { "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.29" + "phpstan/phpstan": "^2.1.39" }, "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.2", @@ -300,7 +302,7 @@ "phpstan/phpstan-phpunit": "^2.0", "phpunit/phpunit": "^9.6" }, - "time": "2025-09-26T11:19:08+00:00", + "time": "2026-05-02T06:54:10+00:00", "type": "phpstan-extension", "extra": { "phpstan": { @@ -320,9 +322,12 @@ "MIT" ], "description": "Extra strict and opinionated rules for PHPStan", + "keywords": [ + "static analysis" + ], "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.7" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.11" }, "install-path": "../phpstan/phpstan-strict-rules" }, diff --git a/tools/.phpstan/vendor/composer/installed.php b/tools/.phpstan/vendor/composer/installed.php index eea1cec..cd5022c 100644 --- a/tools/.phpstan/vendor/composer/installed.php +++ b/tools/.phpstan/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => '__root__', - 'pretty_version' => 'dev-main', - 'version' => 'dev-main', - 'reference' => 'd4d9bba3c5904cdebea5c9bebab27d8abd6c1af1', + 'pretty_version' => '7.0.x-dev', + 'version' => '7.0.9999999.9999999-dev', + 'reference' => '150ed9dd5535041d546fe5416a20dd4be31f6c36', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -11,27 +11,27 @@ ), 'versions' => array( '__root__' => array( - 'pretty_version' => 'dev-main', - 'version' => 'dev-main', - 'reference' => 'd4d9bba3c5904cdebea5c9bebab27d8abd6c1af1', + 'pretty_version' => '7.0.x-dev', + 'version' => '7.0.9999999.9999999-dev', + 'reference' => '150ed9dd5535041d546fe5416a20dd4be31f6c36', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false, ), 'ergebnis/phpstan-rules' => array( - 'pretty_version' => '2.12.0', - 'version' => '2.12.0.0', - 'reference' => 'c4e0121a937b3b551f800a86e7d78794da2783ea', + 'pretty_version' => '2.13.1', + 'version' => '2.13.1.0', + 'reference' => 'f69db86b98595c34fc1f61c89fe3b380141aa519', 'type' => 'phpstan-extension', 'install_path' => __DIR__ . '/../ergebnis/phpstan-rules', 'aliases' => array(), 'dev_requirement' => true, ), 'nette/utils' => array( - 'pretty_version' => 'v4.1.1', - 'version' => '4.1.1.0', - 'reference' => 'c99059c0315591f1a0db7ad6002000288ab8dc72', + 'pretty_version' => 'v4.1.4', + 'version' => '4.1.4.0', + 'reference' => '7da6c396d7ebe142bc857c20479d5e70a5e1aac7', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/utils', 'aliases' => array(), @@ -47,18 +47,18 @@ 'dev_requirement' => true, ), 'phpstan/phpstan' => array( - 'pretty_version' => '2.1.33', - 'version' => '2.1.33.0', - 'reference' => '9e800e6bee7d5bd02784d4c6069b48032d16224f', + 'pretty_version' => '2.1.54', + 'version' => '2.1.54.0', + 'reference' => '8be50c3992107dc837b17da4d140fbbdf9a5c5bd', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpstan', 'aliases' => array(), 'dev_requirement' => true, ), 'phpstan/phpstan-strict-rules' => array( - 'pretty_version' => '2.0.7', - 'version' => '2.0.7.0', - 'reference' => 'd6211c46213d4181054b3d77b10a5c5cb0d59538', + 'pretty_version' => '2.0.11', + 'version' => '2.0.11.0', + 'reference' => '9b000a578b85b32945b358b172c7b20e91189024', 'type' => 'phpstan-extension', 'install_path' => __DIR__ . '/../phpstan/phpstan-strict-rules', 'aliases' => array(), diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/CHANGELOG.md b/tools/.phpstan/vendor/ergebnis/phpstan-rules/CHANGELOG.md index 7729147..6e0d020 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/CHANGELOG.md +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/CHANGELOG.md @@ -6,7 +6,27 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## Unreleased -For a full diff see [`2.12.0...main`][2.12.0...main]. +For a full diff see [`2.13.1...main`][2.13.1...main]. + +## [`2.13.1`][2.13.1] + +For a full diff see [`2.13.0...2.13.1`][2.13.0...2.13.1]. + +### Fixed + +- Adjusted `Files\NoPhpstanIgnoreRule` to traverse into all nodes ([#1011]), by [@localheinz] + +## [`2.13.0`][2.13.0] + +For a full diff see [`2.12.0...2.13.0`][2.12.0...2.13.0]. + +### Added + +- Added `Files\NoPhpstanIgnoreRule`, which reports an error when a `@phpstan-ignore`, `@phpstan-ignore-line`, or `@phpstan-ignore-next-line` tag is used to suppress an error ([#1009]), by [@localheinz] + +### Changed + +- Required `phpstan/phpstan:^2.1.35` ([#1010]), by [@localheinz] ## [`2.12.0`][2.12.0] @@ -588,6 +608,8 @@ For a full diff see [`362c7ea...0.1.0`][362c7ea...0.1.0]. [2.10.5]: https://github.com/ergebnis/phpstan-rules/releases/tag/2.10.5 [2.11.0]: https://github.com/ergebnis/phpstan-rules/releases/tag/2.11.0 [2.12.0]: https://github.com/ergebnis/phpstan-rules/releases/tag/2.12.0 +[2.13.0]: https://github.com/ergebnis/phpstan-rules/releases/tag/2.13.0 +[2.13.1]: https://github.com/ergebnis/phpstan-rules/releases/tag/2.13.1 [362c7ea...0.1.0]: https://github.com/ergebnis/phpstan-rules/compare/362c7ea...0.1.0 [0.1.0...0.2.0]: https://github.com/ergebnis/phpstan-rules/compare/0.1.0...0.2.0 @@ -638,7 +660,9 @@ For a full diff see [`362c7ea...0.1.0`][362c7ea...0.1.0]. [2.10.4...2.10.5]: https://github.com/ergebnis/phpstan-rules/compare/2.10.4...2.10.5 [2.10.5...2.11.0]: https://github.com/ergebnis/phpstan-rules/compare/2.10.5...2.11.0 [2.11.0...2.12.0]: https://github.com/ergebnis/phpstan-rules/compare/2.11.0...2.12.0 -[2.12.0...main]: https://github.com/ergebnis/phpstan-rules/compare/2.12.0...main +[2.12.0...2.13.0]: https://github.com/ergebnis/phpstan-rules/compare/2.12.0...2.13.0 +[2.13.0...2.13.1]: https://github.com/ergebnis/phpstan-rules/compare/2.13.0...2.13.1 +[2.13.1...main]: https://github.com/ergebnis/phpstan-rules/compare/2.13.1...main [#1]: https://github.com/ergebnis/phpstan-rules/pull/1 [#4]: https://github.com/ergebnis/phpstan-rules/pull/4 @@ -736,6 +760,9 @@ For a full diff see [`362c7ea...0.1.0`][362c7ea...0.1.0]. [#958]: https://github.com/ergebnis/phpstan-rules/pull/958 [#972]: https://github.com/ergebnis/phpstan-rules/pull/972 [#977]: https://github.com/ergebnis/phpstan-rules/pull/977 +[#1009]: https://github.com/ergebnis/phpstan-rules/pull/1009 +[#1010]: https://github.com/ergebnis/phpstan-rules/pull/1010 +[#1011]: https://github.com/ergebnis/phpstan-rules/pull/1011 [@cosmastech]: https://github.com/cosmastech [@enumag]: https://github.com/enumag diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/LICENSE.md b/tools/.phpstan/vendor/ergebnis/phpstan-rules/LICENSE.md index 130e719..987526c 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/LICENSE.md +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/LICENSE.md @@ -1,6 +1,6 @@ # The MIT License (MIT) -Copyright (c) 2018-2025 Andreas Möller +Copyright (c) 2018-2026 Andreas Möller Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the _Software_), to deal in the Software without restriction, including without limitation the diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/README.md b/tools/.phpstan/vendor/ergebnis/phpstan-rules/README.md index 690d4ad..afe6464 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/README.md +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/README.md @@ -58,6 +58,7 @@ This package provides the following rules for use with [`phpstan/phpstan`](https - [`Ergebnis\PHPStan\Rules\Expressions\NoEvalRule`](https://github.com/ergebnis/phpstan-rules#expressionsnoevalrule) - [`Ergebnis\PHPStan\Rules\Expressions\NoIssetRule`](https://github.com/ergebnis/phpstan-rules#expressionsnoissetrule) - [`Ergebnis\PHPStan\Rules\Files\DeclareStrictTypesRule`](https://github.com/ergebnis/phpstan-rules#filesdeclarestricttypesrule) +- [`Ergebnis\PHPStan\Rules\Files\NoPhpstanIgnoreRule`](https://github.com/ergebnis/phpstan-rules#filesnophpstanignorerule) - [`Ergebnis\PHPStan\Rules\Functions\NoNullableReturnTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#functionsnonullablereturntypedeclarationrule) - [`Ergebnis\PHPStan\Rules\Functions\NoParameterPassedByReferenceRule`](https://github.com/ergebnis/phpstan-rules#functionsnoparameterpassedbyreferencerule) - [`Ergebnis\PHPStan\Rules\Functions\NoParameterWithNullableTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#functionsnoparameterwithnullabletypedeclarationrule) @@ -348,6 +349,21 @@ parameters: enabled: false ``` +#### `Files\NoPhpstanIgnoreRule` + +This rule reports an error when a `@phpstan-ignore`, `@phpstan-ignore-line`, or `@phpstan-ignore-next-line` tag is used to [ignore errors reported by `phpstan/phpstan`](https://phpstan.org/user-guide/ignoring-errors#ignoring-in-code-using-phpdocs). + +##### Disabling the rule + +You can set the `enabled` parameter to `false` to disable this rule. + +```neon +parameters: + ergebnis: + noPhpstanIgnore: + enabled: false +``` + ### Functions #### `Functions\NoNullableReturnTypeDeclarationRule` diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/composer.json b/tools/.phpstan/vendor/ergebnis/phpstan-rules/composer.json index 5060dde..7235712 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/composer.json +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/composer.json @@ -23,20 +23,20 @@ "require": { "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", "ext-mbstring": "*", - "phpstan/phpstan": "^2.1.8" + "phpstan/phpstan": "^2.1.35" }, "require-dev": { "codeception/codeception": "^4.0.0 || ^5.0.0", "doctrine/orm": "^2.20.0 || ^3.3.0", - "ergebnis/composer-normalize": "^2.47.0", - "ergebnis/license": "^2.6.0", - "ergebnis/php-cs-fixer-config": "^6.54.0", + "ergebnis/composer-normalize": "^2.49.0", + "ergebnis/license": "^2.7.0", + "ergebnis/php-cs-fixer-config": "^6.59.0", "ergebnis/phpunit-slow-test-detector": "^2.20.0", "fakerphp/faker": "^1.24.1", "phpstan/extension-installer": "^1.4.3", "phpstan/phpstan-deprecation-rules": "^2.0.3", - "phpstan/phpstan-phpunit": "^2.0.7", - "phpstan/phpstan-strict-rules": "^2.0.6", + "phpstan/phpstan-phpunit": "^2.0.12", + "phpstan/phpstan-strict-rules": "^2.0.8", "phpunit/phpunit": "^9.6.21", "psr/container": "^2.0.2", "symfony/finder": "^5.4.45", diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/rules.neon b/tools/.phpstan/vendor/ergebnis/phpstan-rules/rules.neon index 0458e5a..e1287c5 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/rules.neon +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/rules.neon @@ -25,6 +25,8 @@ conditionalTags: phpstan.rules.rule: %ergebnis.noIsset.enabled% Ergebnis\PHPStan\Rules\Files\DeclareStrictTypesRule: phpstan.rules.rule: %ergebnis.declareStrictTypes.enabled% + Ergebnis\PHPStan\Rules\Files\NoPhpstanIgnoreRule: + phpstan.rules.rule: %ergebnis.noPhpstanIgnore.enabled% Ergebnis\PHPStan\Rules\Functions\NoNullableReturnTypeDeclarationRule: phpstan.rules.rule: %ergebnis.noNullableReturnTypeDeclaration.enabled% Ergebnis\PHPStan\Rules\Functions\NoParameterPassedByReferenceRule: @@ -102,6 +104,8 @@ parameters: enabled: %ergebnis.allRules% noParameterWithNullDefaultValue: enabled: %ergebnis.allRules% + noPhpstanIgnore: + enabled: %ergebnis.allRules% noReturnByReference: enabled: %ergebnis.allRules% noSwitch: @@ -176,6 +180,9 @@ parametersSchema: noParameterWithNullDefaultValue: structure([ enabled: bool(), ]) + noPhpstanIgnore: structure([ + enabled: bool(), + ]) noReturnByReference: structure([ enabled: bool(), ]) @@ -238,6 +245,9 @@ services: - class: Ergebnis\PHPStan\Rules\Files\DeclareStrictTypesRule + - + class: Ergebnis\PHPStan\Rules\Files\NoPhpstanIgnoreRule + - class: Ergebnis\PHPStan\Rules\Functions\NoNullableReturnTypeDeclarationRule diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Analyzer.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Analyzer.php index 938cab7..996aea2 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Analyzer.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Analyzer.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/CallLikes/NoNamedArgumentRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/CallLikes/NoNamedArgumentRule.php index a87bbaf..d76397e 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/CallLikes/NoNamedArgumentRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/CallLikes/NoNamedArgumentRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/ClassName.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/ClassName.php index e62b908..1aa116f 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/ClassName.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/ClassName.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/FinalRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/FinalRule.php index 05a9f3c..7deed48 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/FinalRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/FinalRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/NoExtendsRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/NoExtendsRule.php index 4d4864e..7674298 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/NoExtendsRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/NoExtendsRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php index 4b6d479..7c1ee57 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoNullableReturnTypeDeclarationRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoNullableReturnTypeDeclarationRule.php index 6435157..cca6f29 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoNullableReturnTypeDeclarationRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoNullableReturnTypeDeclarationRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterPassedByReferenceRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterPassedByReferenceRule.php index 2c47cb7..7a5027e 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterPassedByReferenceRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterPassedByReferenceRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterWithNullDefaultValueRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterWithNullDefaultValueRule.php index 94bd146..0982f9e 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterWithNullDefaultValueRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterWithNullDefaultValueRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterWithNullableTypeDeclarationRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterWithNullableTypeDeclarationRule.php index 3cff6ee..b314519 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterWithNullableTypeDeclarationRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Closures/NoParameterWithNullableTypeDeclarationRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/ErrorIdentifier.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/ErrorIdentifier.php index 3435c19..8f9d6f6 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/ErrorIdentifier.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/ErrorIdentifier.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. @@ -110,6 +110,11 @@ final class ErrorIdentifier return new self('noNullableReturnTypeDeclaration'); } + public static function noPhpstanIgnore(): self + { + return new self('noPhpstanIgnore'); + } + public static function noReturnByReference(): self { return new self('noReturnByReference'); diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoAssignByReferenceRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoAssignByReferenceRule.php index ad8cc1e..9f1f09c 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoAssignByReferenceRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoAssignByReferenceRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoCompactRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoCompactRule.php index cd12ffe..0374f3a 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoCompactRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoCompactRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoErrorSuppressionRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoErrorSuppressionRule.php index 49c0939..3640166 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoErrorSuppressionRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoErrorSuppressionRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoEvalRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoEvalRule.php index b542057..3cc858a 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoEvalRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoEvalRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoIssetRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoIssetRule.php index f1443d6..3b78517 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoIssetRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Expressions/NoIssetRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Files/DeclareStrictTypesRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Files/DeclareStrictTypesRule.php index 5f9ec11..e62a854 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Files/DeclareStrictTypesRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Files/DeclareStrictTypesRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Files/NoPhpstanIgnoreRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Files/NoPhpstanIgnoreRule.php new file mode 100644 index 0000000..28ba7e7 --- /dev/null +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Files/NoPhpstanIgnoreRule.php @@ -0,0 +1,70 @@ + + */ +final class NoPhpstanIgnoreRule implements Rules\Rule +{ + public function getNodeType(): string + { + return FileNode::class; + } + + public function processNode( + Node $node, + Analyser\Scope $scope + ): array { + $nodeFinder = new NodeFinder(); + + $foundNodes = $nodeFinder->find($node->getNodes(), static function (Node $node): bool { + return true; + }); + + $errors = []; + + foreach ($foundNodes as $foundNode) { + foreach ($foundNode->getComments() as $comment) { + foreach (\explode("\n", $comment->getText()) as $index => $line) { + if (0 === \preg_match('/@phpstan-ignore(-line|-next-line)?(?=\s|$|,)/', $line, $matches)) { + continue; + } + + $tag = $matches[0]; + + $message = \sprintf( + 'Errors reported by phpstan/phpstan should not be ignored via "%s", fix the error or use the baseline instead.', + $tag, + ); + + $errors[] = Rules\RuleErrorBuilder::message($message) + ->identifier(ErrorIdentifier::noPhpstanIgnore()->toString()) + ->line($comment->getStartLine() + $index) + ->nonIgnorable() + ->build(); + } + } + } + + return $errors; + } +} diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoNullableReturnTypeDeclarationRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoNullableReturnTypeDeclarationRule.php index 06da4f7..32c4f2e 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoNullableReturnTypeDeclarationRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoNullableReturnTypeDeclarationRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterPassedByReferenceRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterPassedByReferenceRule.php index e461aa1..e36f07f 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterPassedByReferenceRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterPassedByReferenceRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterWithNullDefaultValueRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterWithNullDefaultValueRule.php index fe82a4e..f22c006 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterWithNullDefaultValueRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterWithNullDefaultValueRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterWithNullableTypeDeclarationRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterWithNullableTypeDeclarationRule.php index 9027553..92a8ae5 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterWithNullableTypeDeclarationRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoParameterWithNullableTypeDeclarationRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoReturnByReferenceRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoReturnByReferenceRule.php index 0efb700..2c621e0 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoReturnByReferenceRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Functions/NoReturnByReferenceRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/HasContent.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/HasContent.php index ced8177..c37afe8 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/HasContent.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/HasContent.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/HookMethod.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/HookMethod.php index 2d14cad..b944e5e 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/HookMethod.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/HookMethod.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Invocation.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Invocation.php index 722ff5f..3afcc9f 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Invocation.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Invocation.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/MethodName.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/MethodName.php index 47116ce..597a586 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/MethodName.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/MethodName.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/FinalInAbstractClassRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/FinalInAbstractClassRule.php index 271870a..9c9e6fa 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/FinalInAbstractClassRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/FinalInAbstractClassRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/InvokeParentHookMethodRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/InvokeParentHookMethodRule.php index 888aa92..041858d 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/InvokeParentHookMethodRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/InvokeParentHookMethodRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoConstructorParameterWithDefaultValueRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoConstructorParameterWithDefaultValueRule.php index e8b7e34..9315474 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoConstructorParameterWithDefaultValueRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoConstructorParameterWithDefaultValueRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoNullableReturnTypeDeclarationRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoNullableReturnTypeDeclarationRule.php index e0e84c9..facc9fc 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoNullableReturnTypeDeclarationRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoNullableReturnTypeDeclarationRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterPassedByReferenceRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterPassedByReferenceRule.php index 4c90f69..e50a0ef 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterPassedByReferenceRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterPassedByReferenceRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithContainerTypeDeclarationRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithContainerTypeDeclarationRule.php index f64a831..cfd88cf 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithContainerTypeDeclarationRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithContainerTypeDeclarationRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithNullDefaultValueRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithNullDefaultValueRule.php index 9888974..5a100a1 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithNullDefaultValueRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithNullDefaultValueRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithNullableTypeDeclarationRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithNullableTypeDeclarationRule.php index 632cd7b..73d714d 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithNullableTypeDeclarationRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoParameterWithNullableTypeDeclarationRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoReturnByReferenceRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoReturnByReferenceRule.php index a1bf87f..11ecbcd 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoReturnByReferenceRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/NoReturnByReferenceRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/PrivateInFinalClassRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/PrivateInFinalClassRule.php index 9aa2c3c..91fa562 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/PrivateInFinalClassRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Methods/PrivateInFinalClassRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Statements/NoSwitchRule.php b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Statements/NoSwitchRule.php index 127e5ee..38461f5 100644 --- a/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Statements/NoSwitchRule.php +++ b/tools/.phpstan/vendor/ergebnis/phpstan-rules/src/Statements/NoSwitchRule.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * Copyright (c) 2018-2025 Andreas Möller + * Copyright (c) 2018-2026 Andreas Möller * * For the full copyright and license information, please view * the LICENSE.md file that was distributed with this source code. diff --git a/tools/.phpstan/vendor/nette/utils/.phpstorm.meta.php b/tools/.phpstan/vendor/nette/utils/.phpstorm.meta.php index 25851af..64dc487 100644 --- a/tools/.phpstan/vendor/nette/utils/.phpstorm.meta.php +++ b/tools/.phpstan/vendor/nette/utils/.phpstorm.meta.php @@ -1,6 +1,4 @@ -> * @property-read bool $first * @property-read bool $last * @property-read bool $empty * @property-read bool $odd * @property-read bool $even * @property-read int $counter - * @property-read mixed $nextKey - * @property-read mixed $nextValue + * @property-read TKey $nextKey + * @property-read TValue $nextValue */ class CachingIterator extends \CachingIterator implements \Countable { @@ -31,6 +32,7 @@ class CachingIterator extends \CachingIterator implements \Countable private int $counter = 0; + /** @param iterable|\stdClass $iterable */ public function __construct(iterable|\stdClass $iterable) { $iterable = $iterable instanceof \stdClass @@ -58,45 +60,30 @@ class CachingIterator extends \CachingIterator implements \Countable } - /** - * Is the iterator empty? - */ public function isEmpty(): bool { return $this->counter === 0; } - /** - * Is the counter odd? - */ public function isOdd(): bool { return $this->counter % 2 === 1; } - /** - * Is the counter even? - */ public function isEven(): bool { return $this->counter % 2 === 0; } - /** - * Returns the counter. - */ public function getCounter(): int { return $this->counter; } - /** - * Returns the count of elements. - */ public function count(): int { $inner = $this->getInnerIterator(); @@ -131,18 +118,14 @@ class CachingIterator extends \CachingIterator implements \Countable } - /** - * Returns the next key. - */ + /** @return TKey */ public function getNextKey(): mixed { return $this->getInnerIterator()->key(); } - /** - * Returns the next element. - */ + /** @return TValue */ public function getNextValue(): mixed { return $this->getInnerIterator()->current(); diff --git a/tools/.phpstan/vendor/nette/utils/src/Iterators/Mapper.php b/tools/.phpstan/vendor/nette/utils/src/Iterators/Mapper.php index 284da29..a9cfba0 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Iterators/Mapper.php +++ b/tools/.phpstan/vendor/nette/utils/src/Iterators/Mapper.php @@ -1,12 +1,10 @@ -callback = $callback; + $this->callback = $callback(...); } diff --git a/tools/.phpstan/vendor/nette/utils/src/SmartObject.php b/tools/.phpstan/vendor/nette/utils/src/SmartObject.php index 3b2203f..d9742c8 100644 --- a/tools/.phpstan/vendor/nette/utils/src/SmartObject.php +++ b/tools/.phpstan/vendor/nette/utils/src/SmartObject.php @@ -1,12 +1,10 @@ - * @implements \ArrayAccess @@ -39,7 +37,6 @@ class ArrayHash extends \stdClass implements \ArrayAccess, \Countable, \Iterator /** - * Returns an iterator over all items. * @return \Iterator */ public function &getIterator(): \Iterator @@ -50,9 +47,6 @@ class ArrayHash extends \stdClass implements \ArrayAccess, \Countable, \Iterator } - /** - * Returns items count. - */ public function count(): int { return count((array) $this); diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/ArrayList.php b/tools/.phpstan/vendor/nette/utils/src/Utils/ArrayList.php index 98a5082..628cc45 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/ArrayList.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/ArrayList.php @@ -1,12 +1,10 @@ - * @implements \ArrayAccess */ class ArrayList implements \ArrayAccess, \Countable, \IteratorAggregate { + /** @var list */ private array $list = []; @@ -41,7 +40,6 @@ class ArrayList implements \ArrayAccess, \Countable, \IteratorAggregate /** - * Returns an iterator over all items. * @return \Iterator */ public function &getIterator(): \Iterator @@ -52,9 +50,6 @@ class ArrayList implements \ArrayAccess, \Countable, \IteratorAggregate } - /** - * Returns items count. - */ public function count(): int { return count($this->list); @@ -63,7 +58,7 @@ class ArrayList implements \ArrayAccess, \Countable, \IteratorAggregate /** * Replaces or appends an item. - * @param int|null $index + * @param ?int $index * @param T $value * @throws Nette\OutOfRangeException */ diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Arrays.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Arrays.php index 986118c..3769433 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Arrays.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Arrays.php @@ -1,12 +1,10 @@ - $array1 * @param array $array2 - * @return array + * @return array> */ public static function mergeTree(array $array1, array $array2): array { @@ -96,6 +94,7 @@ class Arrays /** * Returns zero-indexed position of given array key. Returns null if key is not found. + * @param array $array */ public static function getKeyOffset(array $array, string|int $key): ?int { @@ -104,9 +103,10 @@ class Arrays /** + * @param array $array * @deprecated use getKeyOffset() */ - public static function searchKey(array $array, $key): ?int + public static function searchKey(array $array, string|int $key): ?int { return self::getKeyOffset($array, $key); } @@ -114,10 +114,11 @@ class Arrays /** * Tests an array for the presence of value. + * @param array $array */ public static function contains(array $array, mixed $value): bool { - return in_array($value, $array, true); + return in_array($value, $array, strict: true); } @@ -125,9 +126,11 @@ class Arrays * Returns the first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null. * @template K of int|string * @template V + * @template E * @param array $array * @param ?callable(V, K, array): bool $predicate - * @return ?V + * @param ?callable(): E $else + * @return ($else is null ? ?V : V|E) */ public static function first(array $array, ?callable $predicate = null, ?callable $else = null): mixed { @@ -142,9 +145,11 @@ class Arrays * Returns the last item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null. * @template K of int|string * @template V + * @template E * @param array $array * @param ?callable(V, K, array): bool $predicate - * @return ?V + * @param ?callable(): E $else + * @return ($else is null ? ?V : V|E) */ public static function last(array $array, ?callable $predicate = null, ?callable $else = null): mixed { @@ -194,8 +199,10 @@ class Arrays /** - * Inserts the contents of the $inserted array into the $array immediately after the $key. + * Inserts the contents of the $inserted array into the $array immediately before the $key. * If $key is null (or does not exist), it is inserted at the beginning. + * @param array $array + * @param array $inserted */ public static function insertBefore(array &$array, string|int|null $key, array $inserted): void { @@ -207,8 +214,10 @@ class Arrays /** - * Inserts the contents of the $inserted array into the $array before the $key. + * Inserts the contents of the $inserted array into the $array immediately after the $key. * If $key is null (or does not exist), it is inserted at the end. + * @param array $array + * @param array $inserted */ public static function insertAfter(array &$array, string|int|null $key, array $inserted): void { @@ -224,6 +233,7 @@ class Arrays /** * Renames key in array. + * @param array $array */ public static function renameKey(array &$array, string|int $oldKey, string|int $newKey): bool { @@ -260,6 +270,8 @@ class Arrays /** * Transforms multidimensional array to flat array. + * @param array $array + * @return array */ public static function flatten(array $array, bool $preserveKeys = false): array { @@ -283,17 +295,19 @@ class Arrays /** - * Reformats table to associative tree. Path looks like 'field|field[]field->field=field'. - * @param string|string[] $path + * Transforms a flat array of rows into an associative tree using a path expression like 'field|field[]field->field=field'. + * @param array $array + * @param string|list $path + * @return array|\stdClass */ - public static function associate(array $array, $path): array|\stdClass + public static function associate(array $array, string|array $path): array|\stdClass { $parts = is_array($path) ? $path : preg_split('#(\[\]|->|=|\|)#', $path, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); if (!$parts || $parts === ['->'] || $parts[0] === '=' || $parts[0] === '|') { - throw new Nette\InvalidArgumentException("Invalid path '$path'."); + throw new Nette\InvalidArgumentException("Invalid path '" . (is_array($path) ? implode('', $path) : $path) . "'."); } $res = $parts[0] === '->' ? new \stdClass : []; @@ -312,6 +326,8 @@ class Arrays $x = $row[$parts[$i]]; $row = null; } + break; // '=' is always the final operation + } elseif ($part === '->') { if (isset($parts[++$i])) { if ($x === null) { @@ -337,7 +353,9 @@ class Arrays /** - * Normalizes array to associative array. Replace numeric keys with their values, the new value will be $filling. + * Converts array to associative: items with numeric keys are converted to keys, with $filling as their value. + * @param array $array + * @return array */ public static function normalize(array $array, mixed $filling = null): array { @@ -480,9 +498,10 @@ class Arrays /** * Invokes all callbacks and returns array of results. - * @param callable[] $callbacks + * @param iterable $callbacks + * @return array */ - public static function invoke(iterable $callbacks, ...$args): array + public static function invoke(iterable $callbacks, mixed ...$args): array { $res = []; foreach ($callbacks as $k => $cb) { @@ -495,9 +514,10 @@ class Arrays /** * Invokes method on every object in an array and returns array of results. - * @param object[] $objects + * @param iterable $objects + * @return array */ - public static function invokeMethod(iterable $objects, string $method, ...$args): array + public static function invokeMethod(iterable $objects, string $method, mixed ...$args): array { $res = []; foreach ($objects as $k => $obj) { @@ -511,6 +531,7 @@ class Arrays /** * Copies the elements of the $array array to the $object object and then returns it. * @template T of object + * @param iterable $array * @param T $object * @return T */ @@ -534,8 +555,7 @@ class Arrays /** - * Returns copy of the $array where every item is converted to string - * and prefixed by $prefix and suffixed by $suffix. + * Returns a copy of $array where every item is cast to string and wrapped with $prefix and $suffix. * @param string[] $array * @return string[] */ diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Callback.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Callback.php index 7d384f2..1c34ac9 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Callback.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Callback.php @@ -1,12 +1,10 @@ - $args + * @param callable(string, int): (bool|void|null) $onError */ public static function invokeSafe(string $function, array $args, callable $onError): mixed { - $prev = set_error_handler(function ($severity, $message, $file) use ($onError, &$prev, $function): ?bool { + $prev = set_error_handler(function (int $severity, string $message, string $file, int $line) use ($onError, &$prev, $function): bool { if ($file === __FILE__) { $msg = ini_get('html_errors') ? Html::htmlToText($message) : $message; - $msg = preg_replace("#^$function\\(.*?\\): #", '', $msg); + $msg = (string) preg_replace("#^$function\\(.*?\\): #", '', $msg); if ($onError($msg, $severity) !== false) { - return null; + return true; } } - return $prev ? $prev(...func_get_args()) : false; + return $prev ? $prev(...func_get_args()) !== false : false; }); try { @@ -48,12 +49,12 @@ final class Callback /** - * Checks that $callable is valid PHP callback. Otherwise throws exception. If the $syntax is set to true, only verifies - * that $callable has a valid structure to be used as a callback, but does not verify if the class or method actually exists. + * Checks that $callable is a valid PHP callback and returns it. With $syntax set to true, only verifies + * the structural validity without checking whether the class or method actually exists. * @return callable * @throws Nette\InvalidArgumentException */ - public static function check(mixed $callable, bool $syntax = false) + public static function check(mixed $callable, bool $syntax = false): mixed { if (!is_callable($callable, $syntax)) { throw new Nette\InvalidArgumentException( @@ -87,7 +88,7 @@ final class Callback * @param callable $callable type check is escalated to ReflectionException * @throws \ReflectionException if callback is not valid */ - public static function toReflection($callable): \ReflectionMethod|\ReflectionFunction + public static function toReflection(mixed $callable): \ReflectionMethod|\ReflectionFunction { if ($callable instanceof \Closure) { $callable = self::unwrap($callable); @@ -100,6 +101,7 @@ final class Callback } elseif (is_object($callable) && !$callable instanceof \Closure) { return new ReflectionMethod($callable, '__invoke'); } else { + assert($callable instanceof \Closure || is_string($callable)); return new \ReflectionFunction($callable); } } @@ -116,8 +118,9 @@ final class Callback /** * Unwraps closure created by Closure::fromCallable(). + * @return callable|array{object|class-string, string}|string */ - public static function unwrap(\Closure $closure): callable|array + public static function unwrap(\Closure $closure): callable|array|string { $r = new \ReflectionFunction($closure); $class = $r->getClosureScopeClass()?->name; diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/DateTime.php b/tools/.phpstan/vendor/nette/utils/src/Utils/DateTime.php index 6191223..af4e94d 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/DateTime.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/DateTime.php @@ -1,19 +1,17 @@ -modify(...) + * Returns a modified copy of the object. Use (clone $dt)->modify(...) for better type safety. */ public function modifyClone(string $modify = ''): static { diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/FileInfo.php b/tools/.phpstan/vendor/nette/utils/src/Utils/FileInfo.php index 59dd722..64eeb74 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/FileInfo.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/FileInfo.php @@ -1,12 +1,10 @@ -setInfoClass(static::class); - $this->relativePath = $relativePath; + $this->setInfoClass(self::class); } diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/FileSystem.php b/tools/.phpstan/vendor/nette/utils/src/Utils/FileSystem.php index 8adb21e..e55b996 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/FileSystem.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/FileSystem.php @@ -1,12 +1,10 @@ -getPathname()); } foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($origin, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) { if ($item->isDir()) { - static::createDir($target . '/' . $iterator->getSubPathName()); + static::createDir($target . '/' . $iterator->getSubPathname()); } else { - static::copy($item->getPathname(), $target . '/' . $iterator->getSubPathName()); + static::copy($item->getPathname(), $target . '/' . $iterator->getSubPathname()); } } } else { @@ -112,6 +111,7 @@ final class FileSystem } } elseif (is_dir($path)) { foreach (new \FilesystemIterator($path) as $item) { + \assert($item instanceof \SplFileInfo); static::delete($item->getPathname()); } @@ -208,7 +208,7 @@ final class FileSystem /** - * Writes the string to a file. + * Writes the string to a file. Creates the parent directory if it does not exist. Pass null as $mode to skip chmod. * @throws Nette\IOException on error occurred */ public static function write(string $file, string $content, ?int $mode = 0o666): void @@ -251,6 +251,7 @@ final class FileSystem } } elseif (is_dir($path)) { foreach (new \FilesystemIterator($path) as $item) { + \assert($item instanceof \SplFileInfo); static::makeWritable($item->getPathname(), $dirMode, $fileMode); } @@ -277,6 +278,19 @@ final class FileSystem } + /** + * Determines whether the string is a valid cross-platform filename without any path information. + */ + public static function isValidFilename(string $name): bool + { + [$stem] = explode('.', $name, 2); + return $name !== '' && $name !== '.' && $name !== '..' + && !preg_match('#[\x00-\x1F<>:"|?*\\\/]#', $name) // control and reserved characters + && !str_ends_with($name, '.') && !str_ends_with($name, ' ') // trailing dots/spaces + && !preg_match('#^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$#i', $stem); // Windows reserved device names + } + + /** * Normalizes `..` and `.` and directory separators in path. */ diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Finder.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Finder.php index 2f5f7d1..10a8474 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Finder.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Finder.php @@ -1,12 +1,10 @@ -size('> 10kB') @@ -32,24 +30,25 @@ class Finder implements \IteratorAggregate /** @var string[] */ private array $in = []; - /** @var \Closure[] */ + /** @var array<\Closure(FileInfo): bool> */ private array $filters = []; - /** @var \Closure[] */ + /** @var array<\Closure(FileInfo): bool> */ private array $descentFilters = []; /** @var array */ private array $appends = []; private bool $childFirst = false; - /** @var ?callable */ - private $sort; + /** @var ?(\Closure(FileInfo, FileInfo): int) */ + private ?\Closure $sort = null; private int $maxDepth = -1; private bool $ignoreUnreadableDirs = true; /** * Begins search for files and directories matching mask. + * @param string|list $masks */ public static function find(string|array $masks = ['*']): static { @@ -60,6 +59,7 @@ class Finder implements \IteratorAggregate /** * Begins search for files matching mask. + * @param string|list $masks */ public static function findFiles(string|array $masks = ['*']): static { @@ -70,6 +70,7 @@ class Finder implements \IteratorAggregate /** * Begins search for directories matching mask. + * @param string|list $masks */ public static function findDirectories(string|array $masks = ['*']): static { @@ -80,6 +81,7 @@ class Finder implements \IteratorAggregate /** * Finds files matching the specified masks. + * @param string|list $masks */ public function files(string|array $masks = ['*']): static { @@ -89,6 +91,7 @@ class Finder implements \IteratorAggregate /** * Finds directories matching the specified masks. + * @param string|list $masks */ public function directories(string|array $masks = ['*']): static { @@ -96,6 +99,7 @@ class Finder implements \IteratorAggregate } + /** @param list $masks */ private function addMask(array $masks, string $mode): static { foreach ($masks as $mask) { @@ -117,6 +121,7 @@ class Finder implements \IteratorAggregate /** * Searches in the given directories. Wildcards are allowed. + * @param string|list $paths */ public function in(string|array $paths): static { @@ -128,6 +133,7 @@ class Finder implements \IteratorAggregate /** * Searches recursively from the given directories. Wildcards are allowed. + * @param string|list $paths */ public function from(string|array $paths): static { @@ -137,6 +143,7 @@ class Finder implements \IteratorAggregate } + /** @param list $paths */ private function addLocation(array $paths, string $ext): void { foreach ($paths as $path) { @@ -170,12 +177,12 @@ class Finder implements \IteratorAggregate /** - * Set a compare function for sorting directory entries. The function will be called to sort entries from the same directory. + * Sets a comparison function for sorting entries within each directory. * @param callable(FileInfo, FileInfo): int $callback */ public function sortBy(callable $callback): static { - $this->sort = $callback; + $this->sort = $callback(...); return $this; } @@ -191,7 +198,8 @@ class Finder implements \IteratorAggregate /** - * Adds the specified paths or appends a new finder that returns. + * Appends the specified file paths to results. Passing null creates and returns a new sub-finder whose results are appended. + * @param string|list|null $paths */ public function append(string|array|null $paths = null): static { @@ -209,6 +217,7 @@ class Finder implements \IteratorAggregate /** * Skips entries that matches the given masks relative to the ones defined with the in() or from() methods. + * @param string|list $masks */ public function exclude(string|array $masks): static { @@ -239,7 +248,7 @@ class Finder implements \IteratorAggregate */ public function filter(callable $callback): static { - $this->filters[] = \Closure::fromCallable($callback); + $this->filters[] = $callback(...); return $this; } @@ -250,7 +259,7 @@ class Finder implements \IteratorAggregate */ public function descentFilter(callable $callback): static { - $this->descentFilters[] = \Closure::fromCallable($callback); + $this->descentFilters[] = $callback(...); return $this; } @@ -267,6 +276,7 @@ class Finder implements \IteratorAggregate /** * Restricts the search by size. $operator accepts "[operator] [size] [unit]" example: >=10kB + * @param '>'|'>='|'<'|'<='|'='|'=='|'==='|'!='|'!=='|'<>' $operator or predicate string */ public function size(string $operator, ?int $size = null): static { @@ -277,7 +287,7 @@ class Finder implements \IteratorAggregate [, $operator, $size, $unit] = $matches; $units = ['' => 1, 'k' => 1e3, 'm' => 1e6, 'g' => 1e9]; - $size *= $units[strtolower($unit)]; + $size = (float) $size * $units[strtolower($unit)]; $operator = $operator ?: '='; } @@ -287,6 +297,7 @@ class Finder implements \IteratorAggregate /** * Restricts the search by modified time. $operator accepts "[operator] [date]" example: >1978-01-23 + * @param '>'|'>='|'<'|'<='|'='|'=='|'==='|'!='|'!=='|'<>' $operator or predicate string */ public function date(string $operator, string|int|\DateTimeInterface|null $date = null): static { @@ -401,6 +412,7 @@ class Finder implements \IteratorAggregate } + /** @param iterable $pathNames */ private function convertToFiles(iterable $pathNames, string $relativePath, bool $absolute): \Generator { foreach ($pathNames as $pathName) { @@ -413,6 +425,10 @@ class Finder implements \IteratorAggregate } + /** + * @param (\Closure(FileInfo): bool)[] $filters + * @param array $cache + */ private function proveFilters(array $filters, FileInfo $file, array &$cache): bool { foreach ($filters as $filter) { @@ -468,6 +484,7 @@ class Finder implements \IteratorAggregate /** * Since glob() does not know ** wildcard, we divide the path into a part for glob and a part for manual traversal. + * @return array{string, string, bool} */ private static function splitRecursivePart(string $path): array { diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Floats.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Floats.php index ed78a55..02cebeb 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Floats.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Floats.php @@ -1,12 +1,10 @@ -, >=, <, <=, =, ==, ===, !=, !==, <> + * @param '>'|'>='|'<'|'<='|'='|'=='|'==='|'!='|'!=='|'<>' $operator */ public static function compare(mixed $left, string $operator, mixed $right): bool { diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Html.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Html.php index de24a96..8ee2f7e 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Html.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Html.php @@ -1,12 +1,10 @@ - + * @implements \ArrayAccess */ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringable { /** @var array element's attributes */ public array $attrs = []; - /** void elements */ + /** @var array void elements */ public static array $emptyElements = [ 'img' => 1, 'hr' => 1, 'br' => 1, 'input' => 1, 'meta' => 1, 'area' => 1, 'embed' => 1, 'keygen' => 1, 'source' => 1, 'base' => 1, 'col' => 1, 'link' => 1, 'param' => 1, 'basefont' => 1, 'frame' => 1, 'isindex' => 1, 'wbr' => 1, 'command' => 1, 'track' => 1, ]; - /** @var array nodes */ + /** @var array nodes */ protected array $children = []; /** element's name */ @@ -254,7 +255,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** * Constructs new HTML element. - * @param array|string $attrs element's attributes or plain text content + * @param array|string|null $attrs element's attributes or plain text content */ public static function el(?string $name = null, array|string|null $attrs = null): static { @@ -345,7 +346,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** - * Is element empty? + * Checks whether the element is a void (self-closing) element. */ final public function isEmpty(): bool { @@ -355,6 +356,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** * Sets multiple attributes. + * @param array $attrs */ public function addAttributes(array $attrs): static { @@ -417,6 +419,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** * Unsets element's attributes. + * @param list $attributes */ public function removeAttributes(array $attributes): static { @@ -429,7 +432,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** - * Overloaded setter for element's attribute. + * Sets element's attribute via property assignment. */ final public function __set(string $name, mixed $value): void { @@ -438,7 +441,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** - * Overloaded getter for element's attribute. + * Returns element's attribute via property access. */ final public function &__get(string $name): mixed { @@ -447,7 +450,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** - * Overloaded tester for element's attribute. + * Checks if element's attribute is set. */ final public function __isset(string $name): bool { @@ -456,7 +459,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** - * Overloaded unsetter for element's attribute. + * Unsets element's attribute via property unset. */ final public function __unset(string $name): void { @@ -465,7 +468,8 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** - * Overloaded setter for element's attribute. + * Sets or returns element's attribute via method call. + * @param mixed[] $args */ final public function __call(string $m, array $args): mixed { @@ -496,6 +500,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** * Special setter for element's attribute. + * @param array $query */ final public function href(string $path, array $query = []): static { @@ -594,6 +599,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** * Creates and adds a new Html child. + * @param array|string|null $attrs */ final public function create(string $name, array|string|null $attrs = null): static { @@ -621,7 +627,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** * Inserts (replaces) child node (\ArrayAccess implementation). - * @param int|null $index position or null for appending + * @param ?int $index position or null for appending * @param Html|string $child Html node or raw HTML string */ final public function offsetSet($index, $child): void @@ -634,7 +640,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab * Returns child node (\ArrayAccess implementation). * @param int $index */ - final public function offsetGet($index): HtmlStringable|string + final public function offsetGet($index): self|string { return $this->children[$index]; } @@ -682,7 +688,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** * Iterates over elements. - * @return \ArrayIterator + * @return \ArrayIterator */ final public function getIterator(): \ArrayIterator { @@ -692,6 +698,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** * Returns all children. + * @return array */ final public function getChildren(): array { @@ -700,7 +707,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab /** - * Renders element's start tag, content and end tag. + * Renders element's start tag, content and end tag. Pass indent level to enable pretty-printing. */ final public function render(?int $indent = null): string { @@ -764,10 +771,6 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab */ final public function attributes(): string { - if (!is_array($this->attrs)) { - return ''; - } - $s = ''; $attrs = $this->attrs; foreach ($attrs as $key => $value) { @@ -780,7 +783,7 @@ class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringab continue; } elseif (is_array($value)) { - if (strncmp($key, 'data-', 5) === 0) { + if (str_starts_with($key, 'data-')) { $value = Json::encode($value); } else { diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Image.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Image.php index a6bb478..3fdc3e4 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Image.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Image.php @@ -1,12 +1,10 @@ -send(); * * - * @method Image affine(array $affine, ?array $clip = null) + * @method Image affine(array $affine, ?array{x: int, y: int, width: int, height: int} $clip = null) * @method void alphaBlending(bool $enable) * @method void antialias(bool $enable) * @method void arc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color) @@ -41,51 +39,51 @@ use const IMG_BMP, IMG_FLIP_BOTH, IMG_FLIP_HORIZONTAL, IMG_FLIP_VERTICAL, IMG_GI * @method int colorResolve(int $red, int $green, int $blue) * @method int colorResolveAlpha(int $red, int $green, int $blue, int $alpha) * @method void colorSet(int $index, int $red, int $green, int $blue, int $alpha = 0) - * @method array colorsForIndex(int $color) + * @method array{red: int, green: int, blue: int, alpha: int} colorsForIndex(int $color) * @method int colorsTotal() * @method int colorTransparent(?int $color = null) - * @method void convolution(array $matrix, float $div, float $offset) + * @method void convolution(array> $matrix, float $div, float $offset) * @method void copy(Image $src, int $dstX, int $dstY, int $srcX, int $srcY, int $srcW, int $srcH) * @method void copyMerge(Image $src, int $dstX, int $dstY, int $srcX, int $srcY, int $srcW, int $srcH, int $pct) * @method void copyMergeGray(Image $src, int $dstX, int $dstY, int $srcX, int $srcY, int $srcW, int $srcH, int $pct) * @method void copyResampled(Image $src, int $dstX, int $dstY, int $srcX, int $srcY, int $dstW, int $dstH, int $srcW, int $srcH) * @method void copyResized(Image $src, int $dstX, int $dstY, int $srcX, int $srcY, int $dstW, int $dstH, int $srcW, int $srcH) - * @method Image cropAuto(int $mode = IMG_CROP_DEFAULT, float $threshold = .5, ?ImageColor $color = null) + * @method Image cropAuto(int $mode = 0, float $threshold = .5, ?ImageColor $color = null) * @method void ellipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color) * @method void fill(int $x, int $y, ImageColor $color) * @method void filledArc(int $centerX, int $centerY, int $width, int $height, int $startAngle, int $endAngle, ImageColor $color, int $style) * @method void filledEllipse(int $centerX, int $centerY, int $width, int $height, ImageColor $color) - * @method void filledPolygon(array $points, ImageColor $color) + * @method void filledPolygon(array $points, ImageColor $color) * @method void filledRectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color) * @method void fillToBorder(int $x, int $y, ImageColor $borderColor, ImageColor $color) * @method void filter(int $filter, ...$args) * @method void flip(int $mode) - * @method array ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options = []) + * @method array ftText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontFile, string $text, array $options = []) * @method void gammaCorrect(float $inputgamma, float $outputgamma) - * @method array getClip() + * @method array{int, int, int, int} getClip() * @method int getInterpolation() * @method int interlace(?bool $enable = null) * @method bool isTrueColor() * @method void layerEffect(int $effect) * @method void line(int $x1, int $y1, int $x2, int $y2, ImageColor $color) - * @method void openPolygon(array $points, ImageColor $color) + * @method void openPolygon(array $points, ImageColor $color) * @method void paletteCopy(Image $source) * @method void paletteToTrueColor() - * @method void polygon(array $points, ImageColor $color) + * @method void polygon(array $points, ImageColor $color) * @method void rectangle(int $x1, int $y1, int $x2, int $y2, ImageColor $color) * @method mixed resolution(?int $resolutionX = null, ?int $resolutionY = null) * @method Image rotate(float $angle, ImageColor $backgroundColor) * @method void saveAlpha(bool $enable) - * @method Image scale(int $newWidth, int $newHeight = -1, int $mode = IMG_BILINEAR_FIXED) + * @method Image scale(int $newWidth, int $newHeight = -1, int $mode = 3) * @method void setBrush(Image $brush) * @method void setClip(int $x1, int $y1, int $x2, int $y2) - * @method void setInterpolation(int $method = IMG_BILINEAR_FIXED) + * @method void setInterpolation(int $method = 3) * @method void setPixel(int $x, int $y, ImageColor $color) - * @method void setStyle(array $style) + * @method void setStyle(array $style) * @method void setThickness(int $thickness) * @method void setTile(Image $tile) * @method void trueColorToPalette(bool $dither, int $ncolors) - * @method array ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontfile, string $text, array $options = []) + * @method array ttfText(float $size, float $angle, int $x, int $y, ImageColor $color, string $fontfile, string $text, array $options = []) * @property-read positive-int $width * @property-read positive-int $height * @property-read \GdImage $imageResource @@ -139,6 +137,7 @@ class Image public const EmptyGIF = "GIF89a\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;"; private const Formats = [ImageType::JPEG => 'jpeg', ImageType::PNG => 'png', ImageType::GIF => 'gif', ImageType::WEBP => 'webp', ImageType::AVIF => 'avif', ImageType::BMP => 'bmp']; + private const Sentinel = "\0"; private \GdImage $image; @@ -146,6 +145,7 @@ class Image /** * Returns RGB color (0..255) and transparency (0..127). * @deprecated use ImageColor::rgb() + * @return array{red: int, green: int, blue: int, alpha: int} */ public static function rgb(int $red, int $green, int $blue, int $transparency = 0): array { @@ -159,11 +159,13 @@ class Image /** - * Reads an image from a file and returns its type in $type. + * Reads an image from a file and returns its type in $type. If $warnings is passed, recoverable decoder + * warnings are returned in it instead of being raised as a PHP warning. + * @param-out ?string $warnings * @throws Nette\NotSupportedException if gd extension is not loaded * @throws UnknownImageFileException if file not found or file type is not known */ - public static function fromFile(string $file, ?int &$type = null): static + public static function fromFile(string $file, ?int &$type = null, ?string &$warnings = self::Sentinel): static { self::ensureExtension(); $type = self::detectTypeFromFile($file); @@ -171,16 +173,18 @@ class Image throw new UnknownImageFileException(is_file($file) ? "Unknown type of file '$file'." : "File '$file' not found."); } - return self::invokeSafe('imagecreatefrom' . self::Formats[$type], $file, "Unable to open file '$file'.", __METHOD__); + return self::invokeSafe('imagecreatefrom' . self::Formats[$type], $file, "Unable to open file '$file'.", __METHOD__, $warnings); } /** - * Reads an image from a string and returns its type in $type. + * Reads an image from a string and returns its type in $type. If $warnings is passed, recoverable decoder + * warnings are returned in it instead of being raised as a PHP warning. + * @param-out ?string $warnings * @throws Nette\NotSupportedException if gd extension is not loaded * @throws ImageException */ - public static function fromString(string $s, ?int &$type = null): static + public static function fromString(string $s, ?int &$type = null, ?string &$warnings = self::Sentinel): static { self::ensureExtension(); $type = self::detectTypeFromString($s); @@ -188,21 +192,31 @@ class Image throw new UnknownImageFileException('Unknown type of image.'); } - return self::invokeSafe('imagecreatefromstring', $s, 'Unable to open image from string.', __METHOD__); + return self::invokeSafe('imagecreatefromstring', $s, 'Unable to open image from string.', __METHOD__, $warnings); } - private static function invokeSafe(string $func, string $arg, string $message, string $callee): static + /** @param callable-string $func */ + private static function invokeSafe( + string $func, + string $arg, + string $message, + string $callee, + ?string &$warnings = self::Sentinel, + ): static { $errors = []; $res = Callback::invokeSafe($func, [$arg], function (string $message) use (&$errors): void { $errors[] = $message; }); + $raiseWarning = $warnings === self::Sentinel; + $warnings = $errors ? implode(', ', $errors) : null; + if (!$res) { - throw new ImageException($message . ' Errors: ' . implode(', ', $errors)); - } elseif ($errors) { - trigger_error($callee . '(): ' . implode(', ', $errors), E_USER_WARNING); + throw new ImageException($message . ' Errors: ' . $warnings); + } elseif ($errors && $raiseWarning) { + trigger_error($callee . '(): ' . $warnings, E_USER_WARNING); } return new static($res); @@ -213,6 +227,7 @@ class Image * Creates a new true color image of the given dimensions. The default color is black. * @param positive-int $width * @param positive-int $height + * @param ImageColor|array{red: int, green: int, blue: int, alpha?: int}|null $color * @throws Nette\NotSupportedException if gd extension is not loaded */ public static function fromBlank(int $width, int $height, ImageColor|array|null $color = null): static @@ -224,9 +239,9 @@ class Image $image = new static(imagecreatetruecolor($width, $height)); if ($color) { - $image->alphablending(false); - $image->filledrectangle(0, 0, $width - 1, $height - 1, $color); - $image->alphablending(true); + $image->alphaBlending(false); + $image->filledRectangle(0, 0, $width - 1, $height - 1, self::normalizeColor($color)); + $image->alphaBlending(true); } return $image; @@ -235,9 +250,11 @@ class Image /** * Returns the type of image from file. - * @return ImageType::*|null + * @param-out ?int $width + * @param-out ?int $height + * @return ?ImageType::* */ - public static function detectTypeFromFile(string $file, &$width = null, &$height = null): ?int + public static function detectTypeFromFile(string $file, mixed &$width = null, mixed &$height = null): ?int { [$width, $height, $type] = Helpers::falseToNull(@getimagesize($file)); // @ - files smaller than 12 bytes causes read error return $type && isset(self::Formats[$type]) ? $type : null; @@ -246,9 +263,11 @@ class Image /** * Returns the type of image from string. - * @return ImageType::*|null + * @param-out ?int $width + * @param-out ?int $height + * @return ?ImageType::* */ - public static function detectTypeFromString(string $s, &$width = null, &$height = null): ?int + public static function detectTypeFromString(string $s, mixed &$width = null, mixed &$height = null): ?int { [$width, $height, $type] = Helpers::falseToNull(@getimagesizefromstring($s)); // @ - strings smaller than 12 bytes causes read error return $type && isset(self::Formats[$type]) ? $type : null; @@ -297,6 +316,7 @@ class Image /** + * Checks whether the given image type is supported by the GD extension. * @param ImageType::* $type */ public static function isTypeSupported(int $type): bool @@ -314,7 +334,10 @@ class Image } - /** @return ImageType[] */ + /** + * Returns list of image types supported by the GD extension. + * @return ImageType::*[] + */ public static function getSupportedTypes(): array { self::ensureExtension(); @@ -386,6 +409,10 @@ class Image public function resize(int|string|null $width, int|string|null $height, int $mode = self::OrSmaller): static { if ($mode & self::Cover) { + if ($width === null || $height === null) { + throw new Nette\InvalidArgumentException('Both width and height must be set for Cover mode.'); + } + return $this->resize($width, $height, self::OrBigger)->crop('50%', '50%', $width, $height); } @@ -419,12 +446,13 @@ class Image /** * Calculates dimensions of resized image. Width and height accept pixels or percent. * @param int-mask-of $mode + * @return array{int<1, max>, int<1, max>} */ public static function calculateSize( int $srcWidth, int $srcHeight, - $newWidth, - $newHeight, + int|string|null $newWidth, + int|string|null $newHeight, int $mode = self::OrSmaller, ): array { @@ -468,19 +496,19 @@ class Image } if ($mode & self::OrBigger) { - $scale = [max($scale)]; + $scale = [max($scale ?: [1])]; } if ($mode & self::ShrinkOnly) { $scale[] = 1; } - $scale = min($scale); + $scale = min($scale ?: [1]); $newWidth = (int) round($srcWidth * $scale); $newHeight = (int) round($srcHeight * $scale); } - return [max($newWidth, 1), max($newHeight, 1)]; + return [max((int) $newWidth, 1), max((int) $newHeight, 1)]; } @@ -495,7 +523,7 @@ class Image $this->image = imagecrop($this->image, $r); imagesavealpha($this->image, true); } else { - $newImage = static::fromBlank($r['width'], $r['height'], ImageColor::rgb(0, 0, 0, 0))->getImageResource(); + $newImage = static::fromBlank(max(1, $r['width']), max(1, $r['height']), ImageColor::rgb(0, 0, 0, 0))->getImageResource(); imagecopy($newImage, $this->image, 0, 0, $r['x'], $r['y'], $r['width'], $r['height']); $this->image = $newImage; } @@ -506,6 +534,7 @@ class Image /** * Calculates dimensions of cutout in image. Arguments accepts pixels or percent. + * @return array{int, int, int, int} */ public static function calculateCutout( int $srcWidth, @@ -516,21 +545,10 @@ class Image int|string $newHeight, ): array { - if (self::isPercent($newWidth)) { - $newWidth = (int) round($srcWidth / 100 * $newWidth); - } - - if (self::isPercent($newHeight)) { - $newHeight = (int) round($srcHeight / 100 * $newHeight); - } - - if (self::isPercent($left)) { - $left = (int) round(($srcWidth - $newWidth) / 100 * $left); - } - - if (self::isPercent($top)) { - $top = (int) round(($srcHeight - $newHeight) / 100 * $top); - } + $newWidth = (int) (self::isPercent($newWidth) ? round($srcWidth / 100 * $newWidth) : $newWidth); + $newHeight = (int) (self::isPercent($newHeight) ? round($srcHeight / 100 * $newHeight) : $newHeight); + $left = (int) (self::isPercent($left) ? round(($srcWidth - $newWidth) / 100 * $left) : $left); + $top = (int) (self::isPercent($top) ? round(($srcHeight - $newHeight) / 100 * $top) : $top); if ($left < 0) { $newWidth += $left; @@ -575,14 +593,8 @@ class Image $width = $image->getWidth(); $height = $image->getHeight(); - - if (self::isPercent($left)) { - $left = (int) round(($this->getWidth() - $width) / 100 * $left); - } - - if (self::isPercent($top)) { - $top = (int) round(($this->getHeight() - $height) / 100 * $top); - } + $left = (int) (self::isPercent($left) ? round(($this->getWidth() - $width) / 100 * $left) : $left); + $top = (int) (self::isPercent($top) ? round(($this->getHeight() - $height) / 100 * $top) : $top); $output = $input = $image->image; if ($opacity < 100) { @@ -595,7 +607,7 @@ class Image imagealphablending($output, false); if (!$image->isTrueColor()) { $input = $output; - imagefilledrectangle($output, 0, 0, $width, $height, imagecolorallocatealpha($output, 0, 0, 0, 127)); + imagefilledrectangle($output, 0, 0, $width, $height, (int) imagecolorallocatealpha($output, 0, 0, 0, 127)); imagecopy($output, $image->image, 0, 0, 0, 0, $width, $height); } @@ -626,6 +638,8 @@ class Image /** * Calculates the bounding box for a TrueType text. Returns keys left, top, width and height. + * @param array $options + * @return array{left: int, top: int, width: int, height: int} */ public static function calculateTextBox( string $text, @@ -647,7 +661,7 @@ class Image /** - * Draw a rectangle. + * Draws a rectangle using top-left coordinates and dimensions instead of two corner coordinates. */ public function rectangleWH(int $x, int $y, int $width, int $height, ImageColor $color): void { @@ -658,7 +672,7 @@ class Image /** - * Draw a filled rectangle. + * Draws a filled rectangle using top-left coordinates and dimensions instead of two corner coordinates. */ public function filledRectangleWH(int $x, int $y, int $width, int $height, ImageColor $color): void { @@ -670,7 +684,7 @@ class Image /** * Saves image to the file. Quality is in the range 0..100 for JPEG (default 85), WEBP (default 80) and AVIF (default 30) and 0..9 for PNG (default 9). - * @param ImageType::*|null $type + * @param ?ImageType::* $type * @throws ImageException */ public function save(string $file, ?int $quality = null, ?int $type = null): void @@ -746,6 +760,7 @@ class Image /** * Call to undefined method. + * @param mixed[] $args * @throws Nette\MemberAccessException */ public function __call(string $name, array $args): mixed @@ -760,6 +775,7 @@ class Image $args[$key] = $value->getImageResource(); } elseif ($value instanceof ImageColor || (is_array($value) && isset($value['red']))) { + /** @var ImageColor|array{red: int, green: int, blue: int, alpha?: int} $value */ $args[$key] = $this->resolveColor($value); } } @@ -775,10 +791,11 @@ class Image { ob_start(fn() => ''); imagepng($this->image, null, 0); - $this->setImageResource(imagecreatefromstring(ob_get_clean())); + $this->setImageResource(imagecreatefromstring(ob_get_clean()) ?: throw new Nette\ShouldNotHappenException); } + /** @param-out int|float $num */ private static function isPercent(int|string &$num): bool { if (is_string($num) && str_ends_with($num, '%')) { @@ -802,13 +819,31 @@ class Image } + /** + * Resolves a color to a GD color index for the current image. + * @param ImageColor|array{red: int, green: int, blue: int, alpha?: int} $color + */ public function resolveColor(ImageColor|array $color): int { - $color = $color instanceof ImageColor ? $color->toRGBA() : array_values($color); + $color = self::normalizeColor($color)->toRGBA(); return imagecolorallocatealpha($this->image, ...$color) ?: imagecolorresolvealpha($this->image, ...$color); } + /** @param ImageColor|array{red: int, green: int, blue: int, alpha?: int} $color */ + private static function normalizeColor(ImageColor|array $color): ImageColor + { + return $color instanceof ImageColor + ? $color + : ImageColor::rgb( + $color['red'], + $color['green'], + $color['blue'], + (127 - ($color['alpha'] ?? 0)) / 127, + ); + } + + private static function ensureExtension(): void { if (!extension_loaded('gd')) { diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/ImageColor.php b/tools/.phpstan/vendor/nette/utils/src/Utils/ImageColor.php index 6696662..31cf542 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/ImageColor.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/ImageColor.php @@ -1,12 +1,10 @@ -, int<0, 255>, int<0, 255>, int<0, 127>} + */ public function toRGBA(): array { return [ diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/ImageType.php b/tools/.phpstan/vendor/nette/utils/src/Utils/ImageType.php index 080ca8a..793f73a 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/ImageType.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/ImageType.php @@ -1,12 +1,10 @@ - $iterable */ public static function contains(iterable $iterable, mixed $value): bool { @@ -36,6 +35,7 @@ final class Iterables /** * Tests for the presence of key. + * @param iterable $iterable */ public static function containsKey(iterable $iterable, mixed $key): bool { @@ -52,9 +52,11 @@ final class Iterables * Returns the first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null. * @template K * @template V + * @template E * @param iterable $iterable * @param ?callable(V, K, iterable): bool $predicate - * @return ?V + * @param ?callable(): E $else + * @return ($else is null ? ?V : V|E) */ public static function first(iterable $iterable, ?callable $predicate = null, ?callable $else = null): mixed { @@ -71,9 +73,11 @@ final class Iterables * Returns the key of first item (matching the specified predicate if given). If there is no such item, it returns result of invoking $else or null. * @template K * @template V + * @template E * @param iterable $iterable * @param ?callable(V, K, iterable): bool $predicate - * @return ?K + * @param ?callable(): E $else + * @return ($else is null ? ?K : K|E) */ public static function firstKey(iterable $iterable, ?callable $predicate = null, ?callable $else = null): mixed { @@ -87,7 +91,7 @@ final class Iterables /** - * Tests whether at least one element in the iterator passes the test implemented by the provided function. + * Tests whether at least one element in the iterable passes the test implemented by the provided function. * @template K * @template V * @param iterable $iterable @@ -105,7 +109,7 @@ final class Iterables /** - * Tests whether all elements in the iterator pass the test implemented by the provided function. + * Tests whether all elements in the iterable pass the test implemented by the provided function. * @template K * @template V * @param iterable $iterable @@ -123,7 +127,7 @@ final class Iterables /** - * Iterator that filters elements according to a given $predicate. Maintains original keys. + * Returns a generator that yields only elements matching the given $predicate. Maintains original keys. * @template K * @template V * @param iterable $iterable @@ -141,7 +145,7 @@ final class Iterables /** - * Iterator that transforms values by calling $transformer. Maintains original keys. + * Returns a generator that transforms values by calling $transformer. Maintains original keys. * @template K * @template V * @template R @@ -158,14 +162,14 @@ final class Iterables /** - * Iterator that transforms keys and values by calling $transformer. If it returns null, the element is skipped. + * Returns a generator that transforms keys and values by calling $transformer. If it returns null, the element is skipped. * @template K * @template V - * @template ResV * @template ResK + * @template ResV * @param iterable $iterable - * @param callable(V, K, iterable): ?array{ResV, ResK} $transformer - * @return \Generator + * @param callable(V, K, iterable): ?array{ResK, ResV} $transformer + * @return \Generator */ public static function mapWithKeys(iterable $iterable, callable $transformer): \Generator { @@ -188,9 +192,10 @@ final class Iterables */ public static function repeatable(callable $factory): \IteratorAggregate { - return new class ($factory) implements \IteratorAggregate { + return new class ($factory(...)) implements \IteratorAggregate { public function __construct( - private $factory, + /** @var \Closure(): iterable */ + private \Closure $factory, ) { } @@ -215,7 +220,8 @@ final class Iterables { return new class (self::toIterator($iterable)) implements \IteratorAggregate { public function __construct( - private \Iterator $iterator, + private readonly \Iterator $iterator, + /** @var array */ private array $cache = [], ) { } diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Json.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Json.php index 4e4cf23..8a5a62e 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Json.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Json.php @@ -1,12 +1,10 @@ - $firstItemOnPage * @property-read int<0,max> $lastItemOnPage * @property int $base * @property-read bool $first * @property-read bool $last - * @property-read int<0,max>|null $pageCount + * @property-read ?int<0,max> $pageCount * @property positive-int $itemsPerPage - * @property int<0,max>|null $itemCount + * @property ?int<0,max> $itemCount * @property-read int<0,max> $offset - * @property-read int<0,max>|null $countdownOffset + * @property-read ?int<0,max> $countdownOffset * @property-read int<0,max> $length */ class Paginator @@ -41,13 +39,10 @@ class Paginator private int $page = 1; - /** @var int<0, max>|null */ + /** @var ?int<0, max> */ private ?int $itemCount = null; - /** - * Sets current page number. - */ public function setPage(int $page): static { $this->page = $page; @@ -55,27 +50,18 @@ class Paginator } - /** - * Returns current page number. - */ public function getPage(): int { return $this->base + $this->getPageIndex(); } - /** - * Returns first page number. - */ public function getFirstPage(): int { return $this->base; } - /** - * Returns last page number. - */ public function getLastPage(): ?int { return $this->itemCount === null @@ -85,7 +71,7 @@ class Paginator /** - * Returns the sequence number of the first element on the page + * Returns the 1-based index of the first item on the current page, or 0 if the page is empty. * @return int<0, max> */ public function getFirstItemOnPage(): int @@ -97,7 +83,7 @@ class Paginator /** - * Returns the sequence number of the last element on the page + * Returns the 1-based index of the last item on the current page. * @return int<0, max> */ public function getLastItemOnPage(): int @@ -106,9 +92,6 @@ class Paginator } - /** - * Sets first page (base) number. - */ public function setBase(int $base): static { $this->base = $base; @@ -116,9 +99,6 @@ class Paginator } - /** - * Returns first page (base) number. - */ public function getBase(): int { return $this->base; @@ -138,18 +118,12 @@ class Paginator } - /** - * Is the current page the first one? - */ public function isFirst(): bool { return $this->getPageIndex() === 0; } - /** - * Is the current page the last one? - */ public function isLast(): bool { return $this->itemCount === null @@ -159,20 +133,16 @@ class Paginator /** - * Returns the total number of pages. - * @return int<0, max>|null + * @return ?int<0, max> */ public function getPageCount(): ?int { return $this->itemCount === null ? null - : (int) ceil($this->itemCount / $this->itemsPerPage); + : max(0, (int) ceil($this->itemCount / $this->itemsPerPage)); } - /** - * Sets the number of items to display on a single page. - */ public function setItemsPerPage(int $itemsPerPage): static { $this->itemsPerPage = max(1, $itemsPerPage); @@ -181,7 +151,6 @@ class Paginator /** - * Returns the number of items to display on a single page. * @return positive-int */ public function getItemsPerPage(): int @@ -190,9 +159,6 @@ class Paginator } - /** - * Sets the total number of items. - */ public function setItemCount(?int $itemCount = null): static { $this->itemCount = $itemCount === null ? null : max(0, $itemCount); @@ -201,8 +167,7 @@ class Paginator /** - * Returns the total number of items. - * @return int<0, max>|null + * @return ?int<0, max> */ public function getItemCount(): ?int { @@ -222,7 +187,7 @@ class Paginator /** * Returns the absolute index of the first item on current page in countdown paging. - * @return int<0, max>|null + * @return ?int<0, max> */ public function getCountdownOffset(): ?int { @@ -240,6 +205,6 @@ class Paginator { return $this->itemCount === null ? $this->itemsPerPage - : min($this->itemsPerPage, $this->itemCount - $this->getPageIndex() * $this->itemsPerPage); + : max(0, min($this->itemsPerPage, $this->itemCount - $this->getPageIndex() * $this->itemsPerPage)); } } diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Process.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Process.php new file mode 100644 index 0000000..8ec0a5b --- /dev/null +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Process.php @@ -0,0 +1,507 @@ + result of proc_get_status() */ + private array $status = ['running' => true]; + + /** @var resource */ + private mixed $inputPipe; + + /** @var array pipe resources, or ['file', path, mode] descriptors for discarded output */ + private array $outputPipes = []; + + /** @var string[] */ + private array $outputBuffers = []; + + /** @var int[] Number of bytes already read from buffers. */ + private array $outputBufferOffsets = []; + + /** @var array Output IDs whose target resource was supplied by the caller and must not be closed here. */ + private array $callerOutputs = []; + private float $startTime; + + + /** + * Starts an executable with given arguments. Because the arguments are passed as an array, the shell is + * never involved, so they need no escaping and there is no risk of shell injection. + * @param string $executable Path to the executable binary. + * @param list $arguments Arguments passed to the executable. + * @param string[]|null $env Environment variables or null to use the same environment as the current process. + * @param array $options Additional options for proc_open(). On Windows the executable is launched directly, without cmd.exe. + * @param mixed $stdin Input: string, a readable resource (its content is copied to STDIN), a Process (its STDOUT is piped in), or null (STDIN stays open for writeStdInput()). + * @param mixed $stdout Output target: string filename, a writable resource backed by a real OS file descriptor (not php://memory etc.), false to discard, or null to capture into memory. + * @param mixed $stderr Error output target (same options as $stdout). + * @param string|null $directory Working directory. + * @param float|null $timeout Time limit in seconds, checked while waiting for or reading the process; null disables it. + */ + public static function runExecutable( + string $executable, + array $arguments = [], + ?array $env = null, + array $options = [], + mixed $stdin = '', + mixed $stdout = null, + mixed $stderr = null, + ?string $directory = null, + ?float $timeout = self::DefaultTimeout, + ): self + { + return new self([$executable, ...$arguments], $env, $options, $directory, $stdin, $stdout, $stderr, $timeout); + } + + + /** + * Starts a process from a command string interpreted by the shell (/bin/sh on POSIX, cmd.exe on Windows). + * Because the shell parses the string, NEVER pass unescaped user input here - use runExecutable() for that. + * @param string $command Shell command to run. + * @param string[]|null $env Environment variables or null to use the same environment as the current process. + * @param array $options Options for proc_open(), e.g. ['bypass_shell' => true] on Windows to skip cmd.exe. + * @param mixed $stdin Input: string, a readable resource (its content is copied to STDIN), a Process (its STDOUT is piped in), or null (STDIN stays open for writeStdInput()). + * @param mixed $stdout Output target: string filename, a writable resource backed by a real OS file descriptor (not php://memory etc.), false to discard, or null to capture into memory. + * @param mixed $stderr Error output target (same options as $stdout). + * @param string|null $directory Working directory. + * @param float|null $timeout Time limit in seconds, checked while waiting for or reading the process; null disables it. + */ + public static function runCommand( + string $command, + ?array $env = null, + array $options = [], + mixed $stdin = '', + mixed $stdout = null, + mixed $stderr = null, + ?string $directory = null, + ?float $timeout = self::DefaultTimeout, + ): self + { + return new self($command, $env, $options, $directory, $stdin, $stdout, $stderr, $timeout); + } + + + /** + * @param list|string $command + * @param array|null $env + * @param array $options + */ + private function __construct( + string|array $command, + ?array $env, + array $options, + ?string $directory, + mixed $stdin, + mixed $stdout, + mixed $stderr, + private ?float $timeout, + ) { + $descriptors = [ + self::StdIn => $this->createInputDescriptor($stdin), + self::StdOut => $this->createOutputDescriptor(self::StdOut, $stdout), + self::StdErr => $this->createOutputDescriptor(self::StdErr, $stderr), + ]; + + $process = @proc_open($command, $descriptors, $pipes, $directory, $env, $options); + if (!is_resource($process)) { + throw new ProcessFailedException('Failed to start process: ' . Helpers::getLastError()); + } + + $this->process = $process; + [$this->inputPipe, $this->outputPipes[self::StdOut], $this->outputPipes[self::StdErr]] = $pipes + $descriptors; + + if ($stdin instanceof self) { + // the source process hands over its STDOUT pipe; from now on this process owns it + unset( + $stdin->outputBuffers[self::StdOut], + $stdin->outputBufferOffsets[self::StdOut], + $stdin->outputPipes[self::StdOut], + ); + } + + $this->writeInitialInput($stdin); + $this->startTime = microtime(true); + } + + + public function __destruct() + { + $this->outputBuffers = []; + $this->terminate(); + } + + + /** + * Checks if the process is currently running. + */ + public function isRunning(): bool + { + if (!$this->status['running']) { + return false; + } + + $this->status = proc_get_status($this->process); + if (!$this->status['running']) { + $this->close(); + } + + return $this->status['running']; + } + + + /** + * Finishes the process by waiting for its completion. While waiting, the captured output is read + * continuously and kept in memory; an optional callback is invoked with each new output/error chunk. + * + * @param (\Closure(string, string): void)|null $callback + */ + public function wait(?\Closure $callback = null): void + { + while ($this->isRunning()) { + $this->enforceTimeout(); + $this->drainPipes(); + $this->dispatchCallback($callback); + usleep(self::PollInterval); + } + + $this->dispatchCallback($callback); + } + + + /** + * Reads any new data from the captured pipes into the buffers, so a process producing more output + * than the OS pipe buffer holds does not block. (On Windows the captured output is a file and never blocks.) + */ + private function drainPipes(): void + { + foreach ([self::StdOut, self::StdErr] as $id) { + $this->readFromPipe($id); + } + } + + + /** + * Terminates the running process if it is still running. + */ + public function terminate(): void + { + if (!$this->isRunning()) { + return; + } elseif (Helpers::IsWindows) { + exec("taskkill /F /T /PID {$this->getPid()} 2>&1"); + } else { + proc_terminate($this->process, 9); // 9 = SIGKILL: cannot be trapped, so the following proc_close() won't hang + } + $this->status['running'] = false; + $this->close(); + } + + + /** + * Returns the process exit code. If the process is still running, waits until it finishes. + */ + public function getExitCode(): int + { + $this->wait(); + return $this->status['exitcode'] ?? -1; + } + + + /** + * Returns true if the process terminated with exit code 0. + */ + public function isSuccess(): bool + { + return $this->getExitCode() === 0; + } + + + /** + * Waits for the process to finish and throws ProcessFailedException if exit code is not zero. + */ + public function ensureSuccess(): void + { + $code = $this->getExitCode(); + if ($code !== 0) { + throw new ProcessFailedException("Process failed with non-zero exit code: $code"); + } + } + + + /** + * Returns the PID of the running process, or null if it is not running. + */ + public function getPid(): ?int + { + return $this->isRunning() ? $this->status['pid'] : null; + } + + + /** + * Waits for the process to finish and returns everything it wrote to STDOUT. + */ + public function getStdOutput(): string + { + $this->wait(); + return $this->outputBuffers[self::StdOut] ?? throw new Nette\InvalidStateException('Cannot read output: it is not captured (it was redirected, discarded or piped).'); + } + + + /** + * Waits for the process to finish and returns everything it wrote to STDERR. + */ + public function getStdError(): string + { + $this->wait(); + return $this->outputBuffers[self::StdErr] ?? throw new Nette\InvalidStateException('Cannot read output: it is not captured (it was redirected, discarded or piped).'); + } + + + /** + * Returns the STDOUT data produced since the previous consumeStdOutput() call. + * To read everything incrementally, poll `while ($p->isRunning())` calling this, then call it once more + * after the loop; that last call returns whatever the process wrote just before the loop noticed it had exited. + */ + public function consumeStdOutput(): string + { + return $this->consumeBuffer(self::StdOut); + } + + + /** + * Returns the STDERR data produced since the previous consumeStdError() call. See consumeStdOutput(). + */ + public function consumeStdError(): string + { + return $this->consumeBuffer(self::StdErr); + } + + + /** + * Returns newly available data from the specified buffer and advances the read pointer. + */ + private function consumeBuffer(int $id): string + { + if (!isset($this->outputBuffers[$id])) { + throw new Nette\InvalidStateException('Cannot read output: it is not captured (it was redirected, discarded or piped).'); + } elseif ($this->isRunning()) { + $this->enforceTimeout(); + $this->readFromPipe($id); + } + return $this->extractNewData($id); + } + + + /** + * Returns the buffered data not returned yet and advances the read pointer. + */ + private function extractNewData(int $id): string + { + if (!isset($this->outputBuffers[$id])) { + return ''; + } + $res = substr($this->outputBuffers[$id], $this->outputBufferOffsets[$id]); + $this->outputBufferOffsets[$id] = strlen($this->outputBuffers[$id]); + return $res; + } + + + /** + * Writes data into the process' STDIN. If STDIN is closed, throws exception. + */ + public function writeStdInput(string $string): void + { + if (!is_resource($this->inputPipe)) { + throw new Nette\InvalidStateException('Cannot write to process: STDIN pipe is closed'); + } + $this->writeToPipe($string); + } + + + /** + * Writes the whole string to STDIN, handling partial writes. Stops (and lets fwrite() warn) on a broken pipe, + * i.e. when the process stopped reading its STDIN. + */ + private function writeToPipe(string $string): void + { + $length = strlen($string); + for ($written = 0; $written < $length; $written += $bytes) { + $bytes = fwrite($this->inputPipe, substr($string, $written)); + if (!$bytes) { + break; + } + } + } + + + /** + * Closes the STDIN pipe, indicating no more data will be sent. + */ + public function closeStdInput(): void + { + if (is_resource($this->inputPipe)) { + fclose($this->inputPipe); + } + } + + + /** + * If a callback is given, invokes it with the output/error produced since the previous call. + * @param (\Closure(string, string): void)|null $callback + */ + private function dispatchCallback(?\Closure $callback): void + { + if (!$callback) { + return; + } + $output = $this->extractNewData(self::StdOut); + $error = $this->extractNewData(self::StdErr); + if ($output !== '' || $error !== '') { + $callback($output, $error); + } + } + + + /** + * Checks if the timeout has expired. If yes, terminates the process. + */ + private function enforceTimeout(): void + { + if ($this->timeout !== null && (microtime(true) - $this->startTime) >= $this->timeout) { + $this->terminate(); + throw new ProcessTimeoutException('Process exceeded the time limit of ' . $this->timeout . ' seconds'); + } + } + + + /** + * Reads any new data from the specified pipe and appends it to the buffer. Does nothing if the output + * is not captured or the pipe is already closed (or handed over to another process). + */ + private function readFromPipe(int $id): void + { + if (!isset($this->outputBuffers[$id]) || !is_resource($this->outputPipes[$id] ?? null)) { + return; + } elseif (Helpers::IsWindows) { + fseek($this->outputPipes[$id], strlen($this->outputBuffers[$id])); + } else { + stream_set_blocking($this->outputPipes[$id], false); + } + $this->outputBuffers[$id] .= stream_get_contents($this->outputPipes[$id]); + } + + + /** + * Sends the initial input to the process: writes and closes a string or stream input, + * or leaves STDIN open when input is null (until closeStdInput()) or another Process (fed by that process). + * The input type was already validated by createInputDescriptor(). + * + * Note: a string or stream input is written upfront, so if it is large and the process does not read it + * while filling its own output, this can block; in that case pass null and feed STDIN via writeStdInput(). + */ + private function writeInitialInput(mixed $input): void + { + if ($input === null || $input instanceof self) { + // STDIN stays open + + } elseif (is_string($input)) { + $this->writeToPipe($input); + $this->closeStdInput(); + + } elseif (is_resource($input)) { + stream_copy_to_stream($input, $this->inputPipe); + $this->closeStdInput(); + } + } + + + /** + * Validates the input and determines the STDIN descriptor based on its type. + */ + private function createInputDescriptor(mixed $input): mixed + { + if ($input === null || is_string($input) || is_resource($input)) { + return ['pipe', 'r']; + } elseif (!$input instanceof self) { + throw new Nette\InvalidArgumentException('Input must be string, resource, Process or null, ' . get_debug_type($input) . ' given.'); + } elseif (Helpers::IsWindows) { + throw new Nette\NotSupportedException('Process piping is not supported on Windows.'); + } elseif (!isset($input->outputBuffers[self::StdOut]) || !is_resource($input->outputPipes[self::StdOut] ?? null)) { + throw new Nette\InvalidStateException('Cannot pipe from the given process: its STDOUT must be captured (it must not be redirected elsewhere).'); + } + return $input->outputPipes[self::StdOut]; + } + + + /** + * Determines the descriptor for STDOUT or STDERR based on the specified output target. + */ + private function createOutputDescriptor(int $id, mixed $output): mixed + { + if (is_resource($output)) { + $this->callerOutputs[$id] = true; + return $output; + + } elseif (is_string($output)) { + return FileSystem::open($output, 'w'); + + } elseif ($output === false) { + return ['file', Helpers::IsWindows ? 'NUL' : '/dev/null', 'w']; + + } elseif ($output === null) { + $this->outputBuffers[$id] = ''; + $this->outputBufferOffsets[$id] = 0; + // On Windows anonymous pipes are blocking and cannot be polled without freezing the process, + // so captured output is backed by a temporary file that can be read non-blockingly (needed for timeouts). + return Helpers::IsWindows ? tmpfile() : ['pipe', 'w']; + + } else { + throw new Nette\InvalidArgumentException('Output must be string, resource, bool or null, ' . get_debug_type($output) . ' given.'); + } + } + + + /** + * Closes all pipes and the process resource. + */ + private function close(): void + { + $this->drainPipes(); + $this->closeStdInput(); + $this->closeOutputPipes(); + proc_close($this->process); + } + + + /** + * Closes the output pipes that this class opened; resources supplied by the caller are left untouched. + * (The temporary file backing captured output on Windows is removed by fclose() itself.) + */ + private function closeOutputPipes(): void + { + foreach ($this->outputPipes as $id => $pipe) { + if (is_resource($pipe) && !isset($this->callerOutputs[$id])) { + fclose($pipe); + } + } + } +} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Random.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Random.php index e636dd0..f3ec874 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Random.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Random.php @@ -1,12 +1,10 @@ -isDefaultValueConstant()) { - $const = $orig = $param->getDefaultValueConstantName(); + $const = $orig = $param->getDefaultValueConstantName() ?? throw new Nette\ShouldNotHappenException; $pair = explode('::', $const); if (isset($pair[1])) { $pair[0] = Type::resolve($pair[0], $param); @@ -68,6 +70,7 @@ final class Reflection /** * Returns a reflection of a class or trait that contains a declaration of given property. Property can also be declared in the trait. + * @return \ReflectionClass */ public static function getPropertyDeclaringClass(\ReflectionProperty $prop): \ReflectionClass { @@ -130,6 +133,9 @@ final class Reflection } + /** + * Returns a human-readable string representation of a reflection object. + */ public static function toString(\Reflector $ref): string { if ($ref instanceof \ReflectionClass) { @@ -151,6 +157,7 @@ final class Reflection /** * Expands the name of the class to full name in the given context of given class. * Thus, it returns how the PHP parser would understand $name if it were written in the body of the class $context. + * @param \ReflectionClass $context * @throws Nette\InvalidArgumentException */ public static function expandClassName(string $name, \ReflectionClass $context): string @@ -189,7 +196,11 @@ final class Reflection } - /** @return array of [alias => class] */ + /** + * Returns the use statements from the file where the class is defined. + * @param \ReflectionClass $class + * @return array Map of alias to fully qualified class name + */ public static function getUseStatements(\ReflectionClass $class): array { if ($class->isAnonymous()) { @@ -201,7 +212,7 @@ final class Reflection if ($class->isInternal()) { $cache[$name] = []; } else { - $code = file_get_contents($class->getFileName()); + $code = (string) file_get_contents((string) $class->getFileName()); $cache = self::parseUseStatements($code, $name) + $cache; } } @@ -212,6 +223,7 @@ final class Reflection /** * Parses PHP code to [class => [alias => class, ...]] + * @return array> */ private static function parseUseStatements(string $code, ?string $forClass = null): array { @@ -256,8 +268,8 @@ final class Reflection $name = ltrim($name, '\\'); if (self::fetch($tokens, '{')) { while ($suffix = self::fetch($tokens, $nameTokens)) { - if (self::fetch($tokens, T_AS)) { - $uses[self::fetch($tokens, T_STRING)] = $name . $suffix; + if (self::fetch($tokens, T_AS) && ($alias = self::fetch($tokens, T_STRING))) { + $uses[$alias] = $name . $suffix; } else { $tmp = explode('\\', $suffix); $uses[end($tmp)] = $name . $suffix; @@ -267,8 +279,8 @@ final class Reflection break; } } - } elseif (self::fetch($tokens, T_AS)) { - $uses[self::fetch($tokens, T_STRING)] = $name; + } elseif (self::fetch($tokens, T_AS) && ($alias = self::fetch($tokens, T_STRING))) { + $uses[$alias] = $name; } else { $tmp = explode('\\', $name); @@ -301,6 +313,10 @@ final class Reflection } + /** + * @param \PhpToken[] $tokens + * @param string|int|int[] $take + */ private static function fetch(array &$tokens, string|int|array $take): ?string { $res = null; diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/ReflectionMethod.php b/tools/.phpstan/vendor/nette/utils/src/Utils/ReflectionMethod.php index 2a8a55c..fe2159c 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/ReflectionMethod.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/ReflectionMethod.php @@ -1,12 +1,10 @@ - */ + private readonly \ReflectionClass $originalClass; + /** @param class-string|object $objectOrMethod */ public function __construct(object|string $objectOrMethod, ?string $method = null) { if (is_string($objectOrMethod) && str_contains($objectOrMethod, '::')) { @@ -31,6 +31,7 @@ final class ReflectionMethod extends \ReflectionMethod } + /** @return \ReflectionClass */ public function getOriginalClass(): \ReflectionClass { return $this->originalClass; diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Strings.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Strings.php index eb44b48..59656ea 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Strings.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Strings.php @@ -1,12 +1,10 @@ - '(R)', "\u{A9}" => '(c)', "\u{2026}" => '...', "\u{AB}" => '<<', "\u{BB}" => '>>', "\u{A3}" => 'lb', "\u{A5}" => 'yen', "\u{B2}" => '^2', "\u{B3}" => '^3', "\u{B5}" => 'u', "\u{B9}" => '^1', "\u{BA}" => 'o', "\u{BF}" => '?', "\u{2CA}" => "'", "\u{2CD}" => '_', "\u{2DD}" => '"', "\u{1FEF}" => '', "\u{20AC}" => 'EUR', "\u{2122}" => 'TM', "\u{212E}" => 'e', "\u{2190}" => '<-', "\u{2191}" => '^', "\u{2192}" => '->', "\u{2193}" => 'V', "\u{2194}" => '<->']); // ® © … « » £ ¥ ² ³ µ ¹ º ¿ ˊ ˍ ˝ ` € ™ ℮ ← ↑ → ↓ ↔ } - $s = \Transliterator::create('Any-Latin; Latin-ASCII')->transliterate($s); + $s = \Transliterator::create('Any-Latin; Latin-ASCII')?->transliterate($s) + ?? throw new Nette\InvalidStateException('Transliterator::transliterate() failed.'); + // use iconv because The transliterator leaves some characters out of ASCII, eg → ʾ if ($iconv === 'glibc') { $s = strtr($s, '?', "\x01"); // temporarily hide ? to distinguish them from the garbage that iconv creates $s = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s); + if ($s === false) { + throw new Nette\InvalidStateException('iconv() failed.'); + } + $s = str_replace(['?', "\x01"], ['', '?'], $s); // remove garbage and restore ? characters } elseif ($iconv === 'libiconv') { $s = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s); + if ($s === false) { + throw new Nette\InvalidStateException('iconv() failed.'); + } } else { // null or 'unknown' (#216) $s = self::pcre('preg_replace', ['#[^\x00-\x7F]++#', '', $s]); // remove non-ascii chars } @@ -323,7 +332,7 @@ class Strings */ public static function compare(string $left, string $right, ?int $length = null): bool { - if (class_exists('Normalizer', false)) { + if (class_exists('Normalizer', autoload: false)) { $left = \Normalizer::normalize($left, \Normalizer::FORM_D); // form NFD is faster $right = \Normalizer::normalize($right, \Normalizer::FORM_D); // form NFD is faster } @@ -347,6 +356,10 @@ class Strings public static function findPrefix(array $strings): string { $first = array_shift($strings); + if ($first === null) { + return ''; + } + for ($i = 0; $i < strlen($first); $i++) { foreach ($strings as $s) { if (!isset($s[$i]) || $first[$i] !== $s[$i]) { @@ -370,8 +383,8 @@ class Strings public static function length(string $s): int { return match (true) { - extension_loaded('mbstring') => mb_strlen($s, 'UTF-8'), - extension_loaded('iconv') => iconv_strlen($s, 'UTF-8'), + extension_loaded('mbstring') => (int) mb_strlen($s, 'UTF-8'), + extension_loaded('iconv') => (int) iconv_strlen($s, 'UTF-8'), default => strlen(@utf8_decode($s)), // deprecated }; } @@ -420,7 +433,10 @@ class Strings throw new Nette\NotSupportedException(__METHOD__ . '() requires ICONV extension that is not loaded.'); } - return iconv('UTF-32LE', 'UTF-8', strrev(iconv('UTF-8', 'UTF-32BE', $s))); + $tmp = iconv('UTF-8', 'UTF-32BE', $s); + return $tmp === false + ? throw new Nette\InvalidStateException('iconv() failed.') + : (string) iconv('UTF-32LE', 'UTF-8', strrev($tmp)); } @@ -498,7 +514,8 @@ class Strings /** - * Divides the string into arrays according to the regular expression. Expressions in parentheses will be captured and returned as well. + * Splits the string by a regular expression. Expressions in parentheses will be captured and returned as well. + * @return list */ public static function split( string $subject, @@ -523,8 +540,9 @@ class Strings /** - * Searches the string for the part matching the regular expression and returns - * an array with the found expression and individual subexpressions, or `null`. + * Searches the string for the first match of the regular expression and returns + * an array with the found expression and individual subexpressions, or null. + * @return ?array */ public static function match( string $subject, @@ -545,6 +563,7 @@ class Strings $pattern .= 'u'; } + $m = []; if ($offset > strlen($subject)) { return null; } elseif (!self::pcre('preg_match', [$pattern, $subject, &$m, $flags, $offset])) { @@ -558,9 +577,9 @@ class Strings /** - * Searches the string for all occurrences matching the regular expression and - * returns an array of arrays containing the found expression and each subexpression. - * @return ($lazy is true ? \Generator : array[]) + * Searches the string for all occurrences matching the regular expression and returns + * an array of arrays containing the found expression and each subexpression. + * @return ($lazy is true ? \Generator> : list>) */ public static function matchAll( string $subject, @@ -583,10 +602,12 @@ class Strings $flags = PREG_OFFSET_CAPTURE | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0); return (function () use ($utf8, $captureOffset, $flags, $subject, $pattern, $offset) { $counter = 0; + $m = []; while ( $offset <= strlen($subject) - ($counter ? 1 : 0) && self::pcre('preg_match', [$pattern, $subject, &$m, $flags, $offset]) ) { + /** @var list $m */ $offset = $m[0][1] + max(1, strlen($m[0][0])); if (!$captureOffset) { $m = array_map(fn($item) => $item[0], $m); @@ -606,6 +627,7 @@ class Strings ? $captureOffset : ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0) | ($patternOrder ? PREG_PATTERN_ORDER : 0); + $m = []; self::pcre('preg_match_all', [ $pattern, $subject, &$m, ($flags & PREG_PATTERN_ORDER) ? $flags : ($flags | PREG_SET_ORDER), @@ -618,7 +640,8 @@ class Strings /** - * Replaces all occurrences matching regular expression $pattern which can be string or array in the form `pattern => replacement`. + * Replaces all occurrences matching the regular expression $pattern, which can be a string or array in the form `pattern => replacement`. + * @param string|array $pattern */ public static function replace( string $subject, @@ -638,7 +661,7 @@ class Strings $flags = ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0); if ($utf8) { - $pattern .= 'u'; + $pattern = is_array($pattern) ? array_map(fn($item) => $item . 'u', $pattern) : $pattern . 'u'; if ($captureOffset) { $replacement = fn($m) => $replacement(self::bytesToChars($subject, [$m])[0]); } @@ -659,6 +682,10 @@ class Strings } + /** + * @param list> $groups + * @return list> + */ private static function bytesToChars(string $s, array $groups): array { $lastBytes = $lastChars = 0; @@ -679,8 +706,12 @@ class Strings } - /** @internal */ - public static function pcre(string $func, array $args) + /** + * @param callable-string $func + * @param list $args + * @internal + */ + public static function pcre(string $func, array $args): mixed { $res = Callback::invokeSafe($func, $args, function (string $message) use ($args): void { // compile-time error, not detectable by preg_last_error @@ -688,7 +719,7 @@ class Strings }); if (($code = preg_last_error()) // run-time error, but preg_last_error & return code are liars - && ($res === null || !in_array($func, ['preg_filter', 'preg_replace_callback', 'preg_replace'], true)) + && ($res === null || !in_array($func, ['preg_filter', 'preg_replace_callback', 'preg_replace'], strict: true)) ) { throw new RegexpException(preg_last_error_msg() . ' (pattern: ' . implode(' or ', (array) $args[0]) . ')', $code); diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Type.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Type.php index 92aac80..329475c 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Type.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Type.php @@ -1,16 +1,14 @@ - */ + /** @var list */ private array $types; - private bool $simple; + private ?string $singleName; private string $kind; // | & @@ -40,7 +38,12 @@ final readonly class Type } - private static function fromReflectionType(\ReflectionType $type, $of, bool $asObject): self|string + /** @return ($asObject is true ? self : self|string) */ + private static function fromReflectionType( + \ReflectionType $type, + \ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $of, + bool $asObject, + ): self|string { if ($type instanceof \ReflectionNamedType) { $name = self::resolve($type->getName(), $of); @@ -107,34 +110,40 @@ final readonly class Type */ public static function resolve( string $type, - \ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $of, + \ReflectionFunction|\ReflectionMethod|\ReflectionParameter|\ReflectionProperty $of, ): string { $lower = strtolower($type); if ($of instanceof \ReflectionFunction) { return $type; + } + + $class = $of->getDeclaringClass(); + if ($class === null) { + return $type; } elseif ($lower === 'self') { - return $of->getDeclaringClass()->name; + return $class->name; } elseif ($lower === 'static') { - return ($of instanceof ReflectionMethod ? $of->getOriginalClass() : $of->getDeclaringClass())->name; - } elseif ($lower === 'parent' && $of->getDeclaringClass()->getParentClass()) { - return $of->getDeclaringClass()->getParentClass()->name; + return ($of instanceof ReflectionMethod ? $of->getOriginalClass() : $class)->name; + } elseif ($lower === 'parent' && $class->getParentClass()) { + return $class->getParentClass()->name; } else { return $type; } } + /** @param array $types */ private function __construct(array $types, string $kind = '|') { $o = array_search('null', $types, strict: true); if ($o !== false) { // null as last - array_splice($types, $o, 1); + array_splice($types, (int) $o, 1); $types[] = 'null'; } - $this->types = $types; - $this->simple = is_string($types[0]) && ($types[1] ?? 'null') === 'null'; + $this->types = array_values($types); + $this->singleName = is_string($types[0]) && ($types[1] ?? 'null') === 'null' ? $types[0] : null; $this->kind = count($types) > 1 ? $kind : ''; } @@ -142,8 +151,8 @@ final readonly class Type public function __toString(): string { $multi = count($this->types) > 1; - if ($this->simple) { - return ($multi ? '?' : '') . $this->types[0]; + if ($this->singleName !== null) { + return ($multi ? '?' : '') . $this->singleName; } $res = []; @@ -155,7 +164,7 @@ final readonly class Type /** - * Returns a type that accepts both the current type and the given type. + * Returns a union type that accepts both the current type and the given type. */ public function with(string|self $type): self { @@ -173,7 +182,7 @@ final readonly class Type /** * Returns the array of subtypes that make up the compound type as strings. - * @return array + * @return list>> */ public function getNames(): array { @@ -182,8 +191,8 @@ final readonly class Type /** - * Returns the array of subtypes that make up the compound type as Type objects: - * @return self[] + * Returns the array of subtypes that make up the compound type as Type objects. + * @return list */ public function getTypes(): array { @@ -196,9 +205,7 @@ final readonly class Type */ public function getSingleName(): ?string { - return $this->simple - ? $this->types[0] - : null; + return $this->singleName; } @@ -221,36 +228,36 @@ final readonly class Type /** - * Returns true whether it is a simple type. Single nullable types are also considered to be simple types. + * Checks whether it is a simple (non-compound) type. Single nullable types such as ?int are also considered simple. */ public function isSimple(): bool { - return $this->simple; + return $this->singleName !== null; } #[\Deprecated('use isSimple()')] public function isSingle(): bool { - return $this->simple; + return $this->singleName !== null; } /** - * Returns true whether the type is both a simple and a PHP built-in type. + * Checks whether it is a simple PHP built-in type (int, string, bool, etc.). */ public function isBuiltin(): bool { - return $this->simple && Validators::isBuiltinType($this->types[0]); + return $this->singleName !== null && Validators::isBuiltinType($this->singleName); } /** - * Returns true whether the type is both a simple and a class name. + * Checks whether it is a simple class or interface name (not a built-in type). */ public function isClass(): bool { - return $this->simple && !Validators::isBuiltinType($this->types[0]); + return $this->singleName !== null && !Validators::isBuiltinType($this->singleName); } @@ -259,12 +266,12 @@ final readonly class Type */ public function isClassKeyword(): bool { - return $this->simple && Validators::isClassKeyword($this->types[0]); + return $this->singleName !== null && Validators::isClassKeyword($this->singleName); } /** - * Verifies type compatibility. For example, it checks if a value of a certain type could be passed as a parameter. + * Checks whether a value of the given type could be assigned to this type. */ public function allows(string|self $type): bool { @@ -279,6 +286,7 @@ final readonly class Type } + /** @param array $givenTypes */ private function allowsAny(array $givenTypes): bool { return $this->isUnion() @@ -287,13 +295,17 @@ final readonly class Type } + /** + * @param array $ourTypes + * @param array $givenTypes + */ private function allowsAll(array $ourTypes, array $givenTypes): bool { return Arrays::every( $ourTypes, - fn($ourType) => Arrays::some( + fn(string $ourType) => Arrays::some( $givenTypes, - fn($givenType) => Validators::isBuiltinType($ourType) + fn(string $givenType) => Validators::isBuiltinType($ourType) ? strcasecmp($ourType, $givenType) === 0 : is_a($givenType, $ourType, allow_string: true), ), diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Validators.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Validators.php index 940c3eb..9e7bd5b 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Validators.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/Validators.php @@ -1,12 +1,10 @@ - 1, 'true' => 1, ]; - /** @var array */ + /** @var array */ protected static $validators = [ // PHP types 'array' => 'is_array', @@ -76,7 +74,7 @@ class Validators 'type' => [self::class, 'isType'], ]; - /** @var array */ + /** @var array */ protected static $counters = [ 'string' => 'strlen', 'unicode' => [Strings::class, 'length'], @@ -114,22 +112,22 @@ class Validators /** - * Verifies that element $key in array is of expected types separated by pipe. + * Verifies that item $key in array exists and is of expected types separated by pipe. * @param mixed[] $array * @throws AssertionException */ public static function assertField( array $array, - $key, + int|string $key, ?string $expected = null, string $label = "item '%' in array", ): void { if (!array_key_exists($key, $array)) { - throw new AssertionException('Missing ' . str_replace('%', $key, $label) . '.'); + throw new AssertionException('Missing ' . str_replace('%', (string) $key, $label) . '.'); } elseif ($expected) { - static::assert($array[$key], $expected, str_replace('%', $key, $label)); + static::assert($array[$key], $expected, str_replace('%', (string) $key, $label)); } } @@ -159,7 +157,7 @@ class Validators if (!static::$validators[$type]($value)) { continue; } - } catch (\TypeError $e) { + } catch (\TypeError) { continue; } } elseif ($type === 'pattern') { @@ -197,7 +195,7 @@ class Validators /** * Finds whether all values are of expected types separated by pipe. - * @param mixed[] $values + * @param iterable $values */ public static function everyIs(iterable $values, string $expected): bool { @@ -261,7 +259,7 @@ class Validators /** * Checks if the value is 0, '', false or null. - * @return ($value is 0|''|false|null ? true : false) + * @return ($value is 0|0.0|''|false|null ? true : false) */ public static function isNone(mixed $value): bool { @@ -290,6 +288,7 @@ class Validators /** * Checks if the value is in the given range [min, max], where the upper or lower limit can be omitted (null). * Numbers, strings and DateTime objects can be compared. + * @param array{int|float|string|\DateTimeInterface|null, int|float|string|\DateTimeInterface|null} $range */ public static function isInRange(mixed $value, array $range): bool { diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/exceptions.php b/tools/.phpstan/vendor/nette/utils/src/Utils/exceptions.php index 30805ea..ba1cdfe 100644 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/exceptions.php +++ b/tools/.phpstan/vendor/nette/utils/src/Utils/exceptions.php @@ -1,12 +1,10 @@ - 'rules.neon', ), ), - 'version' => '2.12.0', - 'phpstanVersionConstraint' => '>=2.1.8.0-dev, <3.0.0.0-dev', + 'version' => '2.13.1', + 'phpstanVersionConstraint' => '>=2.1.35.0-dev, <3.0.0.0-dev', ), 'phpstan/phpstan-strict-rules' => array ( @@ -35,8 +35,8 @@ final class GeneratedConfig 0 => 'rules.neon', ), ), - 'version' => '2.0.7', - 'phpstanVersionConstraint' => '>=2.1.29.0-dev, <3.0.0.0-dev', + 'version' => '2.0.11', + 'phpstanVersionConstraint' => '>=2.1.39.0-dev, <3.0.0.0-dev', ), 'tomasvotruba/type-coverage' => array ( @@ -58,7 +58,7 @@ final class GeneratedConfig ); /** @var string|null */ - public const PHPSTAN_VERSION_CONSTRAINT = '>=2.1.29.0-dev, <3.0.0.0-dev'; + public const PHPSTAN_VERSION_CONSTRAINT = '>=2.1.39.0-dev, <3.0.0.0-dev'; private function __construct() { diff --git a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/.editorconfig b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/.editorconfig deleted file mode 100644 index 5d66bc4..0000000 --- a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/.editorconfig +++ /dev/null @@ -1,27 +0,0 @@ -root = true - -[*] -end_of_line = lf -insert_final_newline = true -charset = utf-8 -trim_trailing_whitespace = true - -[*.{php,phpt}] -indent_style = tab -indent_size = 4 - -[*.xml] -indent_style = tab -indent_size = 4 - -[*.neon] -indent_style = tab -indent_size = 4 - -[*.{yaml,yml}] -indent_style = space -indent_size = 2 - -[composer.json] -indent_style = tab -indent_size = 4 diff --git a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/README.md b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/README.md index 3a60ec8..52ec368 100644 --- a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/README.md +++ b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/README.md @@ -10,13 +10,14 @@ |:---------------------------------------|:--------------------------------------------------------------------------------------------------------| | `booleansInConditions` | Require booleans in `if`, `elseif`, ternary operator, after `!`, and on both sides of `&&` and `\|\|`. | | `booleansInLoopConditions` | Require booleans in `while` and `do while` loop conditions. | -| `numericOperandsInArithmeticOperators` | Require numeric operand in `+$var`, `-$var`, `$var++`, `$var--`, `++$var` and `--$var`. | -| `numericOperandsInArithmeticOperators` | Require numeric operand in `$var++`, `$var--`, `++$var`and `--$var`. | +| `uselessCast` | Detect useless casts — e.g. casting to `int` when the expression is already `int`. | +| `numericOperandsInArithmeticOperators` | Require numeric operands in `+`, `-`, `*`, `/`, `%`, `**`, `+$var`, `-$var`, `$var++`, `$var--`, `++$var` and `--$var`. | | `strictFunctionCalls` | These functions contain a `$strict` parameter for better type safety, it must be set to `true`:
* `in_array` (3rd parameter)
* `array_search` (3rd parameter)
* `array_keys` (3rd parameter; only if the 2nd parameter `$search_value` is provided)
* `base64_decode` (2nd parameter). | | `overwriteVariablesWithLoop` | * Disallow overwriting variables with `foreach` key and value variables.
* Disallow overwriting variables with `for` loop initial assignment. | | `switchConditionsMatchingType` | Types in `switch` condition and `case` value must match. PHP compares them loosely by default and that can lead to unexpected results. | | `dynamicCallOnStaticMethod` | Check that statically declared methods are called statically. | | `disallowedEmpty` | Disallow `empty()` - it's a very loose comparison (see [manual](https://php.net/empty)), it's recommended to use more strict one. | +| `disallowedLooseComparison` | Disallow loose comparison via `==` and `!=`. | | `disallowedShortTernary` | Disallow short ternary operator (`?:`) - implies weak comparison, it's recommended to use null coalesce operator (`??`) or ternary operator with strict condition. | | `noVariableVariables` | Disallow variable variables (`$$foo`, `$this->$method()` etc.). | | `checkAlwaysTrueInstanceof`, `checkAlwaysTrueCheckTypeFunctionCall`, `checkAlwaysTrueStrictComparison` | Always true `instanceof`, type-checking `is_*` functions and strict comparisons `===`/`!==`. These checks can be turned off by setting `checkAlwaysTrueInstanceof`, `checkAlwaysTrueCheckTypeFunctionCall` and `checkAlwaysTrueStrictComparison` to false. | @@ -26,6 +27,9 @@ | | Check LSP even for static methods. | | `requireParentConstructorCall` | Require calling parent constructor. | | `disallowedBacktick` | Disallow usage of backtick operator (`` $ls = `ls -la` ``). | +| `disallowedImplicitArrayCreation` | Disallow implicit array creation through `$var[] =` when the variable does not exist yet. | +| `strictArrayFilter` | Require `array_filter()` to have a callback parameter to avoid loose comparison semantics. | +| `illegalConstructorMethodCall` | Disallow calling `__construct()` on an existing object or as a static call outside of parent constructor. | | `closureUsesThis` | Closure should use `$this` directly instead of using `$this` variable indirectly. | Additional rules are coming in subsequent releases! diff --git a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/composer.json b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/composer.json index bc72c58..f7c12b5 100644 --- a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/composer.json +++ b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/composer.json @@ -5,9 +5,10 @@ "license": [ "MIT" ], + "keywords": ["static analysis"], "require": { "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.29" + "phpstan/phpstan": "^2.1.39" }, "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.2", diff --git a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/rules.neon b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/rules.neon index 0def6d8..92ca7e0 100644 --- a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/rules.neon +++ b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/rules.neon @@ -12,6 +12,7 @@ parameters: reportMaybesInPropertyPhpDocTypes: true reportWrongPhpDocTypeInVarTag: true checkStrictPrintfPlaceholderTypes: true + reportNonIntStringArrayKey: %featureToggles.bleedingEdge% strictRules: allRules: true disallowedLooseComparison: %strictRules.allRules% @@ -164,6 +165,8 @@ services: - class: PHPStan\Rules\DisallowedConstructs\DisallowedLooseComparisonRule + arguments: + includeOperandTypesInErrorMessage: %featureToggles.bleedingEdge% - class: PHPStan\Rules\BooleansInConditions\BooleanInBooleanAndRule diff --git a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/Cast/UselessCastRule.php b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/Cast/UselessCastRule.php index 6629750..4e0be95 100644 --- a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/Cast/UselessCastRule.php +++ b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/Cast/UselessCastRule.php @@ -4,6 +4,7 @@ namespace PHPStan\Rules\Cast; use PhpParser\Node; use PhpParser\Node\Expr\Cast; +use PhpParser\Node\Expr\Cast\Void_; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -38,6 +39,10 @@ class UselessCastRule implements Rule public function processNode(Node $node, Scope $scope): array { + if ($node instanceof Void_) { + return []; + } + $castType = $scope->getType($node); if ($castType instanceof ErrorType) { return []; diff --git a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedLooseComparisonRule.php b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedLooseComparisonRule.php index 70b8514..4eed0c5 100644 --- a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedLooseComparisonRule.php +++ b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedLooseComparisonRule.php @@ -9,6 +9,8 @@ use PhpParser\Node\Expr\BinaryOp\NotEqual; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; +use PHPStan\Type\VerbosityLevel; +use function sprintf; /** * @implements Rule @@ -16,6 +18,13 @@ use PHPStan\Rules\RuleErrorBuilder; class DisallowedLooseComparisonRule implements Rule { + private bool $includeOperandTypesInErrorMessage; + + public function __construct(bool $includeOperandTypesInErrorMessage) + { + $this->includeOperandTypesInErrorMessage = $includeOperandTypesInErrorMessage; + } + public function getNodeType(): string { return BinaryOp::class; @@ -23,26 +32,34 @@ class DisallowedLooseComparisonRule implements Rule public function processNode(Node $node, Scope $scope): array { + if (!$node instanceof Equal && !$node instanceof NotEqual) { + return []; + } + + $left = $scope->getType($node->left)->describe(VerbosityLevel::typeOnly()); + $right = $scope->getType($node->right)->describe(VerbosityLevel::typeOnly()); + if ($node instanceof Equal) { return [ RuleErrorBuilder::message( - 'Loose comparison via "==" is not allowed.', + $this->includeOperandTypesInErrorMessage + ? sprintf('Loose comparison via "==" between %s and %s is not allowed.', $left, $right) + : 'Loose comparison via "==" is not allowed.', )->tip('Use strict comparison via "===" instead.') ->identifier('equal.notAllowed') ->build(), ]; } - if ($node instanceof NotEqual) { - return [ - RuleErrorBuilder::message( - 'Loose comparison via "!=" is not allowed.', - )->tip('Use strict comparison via "!==" instead.') - ->identifier('notEqual.notAllowed') - ->build(), - ]; - } - return []; + return [ + RuleErrorBuilder::message( + $this->includeOperandTypesInErrorMessage + ? sprintf('Loose comparison via "!=" between %s and %s is not allowed.', $left, $right) + : 'Loose comparison via "!=" is not allowed.', + )->tip('Use strict comparison via "!==" instead.') + ->identifier('notEqual.notAllowed') + ->build(), + ]; } } diff --git a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariablePropertyFetchRule.php b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariablePropertyFetchRule.php index 760bff6..44fc32e 100644 --- a/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariablePropertyFetchRule.php +++ b/tools/.phpstan/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariablePropertyFetchRule.php @@ -44,6 +44,10 @@ class VariablePropertyFetchRule implements Rule return []; } + if ($scope->getType($node->name)->isLiteralString()->yes()) { + return []; + } + $fetchedOnType = $scope->getType($node->var); foreach ($fetchedOnType->getObjectClassNames() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { diff --git a/tools/.phpstan/vendor/phpstan/phpstan/bootstrap.php b/tools/.phpstan/vendor/phpstan/phpstan/bootstrap.php index 889755e..53370b5 100644 --- a/tools/.phpstan/vendor/phpstan/phpstan/bootstrap.php +++ b/tools/.phpstan/vendor/phpstan/phpstan/bootstrap.php @@ -27,8 +27,9 @@ final class PharAutoloader if (self::$composerAutoloader === null) { self::$composerAutoloader = require 'phar://' . __DIR__ . '/phpstan.phar/vendor/autoload.php'; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/jetbrains/phpstorm-stubs/PhpStormStubsMap.php'; - require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/async/src/functions_include.php'; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise/src/functions_include.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/ralouphie/getallheaders/src/getallheaders.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/guzzlehttp/guzzle/src/functions_include.php'; } self::$composerAutoloader->loadClass($class); @@ -106,7 +107,7 @@ final class PharAutoloader if ( PHP_VERSION_ID < 80400 && empty ($GLOBALS['__composer_autoload_files']['9d2b9fc6db0f153a0a149fefb182415e']) - && !class_exists(\Symfony\Polyfill\Php83\Php84::class, false) + && !class_exists(\Symfony\Polyfill\Php84\Php84::class, false) ) { $GLOBALS['__composer_autoload_files']['9d2b9fc6db0f153a0a149fefb182415e'] = true; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php84/Php84.php'; @@ -116,7 +117,7 @@ final class PharAutoloader if ( PHP_VERSION_ID < 80500 && empty ($GLOBALS['__composer_autoload_files']['606a39d89246991a373564698c2d8383']) - && !class_exists(\Symfony\Polyfill\Php83\Php85::class, false) + && !class_exists(\Symfony\Polyfill\Php85\Php85::class, false) ) { $GLOBALS['__composer_autoload_files']['606a39d89246991a373564698c2d8383'] = true; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php85/Php85.php'; diff --git a/tools/.phpstan/vendor/phpstan/phpstan/phpstan.phar b/tools/.phpstan/vendor/phpstan/phpstan/phpstan.phar index bc32b80..d5e9ae7 100755 Binary files a/tools/.phpstan/vendor/phpstan/phpstan/phpstan.phar and b/tools/.phpstan/vendor/phpstan/phpstan/phpstan.phar differ diff --git a/tools/.phpstan/vendor/phpstan/phpstan/phpstan.phar.asc b/tools/.phpstan/vendor/phpstan/phpstan/phpstan.phar.asc index fec010b..1de2068 100644 --- a/tools/.phpstan/vendor/phpstan/phpstan/phpstan.phar.asc +++ b/tools/.phpstan/vendor/phpstan/phpstan/phpstan.phar.asc @@ -1,16 +1,16 @@ -----BEGIN PGP SIGNATURE----- -iQIzBAABCgAdFiEEynwsejDI6OEnSoR2UcZzBf/C5cAFAmkysr4ACgkQUcZzBf/C -5cDE+RAAlbDueQxsbyo+wqm1sURcXT4fPbwdFAv1RXSYfZl7XraoagxYHssIHt9n -TcKuBSOPOmlKgZ4FmVW05TRr0yoLZtckpRDCWuJoPzI9ilW2tiVi6AbEVhV0EqwL -xVToGIzZXmti+X5Mm2OwQMCdpAbqpAy0mwmv/TudFiKdgZBzl5zHWDUSNCwP8s2m -pLGBupQis6sA45+u28vLpyR7vn3mIq3F3hJgb5nrZlWt33jVJ7MDFnpGpeJ6+jBn -/1BmefK0sXwN4EqaJbrRkHdRePISt2+jQXa/V/L3oJ0a3hVFufcGze41ARecSQ/0 -203aB0XcBtIFlshE5OIpXW+ibmgBabd+ggZEkRoS3OXtV5cJizLh49B+16A97QOr -H0NWgLfY/W1u2t0Iu+WDT37Na5LPsuucW9vv9PwS6WY9eCr4Jbbmq1PtF0T17aqx -STyPWNjs5A8NNjVUQ+Ufj/AAdH3hmNj4B5H6psxHD5UsFHoOLVFtwih4GdHrKXIZ -N2lznVo8HDCcvKo6C4F8ejG1t4f5qBHNpYeEC9aVQVvXrBockQQz4lUclibW7MIe -g33fXgO/GIm0dn2u0NCzjYof+TAVOfvtbK4GY0Z9BOlJcQnzu7V1LxqFamG5ef+u -A2ABQa0HVEeKTomB3jzNQQVKw9QzWyfI21xSskfpFs4FXW3A5xc= -=edJd +iQIzBAABCgAdFiEEynwsejDI6OEnSoR2UcZzBf/C5cAFAmnyB+sACgkQUcZzBf/C +5cCc/w//RkO2T6MfMe/Fh1MeWAtdvqVCBDG0x1SwP0Z4UmhW2/EyxPlgP7LtyZOr +IiivLmTQlv9VgNsyKrVJjvo6WH4mQ39s6yyGHsRJxtQqeZRHQWFkCz/SykwCFJ8e +X7vhJsW6UzvboA1/zvjkuRnOr1JVt2DWRVN2P5STK+hk/hizBE/ec404Boc/iD7A +0WGEnhnDGsyKfwB1NHhiWiqUrZ3Wo8x17wyeZsvmH/SL2oimfEjPe3oGm37CKbjr +ztSGnCXfO5EWHxFOIs5O1xbW7Lz13EboQNzpsJyQVpjVwEdLq8xt2LWxnRN7gQTd +5JV5pygmAFhrf44xoFa20HLK2ia14izA+dMTXvTBRHDPJzPaVo2wW3Nt4qg+WCdT +TrN7IAWx88OjZ/4rAKIp3SDzNj3TsN9KxzriCokzZmExipkZL4C+rDLkqhwEhrwE +W+kSGTz0egQeNwBA1FBWKmiBzMYr+rF2uwy7Oud2BHwnq1N0n5tpS5Djsti0fFcp +YQdNt27e7yjV4LO6O7h7uK0r7u0QZ7Pw0En9sU9FC5PQsEmzP22aUoFpqEnzNI2g +7MbHRO5qKmYI7f991RFOj/utbuk5d17ByAOLroJ8Ub8B2qIVEczTPwtYJ06Wf59I +ZRQDRoWjv4q8JosQ9xclS2nt6S//SMmeXrJLMh5t3u65vQN9OcI= +=H59Q -----END PGP SIGNATURE----- diff --git a/tools/composer b/tools/composer index 5a80d74..212c0c3 100755 Binary files a/tools/composer and b/tools/composer differ diff --git a/tools/php-cs-fixer b/tools/php-cs-fixer index 2b71338..badcae0 100755 Binary files a/tools/php-cs-fixer and b/tools/php-cs-fixer differ