From 55d51a4e52fb751ac58bb27a99899537c8d92caa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 7 Jun 2026 13:15:16 +0000 Subject: [PATCH] Update dependency tomasvotruba/type-coverage to ^2.2.2 --- tools/.phpstan/composer.json | 2 +- tools/.phpstan/composer.lock | 120 +-- tools/.phpstan/vendor/composer/installed.json | 124 +-- tools/.phpstan/vendor/composer/installed.php | 19 +- .../vendor/nette/utils/.phpstorm.meta.php | 11 - .../.phpstan/vendor/nette/utils/composer.json | 61 -- tools/.phpstan/vendor/nette/utils/license.md | 60 -- tools/.phpstan/vendor/nette/utils/readme.md | 55 -- .../vendor/nette/utils/src/HtmlStringable.php | 23 - .../utils/src/Iterators/CachingIterator.php | 133 --- .../nette/utils/src/Iterators/Mapper.php | 30 - .../vendor/nette/utils/src/SmartObject.php | 141 --- .../vendor/nette/utils/src/StaticClass.php | 22 - .../vendor/nette/utils/src/Translator.php | 23 - .../nette/utils/src/Utils/ArrayHash.php | 100 -- .../nette/utils/src/Utils/ArrayList.php | 130 --- .../vendor/nette/utils/src/Utils/Arrays.php | 571 ------------ .../vendor/nette/utils/src/Utils/Callback.php | 140 --- .../vendor/nette/utils/src/Utils/DateTime.php | 207 ----- .../vendor/nette/utils/src/Utils/FileInfo.php | 66 -- .../nette/utils/src/Utils/FileSystem.php | 355 -------- .../vendor/nette/utils/src/Utils/Finder.php | 527 ----------- .../vendor/nette/utils/src/Utils/Floats.php | 106 --- .../vendor/nette/utils/src/Utils/Helpers.php | 125 --- .../vendor/nette/utils/src/Utils/Html.php | 840 ----------------- .../vendor/nette/utils/src/Utils/Image.php | 853 ------------------ .../nette/utils/src/Utils/ImageColor.php | 81 -- .../nette/utils/src/Utils/ImageType.php | 25 - .../nette/utils/src/Utils/Iterables.php | 271 ------ .../vendor/nette/utils/src/Utils/Json.php | 84 -- .../nette/utils/src/Utils/ObjectHelpers.php | 229 ----- .../nette/utils/src/Utils/Paginator.php | 210 ----- .../vendor/nette/utils/src/Utils/Process.php | 507 ----------- .../vendor/nette/utils/src/Utils/Random.php | 52 -- .../nette/utils/src/Utils/Reflection.php | 335 ------- .../utils/src/Utils/ReflectionMethod.php | 39 - .../vendor/nette/utils/src/Utils/Strings.php | 730 --------------- .../vendor/nette/utils/src/Utils/Type.php | 314 ------- .../nette/utils/src/Utils/Validators.php | 416 --------- .../nette/utils/src/Utils/exceptions.php | 64 -- .../vendor/nette/utils/src/compatibility.php | 30 - .../vendor/nette/utils/src/exceptions.php | 112 --- .../composer-dependency-analyser.php | 10 + .../tomasvotruba/type-coverage/composer.json | 32 +- .../ConstantTypeDeclarationCollector.php | 11 +- .../ParamTypeDeclarationCollector.php | 13 +- .../PropertyTypeDeclarationCollector.php | 13 +- .../type-coverage/src/Configuration.php | 39 +- .../ScopeConfigurationResolver.php | 3 - .../src/Formatter/TypeCoverageFormatter.php | 3 +- .../src/Rules/ConstantTypeCoverageRule.php | 36 +- .../src/Rules/DeclareCoverageRule.php | 23 +- .../src/Rules/ParamTypeCoverageRule.php | 36 +- .../src/Rules/PropertyTypeCoverageRule.php | 36 +- .../src/Rules/ReturnTypeCoverageRule.php | 36 +- .../ValueObject/TypeCountAndMissingTypes.php | 28 +- 56 files changed, 143 insertions(+), 8519 deletions(-) delete mode 100644 tools/.phpstan/vendor/nette/utils/.phpstorm.meta.php delete mode 100644 tools/.phpstan/vendor/nette/utils/composer.json delete mode 100644 tools/.phpstan/vendor/nette/utils/license.md delete mode 100644 tools/.phpstan/vendor/nette/utils/readme.md delete mode 100644 tools/.phpstan/vendor/nette/utils/src/HtmlStringable.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Iterators/CachingIterator.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Iterators/Mapper.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/SmartObject.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/StaticClass.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Translator.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/ArrayHash.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/ArrayList.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Arrays.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Callback.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/DateTime.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/FileInfo.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/FileSystem.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Finder.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Floats.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Helpers.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Html.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Image.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/ImageColor.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/ImageType.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Iterables.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Json.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/ObjectHelpers.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Paginator.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Process.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Random.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Reflection.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/ReflectionMethod.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Strings.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Type.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/Validators.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/Utils/exceptions.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/compatibility.php delete mode 100644 tools/.phpstan/vendor/nette/utils/src/exceptions.php create mode 100644 tools/.phpstan/vendor/tomasvotruba/type-coverage/composer-dependency-analyser.php diff --git a/tools/.phpstan/composer.json b/tools/.phpstan/composer.json index bc26e4a..403f451 100644 --- a/tools/.phpstan/composer.json +++ b/tools/.phpstan/composer.json @@ -3,7 +3,7 @@ "phpstan/phpstan": "^2.2.2", "phpstan/extension-installer": "^1.4.3", "phpstan/phpstan-strict-rules": "^2.0.11", - "tomasvotruba/type-coverage": "^2.2.1", + "tomasvotruba/type-coverage": "^2.2.2", "ergebnis/phpstan-rules": "^2.13.1" }, "config": { diff --git a/tools/.phpstan/composer.lock b/tools/.phpstan/composer.lock index bc66d01..ccd7250 100644 --- a/tools/.phpstan/composer.lock +++ b/tools/.phpstan/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4eab8c5c85547e2ce7955908c8e18413", + "content-hash": "5dee8c6e3ce17b76a883bfa844ffcc70", "packages": [], "packages-dev": [ { @@ -80,97 +80,6 @@ }, "time": "2026-01-27T17:13:06+00:00" }, - { - "name": "nette/utils", - "version": "v4.1.4", - "source": { - "type": "git", - "url": "https://github.com/nette/utils.git", - "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/7da6c396d7ebe142bc857c20479d5e70a5e1aac7", - "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7", - "shasum": "" - }, - "require": { - "php": "8.2 - 8.5" - }, - "conflict": { - "nette/finder": "<3", - "nette/schema": "<1.2.2" - }, - "require-dev": { - "jetbrains/phpstorm-attributes": "^1.2", - "nette/phpstan-rules": "^1.0", - "nette/tester": "^2.5", - "phpstan/extension-installer": "^1.4@stable", - "phpstan/phpstan": "^2.1@stable", - "tracy/tracy": "^2.9" - }, - "suggest": { - "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", - "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", - "ext-json": "to use Nette\\Utils\\Json", - "ext-mbstring": "to use Strings::lower() etc...", - "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.1-dev" - } - }, - "autoload": { - "psr-4": { - "Nette\\": "src" - }, - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", - "homepage": "https://nette.org", - "keywords": [ - "array", - "core", - "datetime", - "images", - "json", - "nette", - "paginator", - "password", - "slugify", - "string", - "unicode", - "utf-8", - "utility", - "validation" - ], - "support": { - "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.4" - }, - "time": "2026-05-11T20:49:54+00:00" - }, { "name": "phpstan/extension-installer", "version": "1.4.3", @@ -336,22 +245,31 @@ }, { "name": "tomasvotruba/type-coverage", - "version": "2.2.1", + "version": "2.2.2", "source": { "type": "git", "url": "https://github.com/TomasVotruba/type-coverage.git", - "reference": "4087caa4639bdd4c646f2984bc333efeddf69e4b" + "reference": "25f298265c823e8fb0505169135855e1e6a91021" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TomasVotruba/type-coverage/zipball/4087caa4639bdd4c646f2984bc333efeddf69e4b", - "reference": "4087caa4639bdd4c646f2984bc333efeddf69e4b", + "url": "https://api.github.com/repos/TomasVotruba/type-coverage/zipball/25f298265c823e8fb0505169135855e1e6a91021", + "reference": "25f298265c823e8fb0505169135855e1e6a91021", "shasum": "" }, "require": { - "nette/utils": "^3.2 || ^4.0", - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.33" + "php": "^8.4", + "phpstan/phpstan": "^2.2" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4", + "phpunit/phpunit": "^12.5", + "rector/jack": "^1.0", + "rector/rector": "^2.4", + "shipmonk/composer-dependency-analyser": "^1.8", + "symplify/easy-coding-standard": "^13.1", + "tomasvotruba/unused-public": "^2.2", + "tracy/tracy": "^2.12" }, "type": "phpstan-extension", "extra": { @@ -377,7 +295,7 @@ ], "support": { "issues": "https://github.com/TomasVotruba/type-coverage/issues", - "source": "https://github.com/TomasVotruba/type-coverage/tree/2.2.1" + "source": "https://github.com/TomasVotruba/type-coverage/tree/2.2.2" }, "funding": [ { @@ -389,7 +307,7 @@ "type": "github" } ], - "time": "2026-05-26T08:14:01+00:00" + "time": "2026-06-07T12:35:00+00:00" } ], "aliases": [], diff --git a/tools/.phpstan/vendor/composer/installed.json b/tools/.phpstan/vendor/composer/installed.json index b1ee3e4..46d12ed 100644 --- a/tools/.phpstan/vendor/composer/installed.json +++ b/tools/.phpstan/vendor/composer/installed.json @@ -76,100 +76,6 @@ }, "install-path": "../ergebnis/phpstan-rules" }, - { - "name": "nette/utils", - "version": "v4.1.4", - "version_normalized": "4.1.4.0", - "source": { - "type": "git", - "url": "https://github.com/nette/utils.git", - "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/7da6c396d7ebe142bc857c20479d5e70a5e1aac7", - "reference": "7da6c396d7ebe142bc857c20479d5e70a5e1aac7", - "shasum": "" - }, - "require": { - "php": "8.2 - 8.5" - }, - "conflict": { - "nette/finder": "<3", - "nette/schema": "<1.2.2" - }, - "require-dev": { - "jetbrains/phpstorm-attributes": "^1.2", - "nette/phpstan-rules": "^1.0", - "nette/tester": "^2.5", - "phpstan/extension-installer": "^1.4@stable", - "phpstan/phpstan": "^2.1@stable", - "tracy/tracy": "^2.9" - }, - "suggest": { - "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", - "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", - "ext-json": "to use Nette\\Utils\\Json", - "ext-mbstring": "to use Strings::lower() etc...", - "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" - }, - "time": "2026-05-11T20:49:54+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.1-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Nette\\": "src" - }, - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", - "homepage": "https://nette.org", - "keywords": [ - "array", - "core", - "datetime", - "images", - "json", - "nette", - "paginator", - "password", - "slugify", - "string", - "unicode", - "utf-8", - "utility", - "validation" - ], - "support": { - "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.4" - }, - "install-path": "../nette/utils" - }, { "name": "phpstan/extension-installer", "version": "1.4.3", @@ -344,25 +250,34 @@ }, { "name": "tomasvotruba/type-coverage", - "version": "2.2.1", - "version_normalized": "2.2.1.0", + "version": "2.2.2", + "version_normalized": "2.2.2.0", "source": { "type": "git", "url": "https://github.com/TomasVotruba/type-coverage.git", - "reference": "4087caa4639bdd4c646f2984bc333efeddf69e4b" + "reference": "25f298265c823e8fb0505169135855e1e6a91021" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TomasVotruba/type-coverage/zipball/4087caa4639bdd4c646f2984bc333efeddf69e4b", - "reference": "4087caa4639bdd4c646f2984bc333efeddf69e4b", + "url": "https://api.github.com/repos/TomasVotruba/type-coverage/zipball/25f298265c823e8fb0505169135855e1e6a91021", + "reference": "25f298265c823e8fb0505169135855e1e6a91021", "shasum": "" }, "require": { - "nette/utils": "^3.2 || ^4.0", - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.33" + "php": "^8.4", + "phpstan/phpstan": "^2.2" }, - "time": "2026-05-26T08:14:01+00:00", + "require-dev": { + "phpstan/extension-installer": "^1.4", + "phpunit/phpunit": "^12.5", + "rector/jack": "^1.0", + "rector/rector": "^2.4", + "shipmonk/composer-dependency-analyser": "^1.8", + "symplify/easy-coding-standard": "^13.1", + "tomasvotruba/unused-public": "^2.2", + "tracy/tracy": "^2.12" + }, + "time": "2026-06-07T12:35:00+00:00", "type": "phpstan-extension", "extra": { "phpstan": { @@ -388,7 +303,7 @@ ], "support": { "issues": "https://github.com/TomasVotruba/type-coverage/issues", - "source": "https://github.com/TomasVotruba/type-coverage/tree/2.2.1" + "source": "https://github.com/TomasVotruba/type-coverage/tree/2.2.2" }, "funding": [ { @@ -406,7 +321,6 @@ "dev": true, "dev-package-names": [ "ergebnis/phpstan-rules", - "nette/utils", "phpstan/extension-installer", "phpstan/phpstan", "phpstan/phpstan-strict-rules", diff --git a/tools/.phpstan/vendor/composer/installed.php b/tools/.phpstan/vendor/composer/installed.php index 425601d..6d27641 100644 --- a/tools/.phpstan/vendor/composer/installed.php +++ b/tools/.phpstan/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => '__root__', 'pretty_version' => 'dev-main', 'version' => 'dev-main', - 'reference' => '94a4f8ce9b795e1d194884a36bbda93115a7ffa1', + 'reference' => '183b82cc23c52c7b70a24393bcfb6fdb0ca27146', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -13,7 +13,7 @@ '__root__' => array( 'pretty_version' => 'dev-main', 'version' => 'dev-main', - 'reference' => '94a4f8ce9b795e1d194884a36bbda93115a7ffa1', + 'reference' => '183b82cc23c52c7b70a24393bcfb6fdb0ca27146', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -28,15 +28,6 @@ 'aliases' => array(), 'dev_requirement' => true, ), - 'nette/utils' => array( - 'pretty_version' => 'v4.1.4', - 'version' => '4.1.4.0', - 'reference' => '7da6c396d7ebe142bc857c20479d5e70a5e1aac7', - 'type' => 'library', - 'install_path' => __DIR__ . '/../nette/utils', - 'aliases' => array(), - 'dev_requirement' => true, - ), 'phpstan/extension-installer' => array( 'pretty_version' => '1.4.3', 'version' => '1.4.3.0', @@ -65,9 +56,9 @@ 'dev_requirement' => true, ), 'tomasvotruba/type-coverage' => array( - 'pretty_version' => '2.2.1', - 'version' => '2.2.1.0', - 'reference' => '4087caa4639bdd4c646f2984bc333efeddf69e4b', + 'pretty_version' => '2.2.2', + 'version' => '2.2.2.0', + 'reference' => '25f298265c823e8fb0505169135855e1e6a91021', 'type' => 'phpstan-extension', 'install_path' => __DIR__ . '/../tomasvotruba/type-coverage', 'aliases' => array(), diff --git a/tools/.phpstan/vendor/nette/utils/.phpstorm.meta.php b/tools/.phpstan/vendor/nette/utils/.phpstorm.meta.php deleted file mode 100644 index 64dc487..0000000 --- a/tools/.phpstan/vendor/nette/utils/.phpstorm.meta.php +++ /dev/null @@ -1,11 +0,0 @@ - -✅ [Callback](https://doc.nette.org/utils/callback) - PHP callbacks
-✅ [Filesystem](https://doc.nette.org/utils/filesystem) - copying, renaming, …
-✅ [Finder](https://doc.nette.org/utils/finder) - finds files and directories
-✅ [Floats](https://doc.nette.org/utils/floats) - floating point numbers
-✅ [Helper Functions](https://doc.nette.org/utils/helpers)
-✅ [HTML elements](https://doc.nette.org/utils/html-elements) - generate HTML
-✅ [Images](https://doc.nette.org/utils/images) - crop, resize, rotate images
-✅ [Iterables](https://doc.nette.org/utils/iterables)
-✅ [JSON](https://doc.nette.org/utils/json) - encoding and decoding
-✅ [Generating Random Strings](https://doc.nette.org/utils/random)
-✅ [Paginator](https://doc.nette.org/utils/paginator) - pagination math
-✅ [PHP Reflection](https://doc.nette.org/utils/reflection)
-✅ [Strings](https://doc.nette.org/utils/strings) - useful text functions
-✅ [SmartObject](https://doc.nette.org/utils/smartobject) - PHP object enhancements
-✅ [Type](https://doc.nette.org/utils/type) - PHP data type
-✅ [Validation](https://doc.nette.org/utils/validators) - validate inputs
- -  - -Installation ------------- - -The recommended way to install is via Composer: - -``` -composer require nette/utils -``` - -Nette Utils 4.1 is compatible with PHP 8.2 to 8.5. - -  - -[Support Me](https://github.com/sponsors/dg) --------------------------------------------- - -Do you like Nette Utils? Are you looking forward to the new features? - -[![Buy me a coffee](https://files.nette.org/icons/donation-3.svg)](https://github.com/sponsors/dg) - -Thank you! diff --git a/tools/.phpstan/vendor/nette/utils/src/HtmlStringable.php b/tools/.phpstan/vendor/nette/utils/src/HtmlStringable.php deleted file mode 100644 index c9600d2..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/HtmlStringable.php +++ /dev/null @@ -1,23 +0,0 @@ -> - * @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 TKey $nextKey - * @property-read TValue $nextValue - */ -class CachingIterator extends \CachingIterator implements \Countable -{ - use Nette\SmartObject; - - private int $counter = 0; - - - /** @param iterable|\stdClass $iterable */ - public function __construct(iterable|\stdClass $iterable) - { - $iterable = $iterable instanceof \stdClass - ? new \ArrayIterator((array) $iterable) - : Nette\Utils\Iterables::toIterator($iterable); - parent::__construct($iterable, 0); - } - - - /** - * Is the current element the first one? - */ - public function isFirst(?int $gridWidth = null): bool - { - return $this->counter === 1 || ($gridWidth && $this->counter !== 0 && (($this->counter - 1) % $gridWidth) === 0); - } - - - /** - * Is the current element the last one? - */ - public function isLast(?int $gridWidth = null): bool - { - return !$this->hasNext() || ($gridWidth && ($this->counter % $gridWidth) === 0); - } - - - public function isEmpty(): bool - { - return $this->counter === 0; - } - - - public function isOdd(): bool - { - return $this->counter % 2 === 1; - } - - - public function isEven(): bool - { - return $this->counter % 2 === 0; - } - - - public function getCounter(): int - { - return $this->counter; - } - - - public function count(): int - { - $inner = $this->getInnerIterator(); - if ($inner instanceof \Countable) { - return $inner->count(); - - } else { - throw new Nette\NotSupportedException('Iterator is not countable.'); - } - } - - - /** - * Forwards to the next element. - */ - public function next(): void - { - parent::next(); - if (parent::valid()) { - $this->counter++; - } - } - - - /** - * Rewinds the Iterator. - */ - public function rewind(): void - { - parent::rewind(); - $this->counter = parent::valid() ? 1 : 0; - } - - - /** @return TKey */ - public function getNextKey(): mixed - { - return $this->getInnerIterator()->key(); - } - - - /** @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 deleted file mode 100644 index a9cfba0..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Iterators/Mapper.php +++ /dev/null @@ -1,30 +0,0 @@ -callback = $callback(...); - } - - - public function current(): mixed - { - return ($this->callback)(parent::current(), parent::key()); - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/SmartObject.php b/tools/.phpstan/vendor/nette/utils/src/SmartObject.php deleted file mode 100644 index d9742c8..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/SmartObject.php +++ /dev/null @@ -1,141 +0,0 @@ -$name ?? null; - if (is_iterable($handlers)) { - foreach ($handlers as $handler) { - $handler(...$args); - } - } elseif ($handlers !== null) { - throw new UnexpectedValueException("Property $class::$$name must be iterable or null, " . get_debug_type($handlers) . ' given.'); - } - - return null; - } - - ObjectHelpers::strictCall($class, $name); - } - - - /** - * @param mixed[] $args - * @return never - * @throws MemberAccessException - */ - public static function __callStatic(string $name, array $args) - { - ObjectHelpers::strictStaticCall(static::class, $name); - } - - - /** - * @return mixed - * @throws MemberAccessException if the property is not defined. - */ - public function &__get(string $name) - { - $class = static::class; - - if ($prop = ObjectHelpers::getMagicProperties($class)[$name] ?? null) { // property getter - if (!($prop & 0b0001)) { - throw new MemberAccessException("Cannot read a write-only property $class::\$$name."); - } - - $m = ($prop & 0b0010 ? 'get' : 'is') . ucfirst($name); - if ($prop & 0b10000) { - $trace = debug_backtrace(0, 1)[0]; // suppose this method is called from __call() - $loc = isset($trace['file'], $trace['line']) - ? " in $trace[file] on line $trace[line]" - : ''; - trigger_error("Property $class::\$$name is deprecated, use $class::$m() method$loc.", E_USER_DEPRECATED); - } - - if ($prop & 0b0100) { // return by reference - return $this->$m(); - } else { - $val = $this->$m(); - return $val; - } - } else { - ObjectHelpers::strictGet($class, $name); - } - } - - - /** - * @throws MemberAccessException if the property is not defined or is read-only - */ - public function __set(string $name, mixed $value): void - { - $class = static::class; - - if (ObjectHelpers::hasProperty($class, $name)) { // unsetted property - $this->$name = $value; - - } elseif ($prop = ObjectHelpers::getMagicProperties($class)[$name] ?? null) { // property setter - if (!($prop & 0b1000)) { - throw new MemberAccessException("Cannot write to a read-only property $class::\$$name."); - } - - $m = 'set' . ucfirst($name); - if ($prop & 0b10000) { - $trace = debug_backtrace(0, 1)[0]; // suppose this method is called from __call() - $loc = isset($trace['file'], $trace['line']) - ? " in $trace[file] on line $trace[line]" - : ''; - trigger_error("Property $class::\$$name is deprecated, use $class::$m() method$loc.", E_USER_DEPRECATED); - } - - $this->$m($value); - - } else { - ObjectHelpers::strictSet($class, $name); - } - } - - - /** - * @throws MemberAccessException - */ - public function __unset(string $name): void - { - $class = static::class; - if (!ObjectHelpers::hasProperty($class, $name)) { - throw new MemberAccessException("Cannot unset the property $class::\$$name."); - } - } - - - public function __isset(string $name): bool - { - return isset(ObjectHelpers::getMagicProperties(static::class)[$name]); - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/StaticClass.php b/tools/.phpstan/vendor/nette/utils/src/StaticClass.php deleted file mode 100644 index e88a74b..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/StaticClass.php +++ /dev/null @@ -1,22 +0,0 @@ - - * @implements \ArrayAccess - */ -class ArrayHash extends \stdClass implements \ArrayAccess, \Countable, \IteratorAggregate -{ - /** - * Transforms array to ArrayHash. - * @param array $array - */ - public static function from(array $array, bool $recursive = true): static - { - $obj = new static; - foreach ($array as $key => $value) { - $obj->$key = $recursive && is_array($value) - ? static::from($value) - : $value; - } - - return $obj; - } - - - /** - * @return \Iterator - */ - public function &getIterator(): \Iterator - { - foreach ((array) $this as $key => $foo) { - yield $key => $this->$key; - } - } - - - public function count(): int - { - return count((array) $this); - } - - - /** - * Replaces or appends an item. - * @param array-key $key - * @param T $value - */ - public function offsetSet($key, $value): void - { - if (!is_scalar($key)) { // prevents null - throw new Nette\InvalidArgumentException(sprintf('Key must be either a string or an integer, %s given.', get_debug_type($key))); - } - - $this->$key = $value; - } - - - /** - * Returns an item. - * @param array-key $key - * @return T - */ - public function offsetGet($key): mixed - { - return $this->$key; - } - - - /** - * Determines whether an item exists. - * @param array-key $key - */ - public function offsetExists($key): bool - { - return isset($this->$key); - } - - - /** - * Removes the element from this list. - * @param array-key $key - */ - public function offsetUnset($key): void - { - unset($this->$key); - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/ArrayList.php b/tools/.phpstan/vendor/nette/utils/src/Utils/ArrayList.php deleted file mode 100644 index 628cc45..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/ArrayList.php +++ /dev/null @@ -1,130 +0,0 @@ - - * @implements \ArrayAccess - */ -class ArrayList implements \ArrayAccess, \Countable, \IteratorAggregate -{ - /** @var list */ - private array $list = []; - - - /** - * Transforms array to ArrayList. - * @param list $array - */ - public static function from(array $array): static - { - if (!Arrays::isList($array)) { - throw new Nette\InvalidArgumentException('Array is not valid list.'); - } - - $obj = new static; - $obj->list = $array; - return $obj; - } - - - /** - * @return \Iterator - */ - public function &getIterator(): \Iterator - { - foreach ($this->list as &$item) { - yield $item; - } - } - - - public function count(): int - { - return count($this->list); - } - - - /** - * Replaces or appends an item. - * @param ?int $index - * @param T $value - * @throws Nette\OutOfRangeException - */ - public function offsetSet($index, $value): void - { - if ($index === null) { - $this->list[] = $value; - - } elseif (!is_int($index) || $index < 0 || $index >= count($this->list)) { - throw new Nette\OutOfRangeException('Offset invalid or out of range'); - - } else { - $this->list[$index] = $value; - } - } - - - /** - * Returns an item. - * @param int $index - * @return T - * @throws Nette\OutOfRangeException - */ - public function offsetGet($index): mixed - { - if (!is_int($index) || $index < 0 || $index >= count($this->list)) { - throw new Nette\OutOfRangeException('Offset invalid or out of range'); - } - - return $this->list[$index]; - } - - - /** - * Determines whether an item exists. - * @param int $index - */ - public function offsetExists($index): bool - { - return is_int($index) && $index >= 0 && $index < count($this->list); - } - - - /** - * Removes the element at the specified position in this list. - * @param int $index - * @throws Nette\OutOfRangeException - */ - public function offsetUnset($index): void - { - if (!is_int($index) || $index < 0 || $index >= count($this->list)) { - throw new Nette\OutOfRangeException('Offset invalid or out of range'); - } - - array_splice($this->list, $index, 1); - } - - - /** - * Prepends an item. - * @param T $value - */ - public function prepend(mixed $value): void - { - $first = array_slice($this->list, 0, 1); - $this->offsetSet(0, $value); - array_splice($this->list, 1, 0, $first); - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Arrays.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Arrays.php deleted file mode 100644 index 3769433..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Arrays.php +++ /dev/null @@ -1,571 +0,0 @@ - $array - * @param array-key|array-key[] $key - * @param ?T $default - * @return ?T - * @throws Nette\InvalidArgumentException if item does not exist and default value is not provided - */ - public static function get(array $array, string|int|array $key, mixed $default = null): mixed - { - foreach (is_array($key) ? $key : [$key] as $k) { - if (is_array($array) && array_key_exists($k, $array)) { - $array = $array[$k]; - } else { - if (func_num_args() < 3) { - throw new Nette\InvalidArgumentException("Missing item '$k'."); - } - - return $default; - } - } - - return $array; - } - - - /** - * Returns reference to array item. If the index does not exist, new one is created with value null. - * @template T - * @param array $array - * @param array-key|array-key[] $key - * @return ?T - * @throws Nette\InvalidArgumentException if traversed item is not an array - */ - public static function &getRef(array &$array, string|int|array $key): mixed - { - foreach (is_array($key) ? $key : [$key] as $k) { - if (is_array($array) || $array === null) { - $array = &$array[$k]; - } else { - throw new Nette\InvalidArgumentException('Traversed item is not an array.'); - } - } - - return $array; - } - - - /** - * Recursively merges two arrays. Useful for merging tree structures. Behaves like the + operator: - * key/value pairs from the second array are added to the first, with the first array's values taking - * precedence on key collisions. Nested arrays are merged recursively instead of replaced. - * @template T1 - * @template T2 - * @param array $array1 - * @param array $array2 - * @return array> - */ - public static function mergeTree(array $array1, array $array2): array - { - $res = $array1 + $array2; - foreach (array_intersect_key($array1, $array2) as $k => $v) { - if (is_array($v) && is_array($array2[$k])) { - $res[$k] = self::mergeTree($v, $array2[$k]); - } - } - - return $res; - } - - - /** - * 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 - { - return Helpers::falseToNull(array_search(self::toKey($key), array_keys($array), strict: true)); - } - - - /** - * @param array $array - * @deprecated use getKeyOffset() - */ - public static function searchKey(array $array, string|int $key): ?int - { - return self::getKeyOffset($array, $key); - } - - - /** - * 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, strict: true); - } - - - /** - * 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 - * @param ?callable(): E $else - * @return ($else is null ? ?V : V|E) - */ - public static function first(array $array, ?callable $predicate = null, ?callable $else = null): mixed - { - $key = self::firstKey($array, $predicate); - return $key === null - ? ($else ? $else() : null) - : $array[$key]; - } - - - /** - * 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 - * @param ?callable(): E $else - * @return ($else is null ? ?V : V|E) - */ - public static function last(array $array, ?callable $predicate = null, ?callable $else = null): mixed - { - $key = self::lastKey($array, $predicate); - return $key === null - ? ($else ? $else() : null) - : $array[$key]; - } - - - /** - * Returns the key of first item (matching the specified predicate if given) or null if there is no such item. - * @template K of int|string - * @template V - * @param array $array - * @param ?callable(V, K, array): bool $predicate - * @return ?K - */ - public static function firstKey(array $array, ?callable $predicate = null): int|string|null - { - if (!$predicate) { - return array_key_first($array); - } - foreach ($array as $k => $v) { - if ($predicate($v, $k, $array)) { - return $k; - } - } - return null; - } - - - /** - * Returns the key of last item (matching the specified predicate if given) or null if there is no such item. - * @template K of int|string - * @template V - * @param array $array - * @param ?callable(V, K, array): bool $predicate - * @return ?K - */ - public static function lastKey(array $array, ?callable $predicate = null): int|string|null - { - return $predicate - ? self::firstKey(array_reverse($array, preserve_keys: true), $predicate) - : array_key_last($array); - } - - - /** - * 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 - { - $offset = $key === null ? 0 : (int) self::getKeyOffset($array, $key); - $array = array_slice($array, 0, $offset, preserve_keys: true) - + $inserted - + array_slice($array, $offset, count($array), preserve_keys: true); - } - - - /** - * 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 - { - if ($key === null || ($offset = self::getKeyOffset($array, $key)) === null) { - $offset = count($array) - 1; - } - - $array = array_slice($array, 0, $offset + 1, preserve_keys: true) - + $inserted - + array_slice($array, $offset + 1, count($array), preserve_keys: true); - } - - - /** - * Renames key in array. - * @param array $array - */ - public static function renameKey(array &$array, string|int $oldKey, string|int $newKey): bool - { - $offset = self::getKeyOffset($array, $oldKey); - if ($offset === null) { - return false; - } - - $val = &$array[$oldKey]; - $keys = array_keys($array); - $keys[$offset] = $newKey; - $array = array_combine($keys, $array); - $array[$newKey] = &$val; - return true; - } - - - /** - * Returns only those array items, which matches a regular expression $pattern. - * @param string[] $array - * @return string[] - */ - public static function grep( - array $array, - #[Language('RegExp')] - string $pattern, - bool|int $invert = false, - ): array - { - $flags = $invert ? PREG_GREP_INVERT : 0; - return Strings::pcre('preg_grep', [$pattern, $array, $flags]); - } - - - /** - * Transforms multidimensional array to flat array. - * @param array $array - * @return array - */ - public static function flatten(array $array, bool $preserveKeys = false): array - { - $res = []; - $cb = $preserveKeys - ? function ($v, $k) use (&$res): void { $res[$k] = $v; } - : function ($v) use (&$res): void { $res[] = $v; }; - array_walk_recursive($array, $cb); - return $res; - } - - - /** - * Checks if the array is indexed in ascending order of numeric keys from zero, a.k.a list. - * @return ($value is list ? true : false) - */ - public static function isList(mixed $value): bool - { - return is_array($value) && array_is_list($value); - } - - - /** - * 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, 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 '" . (is_array($path) ? implode('', $path) : $path) . "'."); - } - - $res = $parts[0] === '->' ? new \stdClass : []; - - foreach ($array as $rowOrig) { - $row = (array) $rowOrig; - $x = &$res; - - for ($i = 0; $i < count($parts); $i++) { - $part = $parts[$i]; - if ($part === '[]') { - $x = &$x[]; - - } elseif ($part === '=') { - if (isset($parts[++$i])) { - $x = $row[$parts[$i]]; - $row = null; - } - break; // '=' is always the final operation - - } elseif ($part === '->') { - if (isset($parts[++$i])) { - if ($x === null) { - $x = new \stdClass; - } - - $x = &$x->{$row[$parts[$i]]}; - } else { - $row = is_object($rowOrig) ? $rowOrig : (object) $row; - } - } elseif ($part !== '|') { - $x = &$x[(string) $row[$part]]; - } - } - - if ($x === null) { - $x = $row; - } - } - - return $res; - } - - - /** - * 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 - { - $res = []; - foreach ($array as $k => $v) { - $res[is_int($k) ? $v : $k] = is_int($k) ? $filling : $v; - } - - return $res; - } - - - /** - * Returns and removes the value of an item from an array. If it does not exist, it throws an exception, - * or returns $default, if provided. - * @template T - * @param array $array - * @param ?T $default - * @return ?T - * @throws Nette\InvalidArgumentException if item does not exist and default value is not provided - */ - public static function pick(array &$array, string|int $key, mixed $default = null): mixed - { - if (array_key_exists($key, $array)) { - $value = $array[$key]; - unset($array[$key]); - return $value; - - } elseif (func_num_args() < 3) { - throw new Nette\InvalidArgumentException("Missing item '$key'."); - - } else { - return $default; - } - } - - - /** - * Tests whether at least one element in the array passes the test implemented by the provided function. - * @template K of int|string - * @template V - * @param array $array - * @param callable(V, K, array): bool $predicate - */ - public static function some(iterable $array, callable $predicate): bool - { - foreach ($array as $k => $v) { - if ($predicate($v, $k, $array)) { - return true; - } - } - - return false; - } - - - /** - * Tests whether all elements in the array pass the test implemented by the provided function. - * @template K of int|string - * @template V - * @param array $array - * @param callable(V, K, array): bool $predicate - */ - public static function every(iterable $array, callable $predicate): bool - { - foreach ($array as $k => $v) { - if (!$predicate($v, $k, $array)) { - return false; - } - } - - return true; - } - - - /** - * Returns a new array containing all key-value pairs matching the given $predicate. - * @template K of int|string - * @template V - * @param array $array - * @param callable(V, K, array): bool $predicate - * @return array - */ - public static function filter(array $array, callable $predicate): array - { - $res = []; - foreach ($array as $k => $v) { - if ($predicate($v, $k, $array)) { - $res[$k] = $v; - } - } - return $res; - } - - - /** - * Returns an array containing the original keys and results of applying the given transform function to each element. - * @template K of int|string - * @template V - * @template R - * @param array $array - * @param callable(V, K, array): R $transformer - * @return array - */ - public static function map(iterable $array, callable $transformer): array - { - $res = []; - foreach ($array as $k => $v) { - $res[$k] = $transformer($v, $k, $array); - } - - return $res; - } - - - /** - * Returns an array containing new keys and values generated by applying the given transform function to each element. - * If the function returns null, the element is skipped. - * @template K of int|string - * @template V - * @template ResK of int|string - * @template ResV - * @param array $array - * @param callable(V, K, array): ?array{ResK, ResV} $transformer - * @return array - */ - public static function mapWithKeys(array $array, callable $transformer): array - { - $res = []; - foreach ($array as $k => $v) { - $pair = $transformer($v, $k, $array); - if ($pair) { - $res[$pair[0]] = $pair[1]; - } - } - - return $res; - } - - - /** - * Invokes all callbacks and returns array of results. - * @param iterable $callbacks - * @return array - */ - public static function invoke(iterable $callbacks, mixed ...$args): array - { - $res = []; - foreach ($callbacks as $k => $cb) { - $res[$k] = $cb(...$args); - } - - return $res; - } - - - /** - * Invokes method on every object in an array and returns array of results. - * @param iterable $objects - * @return array - */ - public static function invokeMethod(iterable $objects, string $method, mixed ...$args): array - { - $res = []; - foreach ($objects as $k => $obj) { - $res[$k] = $obj->$method(...$args); - } - - return $res; - } - - - /** - * 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 - */ - public static function toObject(iterable $array, object $object): object - { - foreach ($array as $k => $v) { - $object->$k = $v; - } - - return $object; - } - - - /** - * Converts value to array key. - */ - public static function toKey(mixed $value): int|string - { - return key(@[$value => null]); - } - - - /** - * Returns a copy of $array where every item is cast to string and wrapped with $prefix and $suffix. - * @param string[] $array - * @return string[] - */ - public static function wrap(array $array, string $prefix = '', string $suffix = ''): array - { - $res = []; - foreach ($array as $k => $v) { - $res[$k] = $prefix . $v . $suffix; - } - - return $res; - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Callback.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Callback.php deleted file mode 100644 index 1c34ac9..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Callback.php +++ /dev/null @@ -1,140 +0,0 @@ - $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 (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 = (string) preg_replace("#^$function\\(.*?\\): #", '', $msg); - if ($onError($msg, $severity) !== false) { - return true; - } - } - - return $prev ? $prev(...func_get_args()) !== false : false; - }); - - try { - return $function(...$args); - } finally { - restore_error_handler(); - } - } - - - /** - * 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): mixed - { - if (!is_callable($callable, $syntax)) { - throw new Nette\InvalidArgumentException( - $syntax - ? 'Given value is not a callable type.' - : sprintf("Callback '%s' is not callable.", self::toString($callable)), - ); - } - - return $callable; - } - - - /** - * Converts PHP callback to textual form. Class or method may not exists. - */ - public static function toString(mixed $callable): string - { - if ($callable instanceof \Closure) { - $inner = self::unwrap($callable); - return '{closure' . ($inner instanceof \Closure ? '}' : ' ' . self::toString($inner) . '}'); - } else { - is_callable(is_object($callable) ? [$callable, '__invoke'] : $callable, true, $textual); - return $textual; - } - } - - - /** - * Returns reflection for method or function used in PHP callback. - * @param callable $callable type check is escalated to ReflectionException - * @throws \ReflectionException if callback is not valid - */ - public static function toReflection(mixed $callable): \ReflectionMethod|\ReflectionFunction - { - if ($callable instanceof \Closure) { - $callable = self::unwrap($callable); - } - - if (is_string($callable) && str_contains($callable, '::')) { - return new ReflectionMethod(...explode('::', $callable, 2)); - } elseif (is_array($callable)) { - return new ReflectionMethod($callable[0], $callable[1]); - } elseif (is_object($callable) && !$callable instanceof \Closure) { - return new ReflectionMethod($callable, '__invoke'); - } else { - assert($callable instanceof \Closure || is_string($callable)); - return new \ReflectionFunction($callable); - } - } - - - /** - * Checks whether PHP callback is function or static method. - */ - public static function isStatic(callable $callable): bool - { - return is_string(is_array($callable) ? $callable[0] : $callable); - } - - - /** - * Unwraps closure created by Closure::fromCallable(). - * @return callable|array{object|class-string, string}|string - */ - public static function unwrap(\Closure $closure): callable|array|string - { - $r = new \ReflectionFunction($closure); - $class = $r->getClosureScopeClass()?->name; - if (str_ends_with($r->name, '}')) { - return $closure; - - } elseif (($obj = $r->getClosureThis()) && $obj::class === $class) { - return [$obj, $r->name]; - - } elseif ($class) { - return [$class, $r->name]; - - } else { - return $r->name; - } - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/DateTime.php b/tools/.phpstan/vendor/nette/utils/src/Utils/DateTime.php deleted file mode 100644 index af4e94d..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/DateTime.php +++ /dev/null @@ -1,207 +0,0 @@ -setTimestamp((int) $time); - - } else { // textual or null - return new static((string) $time); - } - } - - - /** - * Creates DateTime object. - * @throws \Exception if the date and time are not valid. - */ - public static function fromParts( - int $year, - int $month, - int $day, - int $hour = 0, - int $minute = 0, - float $second = 0.0, - ): static - { - $sec = (int) floor($second); - return (new static('')) - ->setDate($year, $month, $day) - ->setTime($hour, $minute, $sec, (int) round(($second - $sec) * 1e6)); - } - - - /** - * Returns a new DateTime object formatted according to the specified format. - */ - public static function createFromFormat( - string $format, - string $datetime, - string|\DateTimeZone|null $timezone = null, - ): static|false - { - if (is_string($timezone)) { - $timezone = new \DateTimeZone($timezone); - } - - $date = parent::createFromFormat($format, $datetime, $timezone); - return $date ? static::from($date) : false; - } - - - public function __construct(string $datetime = 'now', ?\DateTimeZone $timezone = null) - { - $this->apply($datetime, $timezone, true); - } - - - public function modify(string $modifier): static - { - $this->apply($modifier); - return $this; - } - - - public function setDate(int $year, int $month, int $day): static - { - if (!checkdate($month, $day, $year)) { - throw new \Exception(sprintf('The date %04d-%02d-%02d is not valid.', $year, $month, $day)); - } - return parent::setDate($year, $month, $day); - } - - - public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0): static - { - if ( - $hour < 0 || $hour > 23 - || $minute < 0 || $minute > 59 - || $second < 0 || $second >= 60 - || $microsecond < 0 || $microsecond >= 1_000_000 - ) { - throw new \Exception(sprintf('The time %02d:%02d:%08.5F is not valid.', $hour, $minute, $second + $microsecond / 1_000_000)); - } - return parent::setTime($hour, $minute, $second, $microsecond); - } - - - /** - * Converts a relative time string (e.g. '10 minut') to seconds. - */ - public static function relativeToSeconds(string $relativeTime): int - { - return (new self('@0 ' . $relativeTime)) - ->getTimestamp(); - } - - - private function apply(string $datetime, ?\DateTimeZone $timezone = null, bool $ctr = false): void - { - $relPart = ''; - $absPart = preg_replace_callback( - '/[+-]?\s*\d+\s+((microsecond|millisecond|[mµu]sec)s?|[mµ]s|sec(ond)?s?|min(ute)?s?|hours?)(\s+ago)?\b/iu', - function ($m) use (&$relPart) { - $relPart .= $m[0] . ' '; - return ''; - }, - $datetime, - ); - - if ($ctr) { - parent::__construct($absPart, $timezone); - $this->handleErrors($datetime); - } elseif (trim($absPart)) { - parent::modify($absPart) && $this->handleErrors($datetime); - } - - if ($relPart) { - $timezone ??= $this->getTimezone(); - $this->setTimezone(new \DateTimeZone('UTC')); - parent::modify($relPart) && $this->handleErrors($datetime); - $this->setTimezone($timezone); - } - } - - - /** - * Returns JSON representation in ISO 8601 (used by JavaScript). - */ - public function jsonSerialize(): string - { - return $this->format('c'); - } - - - /** - * Returns the date and time in the format 'Y-m-d H:i:s'. - */ - public function __toString(): string - { - return $this->format('Y-m-d H:i:s'); - } - - - /** - * Returns a modified copy of the object. Use (clone $dt)->modify(...) for better type safety. - */ - public function modifyClone(string $modify = ''): static - { - $dolly = clone $this; - return $modify ? $dolly->modify($modify) : $dolly; - } - - - private function handleErrors(string $value): void - { - $errors = self::getLastErrors(); - $errors = array_merge($errors['errors'] ?? [], $errors['warnings'] ?? []); - if ($errors) { - throw new \Exception(implode(', ', $errors) . " '$value'"); - } - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/FileInfo.php b/tools/.phpstan/vendor/nette/utils/src/Utils/FileInfo.php deleted file mode 100644 index 64eeb74..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/FileInfo.php +++ /dev/null @@ -1,66 +0,0 @@ -setInfoClass(self::class); - } - - - /** - * Returns the relative directory path. - */ - public function getRelativePath(): string - { - return $this->relativePath; - } - - - /** - * Returns the relative path including file name. - */ - public function getRelativePathname(): string - { - return ($this->relativePath === '' ? '' : $this->relativePath . DIRECTORY_SEPARATOR) - . $this->getBasename(); - } - - - /** - * Returns the contents of the file. - * @throws Nette\IOException - */ - public function read(): string - { - return FileSystem::read($this->getPathname()); - } - - - /** - * Writes the contents to the file. - * @throws Nette\IOException - */ - public function write(string $content): void - { - FileSystem::write($this->getPathname(), $content); - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/FileSystem.php b/tools/.phpstan/vendor/nette/utils/src/Utils/FileSystem.php deleted file mode 100644 index e55b996..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/FileSystem.php +++ /dev/null @@ -1,355 +0,0 @@ -getPathname()); - } - - foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($origin, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) { - if ($item->isDir()) { - static::createDir($target . '/' . $iterator->getSubPathname()); - } else { - static::copy($item->getPathname(), $target . '/' . $iterator->getSubPathname()); - } - } - } else { - static::createDir(dirname($target)); - if (@stream_copy_to_stream(static::open($origin, 'rb'), static::open($target, 'wb')) === false) { // @ is escalated to exception - throw new Nette\IOException(sprintf( - "Unable to copy file '%s' to '%s'. %s", - self::normalizePath($origin), - self::normalizePath($target), - Helpers::getLastError(), - )); - } - } - } - - - /** - * Opens file and returns resource. - * @return resource - * @throws Nette\IOException on error occurred - */ - public static function open(string $path, string $mode) - { - $f = @fopen($path, $mode); // @ is escalated to exception - if (!$f) { - throw new Nette\IOException(sprintf( - "Unable to open file '%s'. %s", - self::normalizePath($path), - Helpers::getLastError(), - )); - } - return $f; - } - - - /** - * Deletes a file or an entire directory if exists. If the directory is not empty, it deletes its contents first. - * @throws Nette\IOException on error occurred - */ - public static function delete(string $path): void - { - if (is_file($path) || is_link($path)) { - $func = DIRECTORY_SEPARATOR === '\\' && is_dir($path) ? 'rmdir' : 'unlink'; - if (!@$func($path)) { // @ is escalated to exception - throw new Nette\IOException(sprintf( - "Unable to delete '%s'. %s", - self::normalizePath($path), - Helpers::getLastError(), - )); - } - } elseif (is_dir($path)) { - foreach (new \FilesystemIterator($path) as $item) { - \assert($item instanceof \SplFileInfo); - static::delete($item->getPathname()); - } - - if (!@rmdir($path)) { // @ is escalated to exception - throw new Nette\IOException(sprintf( - "Unable to delete directory '%s'. %s", - self::normalizePath($path), - Helpers::getLastError(), - )); - } - } - } - - - /** - * Renames or moves a file or a directory. Overwrites existing files and directories by default. - * @throws Nette\IOException on error occurred - * @throws Nette\InvalidStateException if $overwrite is set to false and destination already exists - */ - public static function rename(string $origin, string $target, bool $overwrite = true): void - { - if (!$overwrite && file_exists($target)) { - throw new Nette\InvalidStateException(sprintf("File or directory '%s' already exists.", self::normalizePath($target))); - - } elseif (!file_exists($origin)) { - throw new Nette\IOException(sprintf("File or directory '%s' not found.", self::normalizePath($origin))); - - } else { - static::createDir(dirname($target)); - if (realpath($origin) !== realpath($target)) { - static::delete($target); - } - - if (!@rename($origin, $target)) { // @ is escalated to exception - throw new Nette\IOException(sprintf( - "Unable to rename file or directory '%s' to '%s'. %s", - self::normalizePath($origin), - self::normalizePath($target), - Helpers::getLastError(), - )); - } - } - } - - - /** - * Reads the content of a file. - * @throws Nette\IOException on error occurred - */ - public static function read(string $file): string - { - $content = @file_get_contents($file); // @ is escalated to exception - if ($content === false) { - throw new Nette\IOException(sprintf( - "Unable to read file '%s'. %s", - self::normalizePath($file), - Helpers::getLastError(), - )); - } - - return $content; - } - - - /** - * Reads the file content line by line. Because it reads continuously as we iterate over the lines, - * it is possible to read files larger than the available memory. - * @return \Generator - * @throws Nette\IOException on error occurred - */ - public static function readLines(string $file, bool $stripNewLines = true): \Generator - { - return (function ($f) use ($file, $stripNewLines) { - $counter = 0; - do { - $line = Callback::invokeSafe('fgets', [$f], fn($error) => throw new Nette\IOException(sprintf( - "Unable to read file '%s'. %s", - self::normalizePath($file), - $error, - ))); - if ($line === false) { - fclose($f); - break; - } - if ($stripNewLines) { - $line = rtrim($line, "\r\n"); - } - - yield $counter++ => $line; - - } while (true); - })(static::open($file, 'r')); - } - - - /** - * 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 - { - static::createDir(dirname($file)); - if (@file_put_contents($file, $content) === false) { // @ is escalated to exception - throw new Nette\IOException(sprintf( - "Unable to write file '%s'. %s", - self::normalizePath($file), - Helpers::getLastError(), - )); - } - - if ($mode !== null && !@chmod($file, $mode)) { // @ is escalated to exception - throw new Nette\IOException(sprintf( - "Unable to chmod file '%s' to mode %s. %s", - self::normalizePath($file), - decoct($mode), - Helpers::getLastError(), - )); - } - } - - - /** - * Sets file permissions to `$fileMode` or directory permissions to `$dirMode`. - * Recursively traverses and sets permissions on the entire contents of the directory as well. - * @throws Nette\IOException on error occurred - */ - public static function makeWritable(string $path, int $dirMode = 0o777, int $fileMode = 0o666): void - { - if (is_file($path)) { - if (!@chmod($path, $fileMode)) { // @ is escalated to exception - throw new Nette\IOException(sprintf( - "Unable to chmod file '%s' to mode %s. %s", - self::normalizePath($path), - decoct($fileMode), - Helpers::getLastError(), - )); - } - } elseif (is_dir($path)) { - foreach (new \FilesystemIterator($path) as $item) { - \assert($item instanceof \SplFileInfo); - static::makeWritable($item->getPathname(), $dirMode, $fileMode); - } - - if (!@chmod($path, $dirMode)) { // @ is escalated to exception - throw new Nette\IOException(sprintf( - "Unable to chmod directory '%s' to mode %s. %s", - self::normalizePath($path), - decoct($dirMode), - Helpers::getLastError(), - )); - } - } else { - throw new Nette\IOException(sprintf("File or directory '%s' not found.", self::normalizePath($path))); - } - } - - - /** - * Determines if the path is absolute. - */ - public static function isAbsolute(string $path): bool - { - return (bool) preg_match('#([a-z]:)?[/\\\]|[a-z][a-z0-9+.-]*://#Ai', $path); - } - - - /** - * 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. - */ - public static function normalizePath(string $path): string - { - $parts = $path === '' ? [] : preg_split('~[/\\\]+~', $path); - $res = []; - foreach ($parts as $part) { - if ($part === '..' && $res && end($res) !== '..' && end($res) !== '') { - array_pop($res); - } elseif ($part !== '.') { - $res[] = $part; - } - } - - return $res === [''] - ? DIRECTORY_SEPARATOR - : implode(DIRECTORY_SEPARATOR, $res); - } - - - /** - * Joins all segments of the path and normalizes the result. - */ - public static function joinPaths(string ...$paths): string - { - return self::normalizePath(implode('/', $paths)); - } - - - /** - * Resolves a path against a base path. If the path is absolute, returns it directly, if it's relative, joins it with the base path. - */ - public static function resolvePath(string $basePath, string $path): string - { - return match (true) { - self::isAbsolute($path) => self::platformSlashes($path), - $path === '' => self::platformSlashes($basePath), - default => self::joinPaths($basePath, $path), - }; - } - - - /** - * Converts backslashes to slashes. - */ - public static function unixSlashes(string $path): string - { - return strtr($path, '\\', '/'); - } - - - /** - * Converts slashes to platform-specific directory separators. - */ - public static function platformSlashes(string $path): string - { - return DIRECTORY_SEPARATOR === '/' - ? strtr($path, '\\', '/') - : str_replace(':\\\\', '://', strtr($path, '/', '\\')); // protocol:// - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Finder.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Finder.php deleted file mode 100644 index 10a8474..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Finder.php +++ /dev/null @@ -1,527 +0,0 @@ -size('> 10kB') - * ->from('.') - * ->exclude('temp'); - * - * @implements \IteratorAggregate - */ -class Finder implements \IteratorAggregate -{ - /** @var array */ - private array $find = []; - - /** @var string[] */ - private array $in = []; - - /** @var array<\Closure(FileInfo): bool> */ - private array $filters = []; - - /** @var array<\Closure(FileInfo): bool> */ - private array $descentFilters = []; - - /** @var array */ - private array $appends = []; - private bool $childFirst = false; - - /** @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 - { - $masks = is_array($masks) ? $masks : func_get_args(); // compatibility with variadic - return (new static)->addMask($masks, 'dir')->addMask($masks, 'file'); - } - - - /** - * Begins search for files matching mask. - * @param string|list $masks - */ - public static function findFiles(string|array $masks = ['*']): static - { - $masks = is_array($masks) ? $masks : func_get_args(); // compatibility with variadic - return (new static)->addMask($masks, 'file'); - } - - - /** - * Begins search for directories matching mask. - * @param string|list $masks - */ - public static function findDirectories(string|array $masks = ['*']): static - { - $masks = is_array($masks) ? $masks : func_get_args(); // compatibility with variadic - return (new static)->addMask($masks, 'dir'); - } - - - /** - * Finds files matching the specified masks. - * @param string|list $masks - */ - public function files(string|array $masks = ['*']): static - { - return $this->addMask((array) $masks, 'file'); - } - - - /** - * Finds directories matching the specified masks. - * @param string|list $masks - */ - public function directories(string|array $masks = ['*']): static - { - return $this->addMask((array) $masks, 'dir'); - } - - - /** @param list $masks */ - private function addMask(array $masks, string $mode): static - { - foreach ($masks as $mask) { - $mask = FileSystem::unixSlashes($mask); - if ($mode === 'dir') { - $mask = rtrim($mask, '/'); - } - if ($mask === '' || ($mode === 'file' && str_ends_with($mask, '/'))) { - throw new Nette\InvalidArgumentException("Invalid mask '$mask'"); - } - if (str_starts_with($mask, '**/')) { - $mask = substr($mask, 3); - } - $this->find[] = [$mask, $mode]; - } - return $this; - } - - - /** - * Searches in the given directories. Wildcards are allowed. - * @param string|list $paths - */ - public function in(string|array $paths): static - { - $paths = is_array($paths) ? $paths : func_get_args(); // compatibility with variadic - $this->addLocation($paths, ''); - return $this; - } - - - /** - * Searches recursively from the given directories. Wildcards are allowed. - * @param string|list $paths - */ - public function from(string|array $paths): static - { - $paths = is_array($paths) ? $paths : func_get_args(); // compatibility with variadic - $this->addLocation($paths, '/**'); - return $this; - } - - - /** @param list $paths */ - private function addLocation(array $paths, string $ext): void - { - foreach ($paths as $path) { - if ($path === '') { - throw new Nette\InvalidArgumentException("Invalid directory '$path'"); - } - $path = rtrim(FileSystem::unixSlashes($path), '/'); - $this->in[] = $path . $ext; - } - } - - - /** - * Lists directory's contents before the directory itself. By default, this is disabled. - */ - public function childFirst(bool $state = true): static - { - $this->childFirst = $state; - return $this; - } - - - /** - * Ignores unreadable directories. By default, this is enabled. - */ - public function ignoreUnreadableDirs(bool $state = true): static - { - $this->ignoreUnreadableDirs = $state; - return $this; - } - - - /** - * 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(...); - return $this; - } - - - /** - * Sorts files in each directory naturally by name. - */ - public function sortByName(): static - { - $this->sort = fn(FileInfo $a, FileInfo $b): int => strnatcmp($a->getBasename(), $b->getBasename()); - return $this; - } - - - /** - * 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 - { - if ($paths === null) { - return $this->appends[] = new static; - } - - $this->appends = array_merge($this->appends, (array) $paths); - return $this; - } - - - /********************* filtering ****************d*g**/ - - - /** - * 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 - { - $masks = is_array($masks) ? $masks : func_get_args(); // compatibility with variadic - foreach ($masks as $mask) { - $mask = FileSystem::unixSlashes($mask); - if (!preg_match('~^/?(\*\*/)?(.+)(/\*\*|/\*|/|)$~D', $mask, $m)) { - throw new Nette\InvalidArgumentException("Invalid mask '$mask'"); - } - $end = $m[3]; - $re = $this->buildPattern($m[2]); - $filter = fn(FileInfo $file): bool => ($end && !$file->isDir()) - || !preg_match($re, FileSystem::unixSlashes($file->getRelativePathname())); - - $this->descentFilter($filter); - if ($end !== '/*') { - $this->filter($filter); - } - } - - return $this; - } - - - /** - * Yields only entries which satisfy the given filter. - * @param callable(FileInfo): bool $callback - */ - public function filter(callable $callback): static - { - $this->filters[] = $callback(...); - return $this; - } - - - /** - * It descends only to directories that match the specified filter. - * @param callable(FileInfo): bool $callback - */ - public function descentFilter(callable $callback): static - { - $this->descentFilters[] = $callback(...); - return $this; - } - - - /** - * Sets the maximum depth of entries. - */ - public function limitDepth(?int $depth): static - { - $this->maxDepth = $depth ?? -1; - return $this; - } - - - /** - * 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 - { - if (func_num_args() === 1) { // in $operator is predicate - if (!preg_match('#^(?:([=<>!]=?|<>)\s*)?((?:\d*\.)?\d+)\s*(K|M|G|)B?$#Di', $operator, $matches)) { - throw new Nette\InvalidArgumentException('Invalid size predicate format.'); - } - - [, $operator, $size, $unit] = $matches; - $units = ['' => 1, 'k' => 1e3, 'm' => 1e6, 'g' => 1e9]; - $size = (float) $size * $units[strtolower($unit)]; - $operator = $operator ?: '='; - } - - return $this->filter(fn(FileInfo $file): bool => !$file->isFile() || Helpers::compare($file->getSize(), $operator, $size)); - } - - - /** - * 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 - { - if (func_num_args() === 1) { // in $operator is predicate - if (!preg_match('#^(?:([=<>!]=?|<>)\s*)?(.+)$#Di', $operator, $matches)) { - throw new Nette\InvalidArgumentException('Invalid date predicate format.'); - } - - [, $operator, $date] = $matches; - $operator = $operator ?: '='; - } - - $date = DateTime::from($date)->getTimestamp(); - return $this->filter(fn(FileInfo $file): bool => !$file->isFile() || Helpers::compare($file->getMTime(), $operator, $date)); - } - - - /********************* iterator generator ****************d*g**/ - - - /** - * Returns an array with all found files and directories. - * @return list - */ - public function collect(): array - { - return iterator_to_array($this->getIterator(), preserve_keys: false); - } - - - /** @return \Generator */ - public function getIterator(): \Generator - { - $plan = $this->buildPlan(); - foreach ($plan as $dir => $searches) { - yield from $this->traverseDir($dir, $searches); - } - - foreach ($this->appends as $item) { - if ($item instanceof self) { - yield from $item->getIterator(); - } else { - $item = FileSystem::platformSlashes($item); - yield $item => new FileInfo($item); - } - } - } - - - /** - * @param array $searches - * @param string[] $subdirs - * @return \Generator - */ - private function traverseDir(string $dir, array $searches, array $subdirs = []): \Generator - { - if ($this->maxDepth >= 0 && count($subdirs) > $this->maxDepth) { - return; - } elseif (!is_dir($dir)) { - throw new Nette\InvalidStateException(sprintf("Directory '%s' does not exist.", rtrim($dir, '/\\'))); - } - - try { - $pathNames = new \FilesystemIterator($dir, \FilesystemIterator::FOLLOW_SYMLINKS | \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::UNIX_PATHS); - } catch (\UnexpectedValueException $e) { - if ($this->ignoreUnreadableDirs) { - return; - } else { - throw new Nette\InvalidStateException($e->getMessage()); - } - } - - $files = $this->convertToFiles($pathNames, implode('/', $subdirs), FileSystem::isAbsolute($dir)); - - if ($this->sort) { - $files = iterator_to_array($files); - usort($files, $this->sort); - } - - foreach ($files as $file) { - $pathName = $file->getPathname(); - $cache = $subSearch = []; - - if ($file->isDir()) { - foreach ($searches as $search) { - if ($search->recursive && $this->proveFilters($this->descentFilters, $file, $cache)) { - $subSearch[] = $search; - } - } - } - - if ($this->childFirst && $subSearch) { - yield from $this->traverseDir($pathName, $subSearch, array_merge($subdirs, [$file->getBasename()])); - } - - $relativePathname = FileSystem::unixSlashes($file->getRelativePathname()); - foreach ($searches as $search) { - if ( - "is_$search->mode"(Helpers::IsWindows && $file->isLink() ? $file->getLinkTarget() : $file->getPathname()) - && preg_match($search->pattern, $relativePathname) - && $this->proveFilters($this->filters, $file, $cache) - ) { - yield $pathName => $file; - break; - } - } - - if (!$this->childFirst && $subSearch) { - yield from $this->traverseDir($pathName, $subSearch, array_merge($subdirs, [$file->getBasename()])); - } - } - } - - - /** @param iterable $pathNames */ - private function convertToFiles(iterable $pathNames, string $relativePath, bool $absolute): \Generator - { - foreach ($pathNames as $pathName) { - if (!$absolute) { - $pathName = preg_replace('~\.?/~A', '', $pathName); - } - $pathName = FileSystem::platformSlashes($pathName); - yield new FileInfo($pathName, $relativePath); - } - } - - - /** - * @param (\Closure(FileInfo): bool)[] $filters - * @param array $cache - */ - private function proveFilters(array $filters, FileInfo $file, array &$cache): bool - { - foreach ($filters as $filter) { - $res = &$cache[spl_object_id($filter)]; - $res ??= $filter($file); - if (!$res) { - return false; - } - } - - return true; - } - - - /** @return array> */ - private function buildPlan(): array - { - $plan = $dirCache = []; - foreach ($this->find as [$mask, $mode]) { - $splits = []; - if (FileSystem::isAbsolute($mask)) { - if ($this->in) { - throw new Nette\InvalidStateException("You cannot combine the absolute path in the mask '$mask' and the directory to search '{$this->in[0]}'."); - } - $splits[] = self::splitRecursivePart($mask); - } else { - foreach ($this->in ?: ['.'] as $in) { - $in = strtr($in, ['[' => '[[]', ']' => '[]]']); // in path, do not treat [ and ] as a pattern by glob() - $splits[] = self::splitRecursivePart($in . '/' . $mask); - } - } - - foreach ($splits as [$base, $rest, $recursive]) { - $base = $base === '' ? '.' : $base; - $dirs = $dirCache[$base] ??= strpbrk($base, '*?[') - ? glob($base, GLOB_NOSORT | GLOB_ONLYDIR | GLOB_NOESCAPE) - : [strtr($base, ['[[]' => '[', '[]]' => ']'])]; // unescape [ and ] - - if (!$dirs) { - throw new Nette\InvalidStateException(sprintf("Directory '%s' does not exist.", rtrim($base, '/\\'))); - } - - $search = (object) ['pattern' => $this->buildPattern($rest), 'mode' => $mode, 'recursive' => $recursive]; - foreach ($dirs as $dir) { - $plan[$dir][] = $search; - } - } - } - - return $plan; - } - - - /** - * 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 - { - $a = strrpos($path, '/'); - $parts = preg_split('~(?<=^|/)\*\*($|/)~', substr($path, 0, $a + 1), 2); - return isset($parts[1]) - ? [$parts[0], $parts[1] . substr($path, $a + 1), true] - : [$parts[0], substr($path, $a + 1), false]; - } - - - /** - * Converts wildcards to regular expression. - */ - private function buildPattern(string $mask): string - { - if ($mask === '*') { - return '##'; - } elseif (str_starts_with($mask, './')) { - $anchor = '^'; - $mask = substr($mask, 2); - } else { - $anchor = '(?:^|/)'; - } - - $pattern = strtr( - preg_quote($mask, '#'), - [ - '\*\*/' => '(.+/)?', - '\*' => '[^/]*', - '\?' => '[^/]', - '\[\!' => '[^', - '\[' => '[', - '\]' => ']', - '\-' => '-', - ], - ); - return '#' . $anchor . $pattern . '$#D' . (Helpers::IsWindows ? 'i' : ''); - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Floats.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Floats.php deleted file mode 100644 index 02cebeb..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Floats.php +++ /dev/null @@ -1,106 +0,0 @@ - $b it returns 1 - * @throws \LogicException if one of parameters is NAN - */ - public static function compare(float $a, float $b): int - { - if (is_nan($a) || is_nan($b)) { - throw new \LogicException('Trying to compare NAN'); - - } elseif (!is_finite($a) && !is_finite($b) && $a === $b) { - return 0; - } - - $diff = abs($a - $b); - if (($diff < self::Epsilon || ($diff / max(abs($a), abs($b)) < self::Epsilon))) { - return 0; - } - - return $a < $b ? -1 : 1; - } - - - /** - * Returns true if $a = $b - * @throws \LogicException if one of parameters is NAN - */ - public static function areEqual(float $a, float $b): bool - { - return self::compare($a, $b) === 0; - } - - - /** - * Returns true if $a < $b - * @throws \LogicException if one of parameters is NAN - */ - public static function isLessThan(float $a, float $b): bool - { - return self::compare($a, $b) < 0; - } - - - /** - * Returns true if $a <= $b - * @throws \LogicException if one of parameters is NAN - */ - public static function isLessThanOrEqualTo(float $a, float $b): bool - { - return self::compare($a, $b) <= 0; - } - - - /** - * Returns true if $a > $b - * @throws \LogicException if one of parameters is NAN - */ - public static function isGreaterThan(float $a, float $b): bool - { - return self::compare($a, $b) > 0; - } - - - /** - * Returns true if $a >= $b - * @throws \LogicException if one of parameters is NAN - */ - public static function isGreaterThanOrEqualTo(float $a, float $b): bool - { - return self::compare($a, $b) >= 0; - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Helpers.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Helpers.php deleted file mode 100644 index 73d77bb..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Helpers.php +++ /dev/null @@ -1,125 +0,0 @@ - ''); - try { - $func(); - return ob_get_clean(); - } catch (\Throwable $e) { - ob_end_clean(); - throw $e; - } - } - - - /** - * Returns the last occurred PHP error or an empty string if no error occurred. Unlike error_get_last(), - * it is not affected by the PHP directive html_errors and always returns text, not HTML. - */ - public static function getLastError(): string - { - $message = error_get_last()['message'] ?? ''; - $message = ini_get('html_errors') ? Html::htmlToText($message) : $message; - $message = preg_replace('#^\w+\(.*?\): #', '', $message); - return $message; - } - - - /** - * Converts false to null, does not change other values. - */ - public static function falseToNull(mixed $value): mixed - { - return $value === false ? null : $value; - } - - - /** - * Returns value clamped to the inclusive range of min and max. - * @return ($value is float ? float : ($min is float ? float : ($max is float ? float : int))) - */ - public static function clamp(int|float $value, int|float $min, int|float $max): int|float - { - if ($min > $max) { - throw new Nette\InvalidArgumentException("Minimum ($min) is not less than maximum ($max)."); - } - - return min(max($value, $min), $max); - } - - - /** - * Finds the string from $possibilities most similar to $value using Levenshtein distance, or null if none is close enough. - * @param string[] $possibilities - */ - public static function getSuggestion(array $possibilities, string $value): ?string - { - $best = null; - $min = (strlen($value) / 4 + 1) * 10 + .1; - foreach (array_unique($possibilities) as $item) { - if ($item !== $value && ($len = levenshtein($item, $value, 10, 11, 10)) < $min) { - $min = $len; - $best = $item; - } - } - - return $best; - } - - - /** - * Compares two values in the same way that PHP does. Recognizes operators: >, >=, <, <=, =, ==, ===, !=, !==, <> - * @param '>'|'>='|'<'|'<='|'='|'=='|'==='|'!='|'!=='|'<>' $operator - */ - public static function compare(mixed $left, string $operator, mixed $right): bool - { - return match ($operator) { - '>' => $left > $right, - '>=' => $left >= $right, - '<' => $left < $right, - '<=' => $left <= $right, - '=', '==' => $left == $right, - '===' => $left === $right, - '!=', '<>' => $left != $right, - '!==' => $left !== $right, - default => throw new Nette\InvalidArgumentException("Unknown operator '$operator'"), - }; - } - - - /** - * Splits a class name into namespace and short class name. - * @return array{string, string} - */ - public static function splitClassName(string $name): array - { - return ($pos = strrpos($name, '\\')) === false - ? ['', $name] - : [substr($name, 0, $pos), substr($name, $pos + 1)]; - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Html.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Html.php deleted file mode 100644 index 8ee2f7e..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Html.php +++ /dev/null @@ -1,840 +0,0 @@ - - * @implements \ArrayAccess - */ -class Html implements \ArrayAccess, \Countable, \IteratorAggregate, HtmlStringable -{ - /** @var array element's attributes */ - public array $attrs = []; - - /** @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 */ - protected array $children = []; - - /** element's name */ - private string $name = ''; - - private bool $isEmpty = false; - - - /** - * Constructs new HTML element. - * @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 - { - $el = new static; - $parts = explode(' ', (string) $name, 2); - $el->setName($parts[0]); - - if (is_array($attrs)) { - $el->attrs = $attrs; - - } elseif ($attrs !== null) { - $el->setText($attrs); - } - - if (isset($parts[1])) { - foreach (Strings::matchAll($parts[1] . ' ', '#([a-z0-9:-]+)(?:=(["\'])?(.*?)(?(2)\2|\s))?#i') as $m) { - $el->attrs[$m[1]] = $m[3] ?? true; - } - } - - return $el; - } - - - /** - * Returns an object representing HTML text. - */ - public static function fromHtml(string $html): static - { - return (new static)->setHtml($html); - } - - - /** - * Returns an object representing plain text. - */ - public static function fromText(string $text): static - { - return (new static)->setText($text); - } - - - /** - * Converts to HTML. - */ - final public function toHtml(): string - { - return $this->render(); - } - - - /** - * Converts to plain text. - */ - final public function toText(): string - { - return $this->getText(); - } - - - /** - * Converts given HTML code to plain text. - */ - public static function htmlToText(string $html): string - { - return html_entity_decode(strip_tags($html), ENT_QUOTES | ENT_HTML5, 'UTF-8'); - } - - - /** - * Changes element's name. - */ - final public function setName(string $name, ?bool $isEmpty = null): static - { - $this->name = $name; - $this->isEmpty = $isEmpty ?? isset(static::$emptyElements[$name]); - return $this; - } - - - /** - * Returns element's name. - */ - final public function getName(): string - { - return $this->name; - } - - - /** - * Checks whether the element is a void (self-closing) element. - */ - final public function isEmpty(): bool - { - return $this->isEmpty; - } - - - /** - * Sets multiple attributes. - * @param array $attrs - */ - public function addAttributes(array $attrs): static - { - $this->attrs = array_merge($this->attrs, $attrs); - return $this; - } - - - /** - * Appends value to element's attribute. - */ - public function appendAttribute(string $name, mixed $value, mixed $option = true): static - { - if (is_array($value)) { - $prev = isset($this->attrs[$name]) ? (array) $this->attrs[$name] : []; - $this->attrs[$name] = $value + $prev; - - } elseif ((string) $value === '') { - $tmp = &$this->attrs[$name]; // appending empty value? -> ignore, but ensure it exists - - } elseif (!isset($this->attrs[$name]) || is_array($this->attrs[$name])) { // needs array - $this->attrs[$name][$value] = $option; - - } else { - $this->attrs[$name] = [$this->attrs[$name] => true, $value => $option]; - } - - return $this; - } - - - /** - * Sets element's attribute. - */ - public function setAttribute(string $name, mixed $value): static - { - $this->attrs[$name] = $value; - return $this; - } - - - /** - * Returns element's attribute. - */ - public function getAttribute(string $name): mixed - { - return $this->attrs[$name] ?? null; - } - - - /** - * Unsets element's attribute. - */ - public function removeAttribute(string $name): static - { - unset($this->attrs[$name]); - return $this; - } - - - /** - * Unsets element's attributes. - * @param list $attributes - */ - public function removeAttributes(array $attributes): static - { - foreach ($attributes as $name) { - unset($this->attrs[$name]); - } - - return $this; - } - - - /** - * Sets element's attribute via property assignment. - */ - final public function __set(string $name, mixed $value): void - { - $this->attrs[$name] = $value; - } - - - /** - * Returns element's attribute via property access. - */ - final public function &__get(string $name): mixed - { - return $this->attrs[$name]; - } - - - /** - * Checks if element's attribute is set. - */ - final public function __isset(string $name): bool - { - return isset($this->attrs[$name]); - } - - - /** - * Unsets element's attribute via property unset. - */ - final public function __unset(string $name): void - { - unset($this->attrs[$name]); - } - - - /** - * Sets or returns element's attribute via method call. - * @param mixed[] $args - */ - final public function __call(string $m, array $args): mixed - { - $p = substr($m, 0, 3); - if ($p === 'get' || $p === 'set' || $p === 'add') { - $m = substr($m, 3); - $m[0] = $m[0] | "\x20"; - if ($p === 'get') { - return $this->attrs[$m] ?? null; - - } elseif ($p === 'add') { - $args[] = true; - } - } - - if (count($args) === 0) { // invalid - - } elseif (count($args) === 1) { // set - $this->attrs[$m] = $args[0]; - - } else { // add - $this->appendAttribute($m, $args[0], $args[1]); - } - - return $this; - } - - - /** - * Special setter for element's attribute. - * @param array $query - */ - final public function href(string $path, array $query = []): static - { - if ($query) { - $query = http_build_query($query, '', '&'); - if ($query !== '') { - $path .= '?' . $query; - } - } - - $this->attrs['href'] = $path; - return $this; - } - - - /** - * Setter for data-* attributes. Booleans are converted to 'true' resp. 'false'. - */ - public function data(string $name, mixed $value = null): static - { - if (func_num_args() === 1) { - $this->attrs['data'] = $name; - } else { - $this->attrs["data-$name"] = is_bool($value) - ? json_encode($value) - : $value; - } - - return $this; - } - - - /** - * Sets element's HTML content. - */ - final public function setHtml(mixed $html): static - { - $this->children = [(string) $html]; - return $this; - } - - - /** - * Returns element's HTML content. - */ - final public function getHtml(): string - { - return implode('', $this->children); - } - - - /** - * Sets element's textual content. - */ - final public function setText(mixed $text): static - { - if (!$text instanceof HtmlStringable) { - $text = htmlspecialchars((string) $text, ENT_NOQUOTES, 'UTF-8'); - } - - $this->children = [(string) $text]; - return $this; - } - - - /** - * Returns element's textual content. - */ - final public function getText(): string - { - return self::htmlToText($this->getHtml()); - } - - - /** - * Adds new element's child. - */ - final public function addHtml(HtmlStringable|string $child): static - { - return $this->insert(null, $child); - } - - - /** - * Appends plain-text string to element content. - */ - public function addText(\Stringable|string|int|null $text): static - { - if (!$text instanceof HtmlStringable) { - $text = htmlspecialchars((string) $text, ENT_NOQUOTES, 'UTF-8'); - } - - return $this->insert(null, $text); - } - - - /** - * Creates and adds a new Html child. - * @param array|string|null $attrs - */ - final public function create(string $name, array|string|null $attrs = null): static - { - $this->insert(null, $child = static::el($name, $attrs)); - return $child; - } - - - /** - * Inserts child node. - */ - public function insert(?int $index, HtmlStringable|string $child, bool $replace = false): static - { - $child = $child instanceof self ? $child : (string) $child; - if ($index === null) { // append - $this->children[] = $child; - - } else { // insert or replace - array_splice($this->children, $index, $replace ? 1 : 0, [$child]); - } - - return $this; - } - - - /** - * Inserts (replaces) child node (\ArrayAccess implementation). - * @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 - { - $this->insert($index, $child, replace: true); - } - - - /** - * Returns child node (\ArrayAccess implementation). - * @param int $index - */ - final public function offsetGet($index): self|string - { - return $this->children[$index]; - } - - - /** - * Exists child node? (\ArrayAccess implementation). - * @param int $index - */ - final public function offsetExists($index): bool - { - return isset($this->children[$index]); - } - - - /** - * Removes child node (\ArrayAccess implementation). - * @param int $index - */ - public function offsetUnset($index): void - { - if (isset($this->children[$index])) { - array_splice($this->children, $index, 1); - } - } - - - /** - * Returns children count. - */ - final public function count(): int - { - return count($this->children); - } - - - /** - * Removes all children. - */ - public function removeChildren(): void - { - $this->children = []; - } - - - /** - * Iterates over elements. - * @return \ArrayIterator - */ - final public function getIterator(): \ArrayIterator - { - return new \ArrayIterator($this->children); - } - - - /** - * Returns all children. - * @return array - */ - final public function getChildren(): array - { - return $this->children; - } - - - /** - * Renders element's start tag, content and end tag. Pass indent level to enable pretty-printing. - */ - final public function render(?int $indent = null): string - { - $s = $this->startTag(); - - if (!$this->isEmpty) { - // add content - if ($indent !== null) { - $indent++; - } - - foreach ($this->children as $child) { - if ($child instanceof self) { - $s .= $child->render($indent); - } else { - $s .= $child; - } - } - - // add end tag - $s .= $this->endTag(); - } - - if ($indent !== null) { - return "\n" . str_repeat("\t", $indent - 1) . $s . "\n" . str_repeat("\t", max(0, $indent - 2)); - } - - return $s; - } - - - final public function __toString(): string - { - return $this->render(); - } - - - /** - * Returns element's start tag. - */ - final public function startTag(): string - { - return $this->name - ? '<' . $this->name . $this->attributes() . '>' - : ''; - } - - - /** - * Returns element's end tag. - */ - final public function endTag(): string - { - return $this->name && !$this->isEmpty ? 'name . '>' : ''; - } - - - /** - * Returns element's attributes. - * @internal - */ - final public function attributes(): string - { - $s = ''; - $attrs = $this->attrs; - foreach ($attrs as $key => $value) { - if ($value === null || $value === false) { - continue; - - } elseif ($value === true) { - $s .= ' ' . $key; - - continue; - - } elseif (is_array($value)) { - if (str_starts_with($key, 'data-')) { - $value = Json::encode($value); - - } else { - $tmp = null; - foreach ($value as $k => $v) { - if ($v != null) { // intentionally ==, skip nulls & empty string - // composite 'style' vs. 'others' - $tmp[] = $v === true - ? $k - : (is_string($k) ? $k . ':' . $v : $v); - } - } - - if ($tmp === null) { - continue; - } - - $value = implode($key === 'style' || !strncmp($key, 'on', 2) ? ';' : ' ', $tmp); - } - } elseif (is_float($value)) { - $value = rtrim(rtrim(number_format($value, 10, '.', ''), '0'), '.'); - - } else { - $value = (string) $value; - } - - $q = str_contains($value, '"') ? "'" : '"'; - $s .= ' ' . $key . '=' . $q - . str_replace( - ['&', $q, '<'], - ['&', $q === '"' ? '"' : ''', '<'], - $value, - ) - . (str_contains($value, '`') && strpbrk($value, ' <>"\'') === false ? ' ' : '') - . $q; - } - - $s = str_replace('@', '@', $s); - return $s; - } - - - /** - * Clones all children too. - */ - public function __clone() - { - foreach ($this->children as $key => $value) { - if (is_object($value)) { - $this->children[$key] = clone $value; - } - } - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Image.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Image.php deleted file mode 100644 index 3fdc3e4..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Image.php +++ /dev/null @@ -1,853 +0,0 @@ - - * $image = Image::fromFile('nette.jpg'); - * $image->resize(150, 100); - * $image->sharpen(); - * $image->send(); - * - * - * @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) - * @method int colorAllocate(int $red, int $green, int $blue) - * @method int colorAllocateAlpha(int $red, int $green, int $blue, int $alpha) - * @method int colorAt(int $x, int $y) - * @method int colorClosest(int $red, int $green, int $blue) - * @method int colorClosestAlpha(int $red, int $green, int $blue, int $alpha) - * @method int colorClosestHWB(int $red, int $green, int $blue) - * @method void colorDeallocate(int $color) - * @method int colorExact(int $red, int $green, int $blue) - * @method int colorExactAlpha(int $red, int $green, int $blue, int $alpha) - * @method void colorMatch(Image $image2) - * @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{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 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 = 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 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 void gammaCorrect(float $inputgamma, float $outputgamma) - * @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 paletteCopy(Image $source) - * @method void paletteToTrueColor() - * @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 = 3) - * @method void setBrush(Image $brush) - * @method void setClip(int $x1, int $y1, int $x2, int $y2) - * @method void setInterpolation(int $method = 3) - * @method void setPixel(int $x, int $y, ImageColor $color) - * @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 = []) - * @property-read positive-int $width - * @property-read positive-int $height - * @property-read \GdImage $imageResource - */ -class Image -{ - use Nette\SmartObject; - - /** Prevent from getting resized to a bigger size than the original */ - public const ShrinkOnly = 0b0001; - - /** Resizes to a specified width and height without keeping aspect ratio */ - public const Stretch = 0b0010; - - /** Resizes to fit into a specified width and height and preserves aspect ratio */ - public const OrSmaller = 0b0000; - - /** Resizes while bounding the smaller dimension to the specified width or height and preserves aspect ratio */ - public const OrBigger = 0b0100; - - /** Resizes to the smallest possible size to completely cover specified width and height and reserves aspect ratio */ - public const Cover = 0b1000; - - /** @deprecated use Image::ShrinkOnly */ - public const SHRINK_ONLY = self::ShrinkOnly; - - /** @deprecated use Image::Stretch */ - public const STRETCH = self::Stretch; - - /** @deprecated use Image::OrSmaller */ - public const FIT = self::OrSmaller; - - /** @deprecated use Image::OrBigger */ - public const FILL = self::OrBigger; - - /** @deprecated use Image::Cover */ - public const EXACT = self::Cover; - - /** @deprecated use Image::EmptyGIF */ - public const EMPTY_GIF = self::EmptyGIF; - - /** image types */ - public const - JPEG = ImageType::JPEG, - PNG = ImageType::PNG, - GIF = ImageType::GIF, - WEBP = ImageType::WEBP, - AVIF = ImageType::AVIF, - BMP = ImageType::BMP; - - 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; - - - /** - * 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 - { - return [ - 'red' => max(0, min(255, $red)), - 'green' => max(0, min(255, $green)), - 'blue' => max(0, min(255, $blue)), - 'alpha' => max(0, min(127, $transparency)), - ]; - } - - - /** - * 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, ?string &$warnings = self::Sentinel): static - { - self::ensureExtension(); - $type = self::detectTypeFromFile($file); - if (!$type) { - 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__, $warnings); - } - - - /** - * 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, ?string &$warnings = self::Sentinel): static - { - self::ensureExtension(); - $type = self::detectTypeFromString($s); - if (!$type) { - throw new UnknownImageFileException('Unknown type of image.'); - } - - return self::invokeSafe('imagecreatefromstring', $s, 'Unable to open image from string.', __METHOD__, $warnings); - } - - - /** @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: ' . $warnings); - } elseif ($errors && $raiseWarning) { - trigger_error($callee . '(): ' . $warnings, E_USER_WARNING); - } - - return new static($res); - } - - - /** - * 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 - { - self::ensureExtension(); - if ($width < 1 || $height < 1) { - throw new Nette\InvalidArgumentException('Image width and height must be greater than zero.'); - } - - $image = new static(imagecreatetruecolor($width, $height)); - if ($color) { - $image->alphaBlending(false); - $image->filledRectangle(0, 0, $width - 1, $height - 1, self::normalizeColor($color)); - $image->alphaBlending(true); - } - - return $image; - } - - - /** - * Returns the type of image from file. - * @param-out ?int $width - * @param-out ?int $height - * @return ?ImageType::* - */ - 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; - } - - - /** - * Returns the type of image from string. - * @param-out ?int $width - * @param-out ?int $height - * @return ?ImageType::* - */ - 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; - } - - - /** - * Returns the file extension for the given image type. - * @param ImageType::* $type - * @return value-of - */ - public static function typeToExtension(int $type): string - { - if (!isset(self::Formats[$type])) { - throw new Nette\InvalidArgumentException("Unsupported image type '$type'."); - } - - return self::Formats[$type]; - } - - - /** - * Returns the image type for given file extension. - * @return ImageType::* - */ - public static function extensionToType(string $extension): int - { - $extensions = array_flip(self::Formats) + ['jpg' => ImageType::JPEG]; - $extension = strtolower($extension); - if (!isset($extensions[$extension])) { - throw new Nette\InvalidArgumentException("Unsupported file extension '$extension'."); - } - - return $extensions[$extension]; - } - - - /** - * Returns the mime type for the given image type. - * @param ImageType::* $type - */ - public static function typeToMimeType(int $type): string - { - return 'image/' . self::typeToExtension($type); - } - - - /** - * Checks whether the given image type is supported by the GD extension. - * @param ImageType::* $type - */ - public static function isTypeSupported(int $type): bool - { - self::ensureExtension(); - return (bool) (imagetypes() & match ($type) { - ImageType::JPEG => IMG_JPG, - ImageType::PNG => IMG_PNG, - ImageType::GIF => IMG_GIF, - ImageType::WEBP => IMG_WEBP, - ImageType::AVIF => 256, // IMG_AVIF, - ImageType::BMP => IMG_BMP, - default => 0, - }); - } - - - /** - * Returns list of image types supported by the GD extension. - * @return ImageType::*[] - */ - public static function getSupportedTypes(): array - { - self::ensureExtension(); - $flag = imagetypes(); - return array_filter([ - $flag & IMG_GIF ? ImageType::GIF : null, - $flag & IMG_JPG ? ImageType::JPEG : null, - $flag & IMG_PNG ? ImageType::PNG : null, - $flag & IMG_WEBP ? ImageType::WEBP : null, - $flag & 256 ? ImageType::AVIF : null, // IMG_AVIF - $flag & IMG_BMP ? ImageType::BMP : null, - ]); - } - - - /** - * Wraps GD image. - */ - public function __construct(\GdImage $image) - { - $this->setImageResource($image); - imagesavealpha($image, true); - } - - - /** - * Returns image width. - * @return positive-int - */ - public function getWidth(): int - { - return imagesx($this->image); - } - - - /** - * Returns image height. - * @return positive-int - */ - public function getHeight(): int - { - return imagesy($this->image); - } - - - /** - * Sets image resource. - */ - protected function setImageResource(\GdImage $image): static - { - $this->image = $image; - return $this; - } - - - /** - * Returns image GD resource. - */ - public function getImageResource(): \GdImage - { - return $this->image; - } - - - /** - * Scales an image. Width and height accept pixels or percent. - * @param int-mask-of $mode - */ - 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); - } - - [$newWidth, $newHeight] = static::calculateSize($this->getWidth(), $this->getHeight(), $width, $height, $mode); - - if ($newWidth !== $this->getWidth() || $newHeight !== $this->getHeight()) { // resize - $newImage = static::fromBlank($newWidth, $newHeight, ImageColor::rgb(0, 0, 0, 0))->getImageResource(); - imagecopyresampled( - $newImage, - $this->image, - 0, - 0, - 0, - 0, - $newWidth, - $newHeight, - $this->getWidth(), - $this->getHeight(), - ); - $this->image = $newImage; - } - - if ($width < 0 || $height < 0) { - imageflip($this->image, $width < 0 ? ($height < 0 ? IMG_FLIP_BOTH : IMG_FLIP_HORIZONTAL) : IMG_FLIP_VERTICAL); - } - - return $this; - } - - - /** - * 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, - int|string|null $newWidth, - int|string|null $newHeight, - int $mode = self::OrSmaller, - ): array - { - if ($newWidth === null) { - } elseif (self::isPercent($newWidth)) { - $newWidth = (int) round($srcWidth / 100 * abs($newWidth)); - $percents = true; - } else { - $newWidth = abs($newWidth); - } - - if ($newHeight === null) { - } elseif (self::isPercent($newHeight)) { - $newHeight = (int) round($srcHeight / 100 * abs($newHeight)); - $mode |= empty($percents) ? 0 : self::Stretch; - } else { - $newHeight = abs($newHeight); - } - - if ($mode & self::Stretch) { // non-proportional - if (!$newWidth || !$newHeight) { - throw new Nette\InvalidArgumentException('For stretching must be both width and height specified.'); - } - - if ($mode & self::ShrinkOnly) { - $newWidth = min($srcWidth, $newWidth); - $newHeight = min($srcHeight, $newHeight); - } - } else { // proportional - if (!$newWidth && !$newHeight) { - throw new Nette\InvalidArgumentException('At least width or height must be specified.'); - } - - $scale = []; - if ($newWidth > 0) { // fit width - $scale[] = $newWidth / $srcWidth; - } - - if ($newHeight > 0) { // fit height - $scale[] = $newHeight / $srcHeight; - } - - if ($mode & self::OrBigger) { - $scale = [max($scale ?: [1])]; - } - - if ($mode & self::ShrinkOnly) { - $scale[] = 1; - } - - $scale = min($scale ?: [1]); - $newWidth = (int) round($srcWidth * $scale); - $newHeight = (int) round($srcHeight * $scale); - } - - return [max((int) $newWidth, 1), max((int) $newHeight, 1)]; - } - - - /** - * Crops image. Arguments accepts pixels or percent. - */ - public function crop(int|string $left, int|string $top, int|string $width, int|string $height): static - { - [$r['x'], $r['y'], $r['width'], $r['height']] - = static::calculateCutout($this->getWidth(), $this->getHeight(), $left, $top, $width, $height); - if (gd_info()['GD Version'] === 'bundled (2.1.0 compatible)') { - $this->image = imagecrop($this->image, $r); - imagesavealpha($this->image, true); - } else { - $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; - } - - return $this; - } - - - /** - * Calculates dimensions of cutout in image. Arguments accepts pixels or percent. - * @return array{int, int, int, int} - */ - public static function calculateCutout( - int $srcWidth, - int $srcHeight, - int|string $left, - int|string $top, - int|string $newWidth, - int|string $newHeight, - ): array - { - $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; - $left = 0; - } - - if ($top < 0) { - $newHeight += $top; - $top = 0; - } - - $newWidth = min($newWidth, $srcWidth - $left); - $newHeight = min($newHeight, $srcHeight - $top); - return [$left, $top, $newWidth, $newHeight]; - } - - - /** - * Sharpens image a little bit. - */ - public function sharpen(): static - { - imageconvolution($this->image, [ // my magic numbers ;) - [-1, -1, -1], - [-1, 24, -1], - [-1, -1, -1], - ], 16, 0); - return $this; - } - - - /** - * Puts another image into this image. Left and top accepts pixels or percent. - * @param int<0, 100> $opacity 0..100 - */ - public function place(self $image, int|string $left = 0, int|string $top = 0, int $opacity = 100): static - { - $opacity = max(0, min(100, $opacity)); - if ($opacity === 0) { - return $this; - } - - $width = $image->getWidth(); - $height = $image->getHeight(); - $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) { - $tbl = []; - for ($i = 0; $i < 128; $i++) { - $tbl[$i] = round(127 - (127 - $i) * $opacity / 100); - } - - $output = imagecreatetruecolor($width, $height); - imagealphablending($output, false); - if (!$image->isTrueColor()) { - $input = $output; - imagefilledrectangle($output, 0, 0, $width, $height, (int) imagecolorallocatealpha($output, 0, 0, 0, 127)); - imagecopy($output, $image->image, 0, 0, 0, 0, $width, $height); - } - - for ($x = 0; $x < $width; $x++) { - for ($y = 0; $y < $height; $y++) { - $c = \imagecolorat($input, $x, $y); - $c = ($c & 0xFFFFFF) + ($tbl[$c >> 24] << 24); - \imagesetpixel($output, $x, $y, $c); - } - } - - imagealphablending($output, true); - } - - imagecopy( - $this->image, - $output, - $left, - $top, - 0, - 0, - $width, - $height, - ); - return $this; - } - - - /** - * 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, - string $fontFile, - float $size, - float $angle = 0, - array $options = [], - ): array - { - self::ensureExtension(); - $box = imagettfbbox($size, $angle, $fontFile, $text, $options); - return [ - 'left' => $minX = min([$box[0], $box[2], $box[4], $box[6]]), - 'top' => $minY = min([$box[1], $box[3], $box[5], $box[7]]), - 'width' => max([$box[0], $box[2], $box[4], $box[6]]) - $minX + 1, - 'height' => max([$box[1], $box[3], $box[5], $box[7]]) - $minY + 1, - ]; - } - - - /** - * 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 - { - if ($width !== 0 && $height !== 0) { - $this->rectangle($x, $y, $x + $width + ($width > 0 ? -1 : 1), $y + $height + ($height > 0 ? -1 : 1), $color); - } - } - - - /** - * 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 - { - if ($width !== 0 && $height !== 0) { - $this->filledRectangle($x, $y, $x + $width + ($width > 0 ? -1 : 1), $y + $height + ($height > 0 ? -1 : 1), $color); - } - } - - - /** - * 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::* $type - * @throws ImageException - */ - public function save(string $file, ?int $quality = null, ?int $type = null): void - { - $type ??= self::extensionToType(pathinfo($file, PATHINFO_EXTENSION)); - $this->output($type, $quality, $file); - } - - - /** - * Outputs image to string. 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::* $type - */ - public function toString(int $type = ImageType::JPEG, ?int $quality = null): string - { - return Helpers::capture(function () use ($type, $quality): void { - $this->output($type, $quality); - }); - } - - - /** - * Outputs image to string. - */ - public function __toString(): string - { - return $this->toString(); - } - - - /** - * Outputs image to browser. 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::* $type - * @throws ImageException - */ - public function send(int $type = ImageType::JPEG, ?int $quality = null): void - { - header('Content-Type: ' . self::typeToMimeType($type)); - $this->output($type, $quality); - } - - - /** - * Outputs image to browser or file. - * @param ImageType::* $type - * @throws ImageException - */ - private function output(int $type, ?int $quality, ?string $file = null): void - { - [$defQuality, $min, $max] = match ($type) { - ImageType::JPEG => [85, 0, 100], - ImageType::PNG => [9, 0, 9], - ImageType::GIF => [null, null, null], - ImageType::WEBP => [80, 0, 100], - ImageType::AVIF => [30, 0, 100], - ImageType::BMP => [null, null, null], - default => throw new Nette\InvalidArgumentException("Unsupported image type '$type'."), - }; - - $args = [$this->image, $file]; - if ($defQuality !== null) { - $args[] = $quality === null ? $defQuality : max($min, min($max, $quality)); - } - - Callback::invokeSafe('image' . self::Formats[$type], $args, function (string $message) use ($file): void { - if ($file !== null) { - @unlink($file); - } - throw new ImageException($message); - }); - } - - - /** - * Call to undefined method. - * @param mixed[] $args - * @throws Nette\MemberAccessException - */ - public function __call(string $name, array $args): mixed - { - $function = 'image' . $name; - if (!function_exists($function)) { - ObjectHelpers::strictCall(static::class, $name); - } - - foreach ($args as $key => $value) { - if ($value instanceof self) { - $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); - } - } - - $res = $function($this->image, ...$args); - return $res instanceof \GdImage - ? $this->setImageResource($res) - : $res; - } - - - public function __clone() - { - ob_start(fn() => ''); - imagepng($this->image, null, 0); - $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, '%')) { - $num = (float) substr($num, 0, -1); - return true; - } elseif (is_int($num) || $num === (string) (int) $num) { - $num = (int) $num; - return false; - } - - throw new Nette\InvalidArgumentException("Expected dimension in int|string, '$num' given."); - } - - - /** - * Prevents serialization. - */ - public function __serialize(): array - { - throw new Nette\NotSupportedException('You cannot serialize or unserialize ' . self::class . ' instances.'); - } - - - /** - * 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 = 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')) { - throw new Nette\NotSupportedException('PHP extension GD is not loaded.'); - } - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/ImageColor.php b/tools/.phpstan/vendor/nette/utils/src/Utils/ImageColor.php deleted file mode 100644 index 31cf542..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/ImageColor.php +++ /dev/null @@ -1,81 +0,0 @@ -red = max(0, min(255, $red)); - $this->green = max(0, min(255, $green)); - $this->blue = max(0, min(255, $blue)); - $this->opacity = max(0, min(1, $opacity)); - } - - - /** - * Returns GD-compatible color array [R, G, B, alpha]. - * @return array{int<0, 255>, int<0, 255>, int<0, 255>, int<0, 127>} - */ - public function toRGBA(): array - { - return [ - max(0, min(255, $this->red)), - max(0, min(255, $this->green)), - max(0, min(255, $this->blue)), - max(0, min(127, (int) round(127 - $this->opacity * 127))), - ]; - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/ImageType.php b/tools/.phpstan/vendor/nette/utils/src/Utils/ImageType.php deleted file mode 100644 index 793f73a..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/ImageType.php +++ /dev/null @@ -1,25 +0,0 @@ - $iterable - */ - public static function contains(iterable $iterable, mixed $value): bool - { - foreach ($iterable as $v) { - if ($v === $value) { - return true; - } - } - return false; - } - - - /** - * Tests for the presence of key. - * @param iterable $iterable - */ - public static function containsKey(iterable $iterable, mixed $key): bool - { - foreach ($iterable as $k => $v) { - if ($k === $key) { - return true; - } - } - return false; - } - - - /** - * 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 - * @param ?callable(): E $else - * @return ($else is null ? ?V : V|E) - */ - public static function first(iterable $iterable, ?callable $predicate = null, ?callable $else = null): mixed - { - foreach ($iterable as $k => $v) { - if (!$predicate || $predicate($v, $k, $iterable)) { - return $v; - } - } - return $else ? $else() : null; - } - - - /** - * 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 - * @param ?callable(): E $else - * @return ($else is null ? ?K : K|E) - */ - public static function firstKey(iterable $iterable, ?callable $predicate = null, ?callable $else = null): mixed - { - foreach ($iterable as $k => $v) { - if (!$predicate || $predicate($v, $k, $iterable)) { - return $k; - } - } - return $else ? $else() : null; - } - - - /** - * Tests whether at least one element in the iterable passes the test implemented by the provided function. - * @template K - * @template V - * @param iterable $iterable - * @param callable(V, K, iterable): bool $predicate - */ - public static function some(iterable $iterable, callable $predicate): bool - { - foreach ($iterable as $k => $v) { - if ($predicate($v, $k, $iterable)) { - return true; - } - } - return false; - } - - - /** - * Tests whether all elements in the iterable pass the test implemented by the provided function. - * @template K - * @template V - * @param iterable $iterable - * @param callable(V, K, iterable): bool $predicate - */ - public static function every(iterable $iterable, callable $predicate): bool - { - foreach ($iterable as $k => $v) { - if (!$predicate($v, $k, $iterable)) { - return false; - } - } - return true; - } - - - /** - * Returns a generator that yields only elements matching the given $predicate. Maintains original keys. - * @template K - * @template V - * @param iterable $iterable - * @param callable(V, K, iterable): bool $predicate - * @return \Generator - */ - public static function filter(iterable $iterable, callable $predicate): \Generator - { - foreach ($iterable as $k => $v) { - if ($predicate($v, $k, $iterable)) { - yield $k => $v; - } - } - } - - - /** - * Returns a generator that transforms values by calling $transformer. Maintains original keys. - * @template K - * @template V - * @template R - * @param iterable $iterable - * @param callable(V, K, iterable): R $transformer - * @return \Generator - */ - public static function map(iterable $iterable, callable $transformer): \Generator - { - foreach ($iterable as $k => $v) { - yield $k => $transformer($v, $k, $iterable); - } - } - - - /** - * Returns a generator that transforms keys and values by calling $transformer. If it returns null, the element is skipped. - * @template K - * @template V - * @template ResK - * @template ResV - * @param iterable $iterable - * @param callable(V, K, iterable): ?array{ResK, ResV} $transformer - * @return \Generator - */ - public static function mapWithKeys(iterable $iterable, callable $transformer): \Generator - { - foreach ($iterable as $k => $v) { - $pair = $transformer($v, $k, $iterable); - if ($pair) { - yield $pair[0] => $pair[1]; - } - } - } - - - /** - * Creates a repeatable iterator from a factory function. - * The factory is called every time the iterator is iterated. - * @template K - * @template V - * @param callable(): iterable $factory - * @return \IteratorAggregate - */ - public static function repeatable(callable $factory): \IteratorAggregate - { - return new class ($factory(...)) implements \IteratorAggregate { - public function __construct( - /** @var \Closure(): iterable */ - private \Closure $factory, - ) { - } - - - public function getIterator(): \Iterator - { - return Iterables::toIterator(($this->factory)()); - } - }; - } - - - /** - * Wraps around iterator and caches its keys and values during iteration. - * This allows the data to be re-iterated multiple times. - * @template K - * @template V - * @param iterable $iterable - * @return \IteratorAggregate - */ - public static function memoize(iterable $iterable): \IteratorAggregate - { - return new class (self::toIterator($iterable)) implements \IteratorAggregate { - public function __construct( - private readonly \Iterator $iterator, - /** @var array */ - private array $cache = [], - ) { - } - - - public function getIterator(): \Generator - { - if (!$this->cache) { - $this->iterator->rewind(); - } - $i = 0; - while (true) { - if (isset($this->cache[$i])) { - [$k, $v] = $this->cache[$i]; - } elseif ($this->iterator->valid()) { - $k = $this->iterator->key(); - $v = $this->iterator->current(); - $this->iterator->next(); - $this->cache[$i] = [$k, $v]; - } else { - break; - } - yield $k => $v; - $i++; - } - } - }; - } - - - /** - * Creates an iterator from anything that is iterable. - * @template K - * @template V - * @param iterable $iterable - * @return \Iterator - */ - public static function toIterator(iterable $iterable): \Iterator - { - return match (true) { - $iterable instanceof \Iterator => $iterable, - $iterable instanceof \IteratorAggregate => self::toIterator($iterable->getIterator()), - is_array($iterable) => new \ArrayIterator($iterable), - default => throw new Nette\ShouldNotHappenException, - }; - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Json.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Json.php deleted file mode 100644 index 8a5a62e..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Json.php +++ /dev/null @@ -1,84 +0,0 @@ -getProperties(\ReflectionProperty::IS_PUBLIC), fn($p) => !$p->isStatic()), - self::parseFullDoc($rc, '~^[ \t*]*@property(?:-read)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m'), - ), $name); - throw new MemberAccessException("Cannot read an undeclared property $class::\$$name" . ($hint ? ", did you mean \$$hint?" : '.')); - } - - - /** - * @return never - * @throws MemberAccessException - */ - public static function strictSet(string $class, string $name): void - { - $rc = new \ReflectionClass($class); - $hint = self::getSuggestion(array_merge( - array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), fn($p) => !$p->isStatic()), - self::parseFullDoc($rc, '~^[ \t*]*@property(?:-write)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m'), - ), $name); - throw new MemberAccessException("Cannot write to an undeclared property $class::\$$name" . ($hint ? ", did you mean \$$hint?" : '.')); - } - - - /** - * @return never - * @throws MemberAccessException - */ - public static function strictCall(string $class, string $method, array $additionalMethods = []): void - { - $trace = debug_backtrace(0, 3); // suppose this method is called from __call() - $context = ($trace[1]['function'] ?? null) === '__call' - ? ($trace[2]['class'] ?? null) - : null; - - if ($context && is_a($class, $context, true) && method_exists($context, $method)) { // called parent::$method() - $class = get_parent_class($context); - } - - if (method_exists($class, $method)) { // insufficient visibility - $rm = new \ReflectionMethod($class, $method); - $visibility = $rm->isPrivate() - ? 'private ' - : ($rm->isProtected() ? 'protected ' : ''); - throw new MemberAccessException("Call to {$visibility}method $class::$method() from " . ($context ? "scope $context." : 'global scope.')); - - } else { - $hint = self::getSuggestion(array_merge( - get_class_methods($class), - self::parseFullDoc(new \ReflectionClass($class), '~^[ \t*]*@method[ \t]+(?:static[ \t]+)?(?:\S+[ \t]+)??(\w+)\(~m'), - $additionalMethods, - ), $method); - throw new MemberAccessException("Call to undefined method $class::$method()" . ($hint ? ", did you mean $hint()?" : '.')); - } - } - - - /** - * @return never - * @throws MemberAccessException - */ - public static function strictStaticCall(string $class, string $method): void - { - $trace = debug_backtrace(0, 3); // suppose this method is called from __callStatic() - $context = ($trace[1]['function'] ?? null) === '__callStatic' - ? ($trace[2]['class'] ?? null) - : null; - - if ($context && is_a($class, $context, true) && method_exists($context, $method)) { // called parent::$method() - $class = get_parent_class($context); - } - - if (method_exists($class, $method)) { // insufficient visibility - $rm = new \ReflectionMethod($class, $method); - $visibility = $rm->isPrivate() - ? 'private ' - : ($rm->isProtected() ? 'protected ' : ''); - throw new MemberAccessException("Call to {$visibility}method $class::$method() from " . ($context ? "scope $context." : 'global scope.')); - - } else { - $hint = self::getSuggestion( - array_filter((new \ReflectionClass($class))->getMethods(\ReflectionMethod::IS_PUBLIC), fn($m) => $m->isStatic()), - $method, - ); - throw new MemberAccessException("Call to undefined static method $class::$method()" . ($hint ? ", did you mean $hint()?" : '.')); - } - } - - - /** - * Returns array of magic properties defined by annotation @property. - * @return array of [name => bit mask] - * @internal - */ - public static function getMagicProperties(string $class): array - { - static $cache; - $props = &$cache[$class]; - if ($props !== null) { - return $props; - } - - $rc = new \ReflectionClass($class); - preg_match_all( - '~^ [ \t*]* @property(|-read|-write|-deprecated) [ \t]+ [^\s$]+ [ \t]+ \$ (\w+) ()~mx', - (string) $rc->getDocComment(), - $matches, - PREG_SET_ORDER, - ); - - $props = []; - foreach ($matches as [, $type, $name]) { - $uname = ucfirst($name); - $write = $type !== '-read' - && $rc->hasMethod($nm = 'set' . $uname) - && ($rm = $rc->getMethod($nm))->name === $nm && !$rm->isPrivate() && !$rm->isStatic(); - $read = $type !== '-write' - && ($rc->hasMethod($nm = 'get' . $uname) || $rc->hasMethod($nm = 'is' . $uname)) - && ($rm = $rc->getMethod($nm))->name === $nm && !$rm->isPrivate() && !$rm->isStatic(); - - if ($read || $write) { - $props[$name] = $read << 0 | ($nm[0] === 'g') << 1 | $rm->returnsReference() << 2 | $write << 3 | ($type === '-deprecated') << 4; - } - } - - foreach ($rc->getTraits() as $trait) { - $props += self::getMagicProperties($trait->name); - } - - if ($parent = get_parent_class($class)) { - $props += self::getMagicProperties($parent); - } - - return $props; - } - - - /** - * Finds the best suggestion (for 8-bit encoding). - * @param (\ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionClass|\ReflectionProperty|string)[] $possibilities - * @internal - */ - public static function getSuggestion(array $possibilities, string $value): ?string - { - $norm = preg_replace($re = '#^(get|set|has|is|add)(?=[A-Z])#', '+', $value); - $best = null; - $min = (strlen($value) / 4 + 1) * 10 + .1; - foreach (array_unique($possibilities, SORT_REGULAR) as $item) { - $item = $item instanceof \Reflector ? $item->name : $item; - if ($item !== $value && ( - ($len = levenshtein($item, $value, 10, 11, 10)) < $min - || ($len = levenshtein(preg_replace($re, '*', $item), $norm, 10, 11, 10)) < $min - )) { - $min = $len; - $best = $item; - } - } - - return $best; - } - - - private static function parseFullDoc(\ReflectionClass $rc, string $pattern): array - { - do { - $doc[] = $rc->getDocComment(); - $traits = $rc->getTraits(); - while ($trait = array_pop($traits)) { - $doc[] = $trait->getDocComment(); - $traits += $trait->getTraits(); - } - } while ($rc = $rc->getParentClass()); - - return preg_match_all($pattern, implode('', $doc), $m) ? $m[1] : []; - } - - - /** - * Checks if the public non-static property exists. - * Returns 'event' if the property exists and has event like name - * @internal - */ - public static function hasProperty(string $class, string $name): bool|string - { - static $cache; - $prop = &$cache[$class][$name]; - if ($prop === null) { - $prop = false; - try { - $rp = new \ReflectionProperty($class, $name); - if ($rp->isPublic() && !$rp->isStatic()) { - $prop = $name >= 'onA' && $name < 'on_' ? 'event' : true; - } - } catch (\ReflectionException $e) { - } - } - - return $prop; - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Paginator.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Paginator.php deleted file mode 100644 index e95df0d..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Paginator.php +++ /dev/null @@ -1,210 +0,0 @@ - $firstItemOnPage - * @property-read int<0,max> $lastItemOnPage - * @property int $base - * @property-read bool $first - * @property-read bool $last - * @property-read ?int<0,max> $pageCount - * @property positive-int $itemsPerPage - * @property ?int<0,max> $itemCount - * @property-read int<0,max> $offset - * @property-read ?int<0,max> $countdownOffset - * @property-read int<0,max> $length - */ -class Paginator -{ - use Nette\SmartObject; - - private int $base = 1; - - /** @var positive-int */ - private int $itemsPerPage = 1; - - private int $page = 1; - - /** @var ?int<0, max> */ - private ?int $itemCount = null; - - - public function setPage(int $page): static - { - $this->page = $page; - return $this; - } - - - public function getPage(): int - { - return $this->base + $this->getPageIndex(); - } - - - public function getFirstPage(): int - { - return $this->base; - } - - - public function getLastPage(): ?int - { - return $this->itemCount === null - ? null - : $this->base + max(0, $this->getPageCount() - 1); - } - - - /** - * 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 - { - return $this->itemCount !== 0 - ? $this->offset + 1 - : 0; - } - - - /** - * Returns the 1-based index of the last item on the current page. - * @return int<0, max> - */ - public function getLastItemOnPage(): int - { - return $this->offset + $this->length; - } - - - public function setBase(int $base): static - { - $this->base = $base; - return $this; - } - - - public function getBase(): int - { - return $this->base; - } - - - /** - * Returns zero-based page number. - * @return int<0, max> - */ - protected function getPageIndex(): int - { - $index = max(0, $this->page - $this->base); - return $this->itemCount === null - ? $index - : min($index, max(0, $this->getPageCount() - 1)); - } - - - public function isFirst(): bool - { - return $this->getPageIndex() === 0; - } - - - public function isLast(): bool - { - return $this->itemCount === null - ? false - : $this->getPageIndex() >= $this->getPageCount() - 1; - } - - - /** - * @return ?int<0, max> - */ - public function getPageCount(): ?int - { - return $this->itemCount === null - ? null - : max(0, (int) ceil($this->itemCount / $this->itemsPerPage)); - } - - - public function setItemsPerPage(int $itemsPerPage): static - { - $this->itemsPerPage = max(1, $itemsPerPage); - return $this; - } - - - /** - * @return positive-int - */ - public function getItemsPerPage(): int - { - return $this->itemsPerPage; - } - - - public function setItemCount(?int $itemCount = null): static - { - $this->itemCount = $itemCount === null ? null : max(0, $itemCount); - return $this; - } - - - /** - * @return ?int<0, max> - */ - public function getItemCount(): ?int - { - return $this->itemCount; - } - - - /** - * Returns the absolute index of the first item on current page. - * @return int<0, max> - */ - public function getOffset(): int - { - return $this->getPageIndex() * $this->itemsPerPage; - } - - - /** - * Returns the absolute index of the first item on current page in countdown paging. - * @return ?int<0, max> - */ - public function getCountdownOffset(): ?int - { - return $this->itemCount === null - ? null - : max(0, $this->itemCount - ($this->getPageIndex() + 1) * $this->itemsPerPage); - } - - - /** - * Returns the number of items on current page. - * @return int<0, max> - */ - public function getLength(): int - { - return $this->itemCount === null - ? $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 deleted file mode 100644 index 8ec0a5b..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Process.php +++ /dev/null @@ -1,507 +0,0 @@ - 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 deleted file mode 100644 index f3ec874..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Random.php +++ /dev/null @@ -1,52 +0,0 @@ - implode('', range($m[0][0], $m[0][2])), - $charlist, - ); - $charlist = count_chars($charlist, mode: 3); - $chLen = strlen($charlist); - - if ($length < 1) { - throw new Nette\InvalidArgumentException('Length must be greater than zero.'); - } elseif ($chLen < 2) { - throw new Nette\InvalidArgumentException('Character list must contain at least two chars.'); - } elseif (PHP_VERSION_ID >= 80300) { - return (new Randomizer)->getBytesFromString($charlist, $length); - } - - $res = ''; - for ($i = 0; $i < $length; $i++) { - $res .= $charlist[random_int(0, $chLen - 1)]; - } - - return $res; - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Reflection.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Reflection.php deleted file mode 100644 index 623537b..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Reflection.php +++ /dev/null @@ -1,335 +0,0 @@ -isDefaultValueConstant()) { - $const = $orig = $param->getDefaultValueConstantName() ?? throw new Nette\ShouldNotHappenException; - $pair = explode('::', $const); - if (isset($pair[1])) { - $pair[0] = Type::resolve($pair[0], $param); - try { - $rcc = new \ReflectionClassConstant($pair[0], $pair[1]); - } catch (\ReflectionException $e) { - $name = self::toString($param); - throw new \ReflectionException("Unable to resolve constant $orig used as default value of $name.", 0, $e); - } - - return $rcc->getValue(); - - } elseif (!defined($const)) { - $const = substr((string) strrchr($const, '\\'), 1); - if (!defined($const)) { - $name = self::toString($param); - throw new \ReflectionException("Unable to resolve constant $orig used as default value of $name."); - } - } - - return constant($const); - } - - return $param->getDefaultValue(); - } - - - /** - * 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 - { - foreach ($prop->getDeclaringClass()->getTraits() as $trait) { - if ($trait->hasProperty($prop->name) - // doc-comment guessing as workaround for insufficient PHP reflection - && $trait->getProperty($prop->name)->getDocComment() === $prop->getDocComment() - ) { - return self::getPropertyDeclaringClass($trait->getProperty($prop->name)); - } - } - - return $prop->getDeclaringClass(); - } - - - /** - * Returns a reflection of a method that contains a declaration of $method. - * Usually, each method is its own declaration, but the body of the method can also be in the trait and under a different name. - */ - public static function getMethodDeclaringMethod(\ReflectionMethod $method): \ReflectionMethod - { - // file & line guessing as workaround for insufficient PHP reflection - $decl = $method->getDeclaringClass(); - if ($decl->getFileName() === $method->getFileName() - && $decl->getStartLine() <= $method->getStartLine() - && $decl->getEndLine() >= $method->getEndLine() - ) { - return $method; - } - - $hash = [$method->getFileName(), $method->getStartLine(), $method->getEndLine()]; - if (($alias = $decl->getTraitAliases()[$method->name] ?? null) - && ($m = new \ReflectionMethod(...explode('::', $alias, 2))) - && $hash === [$m->getFileName(), $m->getStartLine(), $m->getEndLine()] - ) { - return self::getMethodDeclaringMethod($m); - } - - foreach ($decl->getTraits() as $trait) { - if ($trait->hasMethod($method->name) - && ($m = $trait->getMethod($method->name)) - && $hash === [$m->getFileName(), $m->getStartLine(), $m->getEndLine()] - ) { - return self::getMethodDeclaringMethod($m); - } - } - - return $method; - } - - - /** - * Finds out if reflection has access to PHPdoc comments. Comments may not be available due to the opcode cache. - */ - public static function areCommentsAvailable(): bool - { - static $res; - return $res ?? $res = (bool) (new \ReflectionMethod(self::class, __FUNCTION__))->getDocComment(); - } - - - /** - * Returns a human-readable string representation of a reflection object. - */ - public static function toString(\Reflector $ref): string - { - if ($ref instanceof \ReflectionClass) { - return $ref->name; - } elseif ($ref instanceof \ReflectionMethod) { - return $ref->getDeclaringClass()->name . '::' . $ref->name . '()'; - } elseif ($ref instanceof \ReflectionFunction) { - return $ref->isAnonymous() ? '{closure}()' : $ref->name . '()'; - } elseif ($ref instanceof \ReflectionProperty) { - return self::getPropertyDeclaringClass($ref)->name . '::$' . $ref->name; - } elseif ($ref instanceof \ReflectionParameter) { - return '$' . $ref->name . ' in ' . self::toString($ref->getDeclaringFunction()); - } else { - throw new Nette\InvalidArgumentException; - } - } - - - /** - * 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 - { - $lower = strtolower($name); - if (empty($name)) { - throw new Nette\InvalidArgumentException('Class name must not be empty.'); - - } elseif (Validators::isBuiltinType($lower)) { - return $lower; - - } elseif ($lower === 'self' || $lower === 'static') { - return $context->name; - - } elseif ($lower === 'parent') { - return $context->getParentClass() - ? $context->getParentClass()->name - : 'parent'; - - } elseif ($name[0] === '\\') { // fully qualified name - return ltrim($name, '\\'); - } - - $uses = self::getUseStatements($context); - $parts = explode('\\', $name, 2); - if (isset($uses[$parts[0]])) { - $parts[0] = $uses[$parts[0]]; - return implode('\\', $parts); - - } elseif ($context->inNamespace()) { - return $context->getNamespaceName() . '\\' . $name; - - } else { - return $name; - } - } - - - /** - * 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()) { - throw new Nette\NotImplementedException('Anonymous classes are not supported.'); - } - - static $cache = []; - if (!isset($cache[$name = $class->name])) { - if ($class->isInternal()) { - $cache[$name] = []; - } else { - $code = (string) file_get_contents((string) $class->getFileName()); - $cache = self::parseUseStatements($code, $name) + $cache; - } - } - - return $cache[$name]; - } - - - /** - * Parses PHP code to [class => [alias => class, ...]] - * @return array> - */ - private static function parseUseStatements(string $code, ?string $forClass = null): array - { - try { - $tokens = \PhpToken::tokenize($code, TOKEN_PARSE); - } catch (\ParseError $e) { - trigger_error($e->getMessage(), E_USER_NOTICE); - $tokens = []; - } - - $namespace = $class = null; - $classLevel = $level = 0; - $res = $uses = []; - - $nameTokens = [T_STRING, T_NS_SEPARATOR, T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED]; - - while ($token = current($tokens)) { - next($tokens); - switch ($token->id) { - case T_NAMESPACE: - $namespace = ltrim(self::fetch($tokens, $nameTokens) . '\\', '\\'); - $uses = []; - break; - - case T_CLASS: - case T_INTERFACE: - case T_TRAIT: - case T_ENUM: - if ($name = self::fetch($tokens, T_STRING)) { - $class = $namespace . $name; - $classLevel = $level + 1; - $res[$class] = $uses; - if ($class === $forClass) { - return $res; - } - } - - break; - - case T_USE: - while (!$class && ($name = self::fetch($tokens, $nameTokens))) { - $name = ltrim($name, '\\'); - if (self::fetch($tokens, '{')) { - while ($suffix = self::fetch($tokens, $nameTokens)) { - 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; - } - - if (!self::fetch($tokens, ',')) { - break; - } - } - } elseif (self::fetch($tokens, T_AS) && ($alias = self::fetch($tokens, T_STRING))) { - $uses[$alias] = $name; - - } else { - $tmp = explode('\\', $name); - $uses[end($tmp)] = $name; - } - - if (!self::fetch($tokens, ',')) { - break; - } - } - - break; - - case T_CURLY_OPEN: - case T_DOLLAR_OPEN_CURLY_BRACES: - case ord('{'): - $level++; - break; - - case ord('}'): - if ($level === $classLevel) { - $class = $classLevel = 0; - } - - $level--; - } - } - - return $res; - } - - - /** - * @param \PhpToken[] $tokens - * @param string|int|int[] $take - */ - private static function fetch(array &$tokens, string|int|array $take): ?string - { - $res = null; - while ($token = current($tokens)) { - if ($token->is($take)) { - $res .= $token->text; - } elseif (!$token->is([T_DOC_COMMENT, T_WHITESPACE, T_COMMENT])) { - break; - } - - next($tokens); - } - - return $res; - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/ReflectionMethod.php b/tools/.phpstan/vendor/nette/utils/src/Utils/ReflectionMethod.php deleted file mode 100644 index fe2159c..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/ReflectionMethod.php +++ /dev/null @@ -1,39 +0,0 @@ - */ - 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, '::')) { - [$objectOrMethod, $method] = explode('::', $objectOrMethod, 2); - } - parent::__construct($objectOrMethod, $method); - $this->originalClass = new \ReflectionClass($objectOrMethod); - } - - - /** @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 deleted file mode 100644 index 59656ea..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Strings.php +++ /dev/null @@ -1,730 +0,0 @@ -= 0xD800 && $code <= 0xDFFF) || $code > 0x10FFFF) { - throw new Nette\InvalidArgumentException('Code point must be in range 0x0 to 0xD7FF or 0xE000 to 0x10FFFF.'); - } elseif (!extension_loaded('iconv')) { - throw new Nette\NotSupportedException(__METHOD__ . '() requires ICONV extension that is not loaded.'); - } - - $res = iconv('UTF-32BE', 'UTF-8//IGNORE', pack('N', $code)); - return $res === false ? throw new Nette\ShouldNotHappenException : $res; - } - - - /** - * Returns a code point of specific character in UTF-8 (number in range 0x0000..D7FF or 0xE000..10FFFF). - */ - public static function ord(string $c): int - { - if (!extension_loaded('iconv')) { - throw new Nette\NotSupportedException(__METHOD__ . '() requires ICONV extension that is not loaded.'); - } - - $tmp = iconv('UTF-8', 'UTF-32BE//IGNORE', $c); - if ($tmp === false || $tmp === '') { - throw new Nette\InvalidArgumentException('Invalid UTF-8 character "' . ($c === '' ? '' : '\x' . strtoupper(bin2hex($c))) . '".'); - } - - return unpack('N', $tmp)[1] ?? throw new Nette\ShouldNotHappenException; - } - - - /** - * @deprecated use str_starts_with() - */ - public static function startsWith(string $haystack, string $needle): bool - { - return str_starts_with($haystack, $needle); - } - - - /** - * @deprecated use str_ends_with() - */ - public static function endsWith(string $haystack, string $needle): bool - { - return str_ends_with($haystack, $needle); - } - - - /** - * @deprecated use str_contains() - */ - public static function contains(string $haystack, string $needle): bool - { - return str_contains($haystack, $needle); - } - - - /** - * Returns a part of UTF-8 string specified by starting position and length. If start is negative, - * the returned string will start at the start'th character from the end of string. - */ - public static function substring(string $s, int $start, ?int $length = null): string - { - if (function_exists('mb_substr')) { - return mb_substr($s, $start, $length, 'UTF-8'); // MB is much faster - } elseif (!extension_loaded('iconv')) { - throw new Nette\NotSupportedException(__METHOD__ . '() requires extension ICONV or MBSTRING, neither is loaded.'); - } elseif ($length === null) { - $length = self::length($s); - } elseif ($start < 0 && $length < 0) { - $start += self::length($s); // unifies iconv_substr behavior with mb_substr - } - - $res = iconv_substr($s, $start, $length, 'UTF-8'); - return $res === false ? throw new Nette\InvalidStateException('iconv_substr() failed.') : $res; - } - - - /** - * Removes control characters, normalizes line breaks to `\n`, removes leading and trailing blank lines, - * trims end spaces on lines, normalizes UTF-8 to the normal form of NFC. - */ - public static function normalize(string $s): string - { - // convert to compressed normal form (NFC) - if (class_exists('Normalizer', autoload: false) && ($n = \Normalizer::normalize($s, \Normalizer::FORM_C)) !== false) { - $s = $n; - } - - $s = self::unixNewLines($s); - - // remove control characters; leave \t + \n - $s = self::pcre('preg_replace', ['#[\x00-\x08\x0B-\x1F\x7F-\x9F]+#u', '', $s]); - - // right trim - $s = self::pcre('preg_replace', ['#[\t ]+$#m', '', $s]); - - // leading and trailing blank lines - $s = trim($s, "\n"); - - return $s; - } - - - /** @deprecated use Strings::unixNewLines() */ - public static function normalizeNewLines(string $s): string - { - return self::unixNewLines($s); - } - - - /** - * Converts line endings to \n used on Unix-like systems. - * Line endings are: \n, \r, \r\n, U+2028 line separator, U+2029 paragraph separator. - */ - public static function unixNewLines(string $s): string - { - return preg_replace("~\r\n?|\u{2028}|\u{2029}~", "\n", $s); - } - - - /** - * Converts line endings to platform-specific, i.e. \r\n on Windows and \n elsewhere. - * Line endings are: \n, \r, \r\n, U+2028 line separator, U+2029 paragraph separator. - */ - public static function platformNewLines(string $s): string - { - return preg_replace("~\r\n?|\n|\u{2028}|\u{2029}~", PHP_EOL, $s); - } - - - /** - * Converts UTF-8 string to ASCII, ie removes diacritics etc. - */ - public static function toAscii(string $s): string - { - if (!extension_loaded('intl')) { - throw new Nette\NotSupportedException(__METHOD__ . '() requires INTL extension that is not loaded.'); - } - - $iconv = defined('ICONV_IMPL') ? trim(ICONV_IMPL, '"\'') : null; - - // remove control characters and check UTF-8 validity - $s = self::pcre('preg_replace', ['#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{2FF}\x{370}-\x{10FFFF}]#u', '', $s]); - - // transliteration (by Transliterator and iconv) is not optimal, replace some characters directly - $s = strtr($s, ["\u{201E}" => '"', "\u{201C}" => '"', "\u{201D}" => '"', "\u{201A}" => "'", "\u{2018}" => "'", "\u{2019}" => "'", "\u{B0}" => '^', "\u{42F}" => 'Ya', "\u{44F}" => 'ya', "\u{42E}" => 'Yu', "\u{44E}" => 'yu', "\u{c4}" => 'Ae', "\u{d6}" => 'Oe', "\u{dc}" => 'Ue', "\u{1e9e}" => 'Ss', "\u{e4}" => 'ae', "\u{f6}" => 'oe', "\u{fc}" => 'ue', "\u{df}" => 'ss']); // „ “ ” ‚ ‘ ’ ° Я я Ю ю Ä Ö Ü ẞ ä ö ü ß - if ($iconv !== 'libiconv') { - $s = strtr($s, ["\u{AE}" => '(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) - ?? 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 - } - - return $s; - } - - - /** - * Modifies the UTF-8 string to the form used in the URL, ie removes diacritics and replaces all characters - * except letters of the English alphabet and numbers with a hyphens. - */ - public static function webalize(string $s, ?string $charlist = null, bool $lower = true): string - { - $s = self::toAscii($s); - if ($lower) { - $s = strtolower($s); - } - - $s = self::pcre('preg_replace', ['#[^a-z0-9' . ($charlist !== null ? preg_quote($charlist, '#') : '') . ']+#i', '-', $s]); - $s = trim($s, '-'); - return $s; - } - - - /** - * Truncates a UTF-8 string to given maximal length, while trying not to split whole words. Only if the string is truncated, - * an ellipsis (or something else set with third argument) is appended to the string. - */ - public static function truncate(string $s, int $maxLen, string $append = "\u{2026}"): string - { - if (self::length($s) > $maxLen) { - $maxLen -= self::length($append); - if ($maxLen < 1) { - return $append; - - } elseif ($matches = self::match($s, '#^.{1,' . $maxLen . '}(?=[\s\x00-/:-@\[-`{-~])#us')) { - return $matches[0] . $append; - - } else { - return self::substring($s, 0, $maxLen) . $append; - } - } - - return $s; - } - - - /** - * Indents a multiline text from the left. Second argument sets how many indentation chars should be used, - * while the indent itself is the third argument (*tab* by default). - */ - public static function indent(string $s, int $level = 1, string $chars = "\t"): string - { - if ($level > 0) { - $s = self::replace($s, '#(?:^|[\r\n]+)(?=[^\r\n])#', '$0' . str_repeat($chars, $level)); - } - - return $s; - } - - - /** - * Converts all characters of UTF-8 string to lower case. - */ - public static function lower(string $s): string - { - return mb_strtolower($s, 'UTF-8'); - } - - - /** - * Converts the first character of a UTF-8 string to lower case and leaves the other characters unchanged. - */ - public static function firstLower(string $s): string - { - return self::lower(self::substring($s, 0, 1)) . self::substring($s, 1); - } - - - /** - * Converts all characters of a UTF-8 string to upper case. - */ - public static function upper(string $s): string - { - return mb_strtoupper($s, 'UTF-8'); - } - - - /** - * Converts the first character of a UTF-8 string to upper case and leaves the other characters unchanged. - */ - public static function firstUpper(string $s): string - { - return self::upper(self::substring($s, 0, 1)) . self::substring($s, 1); - } - - - /** - * Converts the first character of every word of a UTF-8 string to upper case and the others to lower case. - */ - public static function capitalize(string $s): string - { - return mb_convert_case($s, MB_CASE_TITLE, 'UTF-8'); - } - - - /** - * Compares two UTF-8 strings or their parts, without taking character case into account. If length is null, whole strings are compared, - * if it is negative, the corresponding number of characters from the end of the strings is compared, - * otherwise the appropriate number of characters from the beginning is compared. - */ - public static function compare(string $left, string $right, ?int $length = null): bool - { - 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 - } - - if ($length < 0) { - $left = self::substring($left, $length, -$length); - $right = self::substring($right, $length, -$length); - } elseif ($length !== null) { - $left = self::substring($left, 0, $length); - $right = self::substring($right, 0, $length); - } - - return self::lower($left) === self::lower($right); - } - - - /** - * Finds the common prefix of strings or returns empty string if the prefix was not found. - * @param string[] $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]) { - while ($i && $first[$i - 1] >= "\x80" && $first[$i] >= "\x80" && $first[$i] < "\xC0") { - $i--; - } - - return substr($first, 0, $i); - } - } - } - - return $first; - } - - - /** - * Returns number of characters (not bytes) in UTF-8 string. - * That is the number of Unicode code points which may differ from the number of graphemes. - */ - public static function length(string $s): int - { - return match (true) { - extension_loaded('mbstring') => (int) mb_strlen($s, 'UTF-8'), - extension_loaded('iconv') => (int) iconv_strlen($s, 'UTF-8'), - default => strlen(@utf8_decode($s)), // deprecated - }; - } - - - /** - * Removes all left and right side spaces (or the characters passed as second argument) from a UTF-8 encoded string. - */ - public static function trim(string $s, string $charlist = self::TrimCharacters): string - { - $charlist = preg_quote($charlist, '#'); - return self::replace($s, '#^[' . $charlist . ']+|[' . $charlist . ']+$#Du', ''); - } - - - /** - * Pads a UTF-8 string to given length by prepending the $pad string to the beginning. - * @param non-empty-string $pad - */ - public static function padLeft(string $s, int $length, string $pad = ' '): string - { - $length = max(0, $length - self::length($s)); - $padLen = self::length($pad); - return str_repeat($pad, (int) ($length / $padLen)) . self::substring($pad, 0, $length % $padLen) . $s; - } - - - /** - * Pads UTF-8 string to given length by appending the $pad string to the end. - * @param non-empty-string $pad - */ - public static function padRight(string $s, int $length, string $pad = ' '): string - { - $length = max(0, $length - self::length($s)); - $padLen = self::length($pad); - return $s . str_repeat($pad, (int) ($length / $padLen)) . self::substring($pad, 0, $length % $padLen); - } - - - /** - * Reverses UTF-8 string. - */ - public static function reverse(string $s): string - { - if (!extension_loaded('iconv')) { - throw new Nette\NotSupportedException(__METHOD__ . '() requires ICONV extension that is not loaded.'); - } - - $tmp = iconv('UTF-8', 'UTF-32BE', $s); - return $tmp === false - ? throw new Nette\InvalidStateException('iconv() failed.') - : (string) iconv('UTF-32LE', 'UTF-8', strrev($tmp)); - } - - - /** - * Returns part of $haystack before $nth occurence of $needle or returns null if the needle was not found. - * Negative value means searching from the end. - */ - public static function before(string $haystack, string $needle, int $nth = 1): ?string - { - $pos = self::pos($haystack, $needle, $nth); - return $pos === null - ? null - : substr($haystack, 0, $pos); - } - - - /** - * Returns part of $haystack after $nth occurence of $needle or returns null if the needle was not found. - * Negative value means searching from the end. - */ - public static function after(string $haystack, string $needle, int $nth = 1): ?string - { - $pos = self::pos($haystack, $needle, $nth); - return $pos === null - ? null - : substr($haystack, $pos + strlen($needle)); - } - - - /** - * Returns position in characters of $nth occurence of $needle in $haystack or null if the $needle was not found. - * Negative value of `$nth` means searching from the end. - */ - public static function indexOf(string $haystack, string $needle, int $nth = 1): ?int - { - $pos = self::pos($haystack, $needle, $nth); - return $pos === null - ? null - : self::length(substr($haystack, 0, $pos)); - } - - - /** - * Returns position in characters of $nth occurence of $needle in $haystack or null if the needle was not found. - */ - private static function pos(string $haystack, string $needle, int $nth = 1): ?int - { - if (!$nth) { - return null; - } elseif ($nth > 0) { - if ($needle === '') { - return 0; - } - - $pos = 0; - while (($pos = strpos($haystack, $needle, $pos)) !== false && --$nth) { - $pos++; - } - } else { - $len = strlen($haystack); - if ($needle === '') { - return $len; - } elseif ($len === 0) { - return null; - } - - $pos = $len - 1; - while (($pos = strrpos($haystack, $needle, $pos - $len)) !== false && ++$nth) { - $pos--; - } - } - - return Helpers::falseToNull($pos); - } - - - /** - * 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, - #[Language('RegExp')] - string $pattern, - bool|int $captureOffset = false, - bool $skipEmpty = false, - int $limit = -1, - bool $utf8 = false, - ): array - { - $flags = is_int($captureOffset) // back compatibility - ? $captureOffset - : ($captureOffset ? PREG_SPLIT_OFFSET_CAPTURE : 0) | ($skipEmpty ? PREG_SPLIT_NO_EMPTY : 0); - - $pattern .= $utf8 ? 'u' : ''; - $m = self::pcre('preg_split', [$pattern, $subject, $limit, $flags | PREG_SPLIT_DELIM_CAPTURE]); - return $utf8 && $captureOffset - ? self::bytesToChars($subject, [$m])[0] - : $m; - } - - - /** - * 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, - #[Language('RegExp')] - string $pattern, - bool|int $captureOffset = false, - int $offset = 0, - bool $unmatchedAsNull = false, - bool $utf8 = false, - ): ?array - { - $flags = is_int($captureOffset) // back compatibility - ? $captureOffset - : ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0); - - if ($utf8) { - $offset = strlen(self::substring($subject, 0, $offset)); - $pattern .= 'u'; - } - - $m = []; - if ($offset > strlen($subject)) { - return null; - } elseif (!self::pcre('preg_match', [$pattern, $subject, &$m, $flags, $offset])) { - return null; - } elseif ($utf8 && $captureOffset) { - return self::bytesToChars($subject, [$m])[0]; - } else { - return $m; - } - } - - - /** - * 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, - #[Language('RegExp')] - string $pattern, - bool|int $captureOffset = false, - int $offset = 0, - bool $unmatchedAsNull = false, - bool $patternOrder = false, - bool $utf8 = false, - bool $lazy = false, - ): array|\Generator - { - if ($utf8) { - $offset = strlen(self::substring($subject, 0, $offset)); - $pattern .= 'u'; - } - - if ($lazy) { - $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); - } elseif ($utf8) { - $m = self::bytesToChars($subject, [$m])[0]; - } - yield $counter++ => $m; - } - })(); - } - - if ($offset > strlen($subject)) { - return []; - } - - $flags = is_int($captureOffset) // back compatibility - ? $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), - $offset, - ]); - return $utf8 && $captureOffset - ? self::bytesToChars($subject, $m) - : $m; - } - - - /** - * 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, - #[Language('RegExp')] - string|array $pattern, - string|callable $replacement = '', - int $limit = -1, - bool $captureOffset = false, - bool $unmatchedAsNull = false, - bool $utf8 = false, - ): string - { - if (is_object($replacement) || is_array($replacement)) { - if (!is_callable($replacement, false, $textual)) { - throw new Nette\InvalidStateException("Callback '$textual' is not callable."); - } - - $flags = ($captureOffset ? PREG_OFFSET_CAPTURE : 0) | ($unmatchedAsNull ? PREG_UNMATCHED_AS_NULL : 0); - if ($utf8) { - $pattern = is_array($pattern) ? array_map(fn($item) => $item . 'u', $pattern) : $pattern . 'u'; - if ($captureOffset) { - $replacement = fn($m) => $replacement(self::bytesToChars($subject, [$m])[0]); - } - } - - return self::pcre('preg_replace_callback', [$pattern, $replacement, $subject, $limit, 0, $flags]); - - } elseif (is_array($pattern) && is_string(key($pattern))) { - $replacement = array_values($pattern); - $pattern = array_keys($pattern); - } - - if ($utf8) { - $pattern = array_map(fn($item) => $item . 'u', (array) $pattern); - } - - return self::pcre('preg_replace', [$pattern, $replacement, $subject, $limit]); - } - - - /** - * @param list> $groups - * @return list> - */ - private static function bytesToChars(string $s, array $groups): array - { - $lastBytes = $lastChars = 0; - foreach ($groups as &$matches) { - foreach ($matches as &$match) { - if ($match[1] > $lastBytes) { - $lastChars += self::length(substr($s, $lastBytes, $match[1] - $lastBytes)); - } elseif ($match[1] < $lastBytes) { - $lastChars -= self::length(substr($s, $match[1], $lastBytes - $match[1])); - } - - $lastBytes = $match[1]; - $match[1] = $lastChars; - } - } - - return $groups; - } - - - /** - * @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 - throw new RegexpException($message . ' in pattern: ' . implode(' or ', (array) $args[0])); - }); - - 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'], strict: true)) - ) { - throw new RegexpException(preg_last_error_msg() - . ' (pattern: ' . implode(' or ', (array) $args[0]) . ')', $code); - } - - return $res; - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/Type.php b/tools/.phpstan/vendor/nette/utils/src/Utils/Type.php deleted file mode 100644 index 329475c..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Type.php +++ /dev/null @@ -1,314 +0,0 @@ - */ - private array $types; - private ?string $singleName; - private string $kind; // | & - - - /** - * Creates a Type object based on reflection. Resolves self, static and parent to the actual class name. - * If the subject has no type, it returns null. - */ - public static function fromReflection( - \ReflectionFunctionAbstract|\ReflectionParameter|\ReflectionProperty $reflection, - ): ?self - { - $type = $reflection instanceof \ReflectionFunctionAbstract - ? $reflection->getReturnType() ?? ($reflection instanceof \ReflectionMethod ? $reflection->getTentativeReturnType() : null) - : $reflection->getType(); - - return $type ? self::fromReflectionType($type, $reflection, asObject: true) : null; - } - - - /** @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); - return $asObject - ? new self($type->allowsNull() && $name !== 'mixed' ? [$name, 'null'] : [$name]) - : $name; - - } elseif ($type instanceof \ReflectionUnionType || $type instanceof \ReflectionIntersectionType) { - return new self( - array_map(fn($t) => self::fromReflectionType($t, $of, asObject: false), $type->getTypes()), - $type instanceof \ReflectionUnionType ? '|' : '&', - ); - - } else { - throw new Nette\InvalidStateException('Unexpected type of ' . Reflection::toString($of)); - } - } - - - /** - * Creates the Type object according to the text notation. - */ - public static function fromString(string $type): self - { - if (!Validators::isTypeDeclaration($type)) { - throw new Nette\InvalidArgumentException("Invalid type '$type'."); - } - - if ($type[0] === '?') { - return new self([substr($type, 1), 'null']); - } - - $unions = []; - foreach (explode('|', $type) as $part) { - $part = explode('&', trim($part, '()')); - $unions[] = count($part) === 1 ? $part[0] : new self($part, '&'); - } - - return count($unions) === 1 && $unions[0] instanceof self - ? $unions[0] - : new self($unions); - } - - - /** - * Creates a Type object based on the actual type of value. - */ - public static function fromValue(mixed $value): self - { - $type = get_debug_type($value); - if (is_resource($value)) { - $type = 'mixed'; - } elseif (str_ends_with($type, '@anonymous')) { - $parent = substr($type, 0, -10); - $type = $parent === 'class' ? 'object' : $parent; - } - - return new self([$type]); - } - - - /** - * Resolves 'self', 'static' and 'parent' to the actual class name. - */ - public static function resolve( - string $type, - \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 $class->name; - } elseif ($lower === 'static') { - 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, (int) $o, 1); - $types[] = '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 : ''; - } - - - public function __toString(): string - { - $multi = count($this->types) > 1; - if ($this->singleName !== null) { - return ($multi ? '?' : '') . $this->singleName; - } - - $res = []; - foreach ($this->types as $type) { - $res[] = $type instanceof self && $multi ? "($type)" : $type; - } - return implode($this->kind, $res); - } - - - /** - * Returns a union type that accepts both the current type and the given type. - */ - public function with(string|self $type): self - { - $type = is_string($type) ? self::fromString($type) : $type; - return match (true) { - $this->allows($type) => $this, - $type->allows($this) => $type, - default => new self(array_unique( - array_merge($this->isIntersection() ? [$this] : $this->types, $type->isIntersection() ? [$type] : $type->types), - SORT_REGULAR, - ), '|'), - }; - } - - - /** - * Returns the array of subtypes that make up the compound type as strings. - * @return list>> - */ - public function getNames(): array - { - return array_map(fn($t) => $t instanceof self ? $t->getNames() : $t, $this->types); - } - - - /** - * Returns the array of subtypes that make up the compound type as Type objects. - * @return list - */ - public function getTypes(): array - { - return array_map(fn($t) => $t instanceof self ? $t : new self([$t]), $this->types); - } - - - /** - * Returns the type name for simple types, otherwise null. - */ - public function getSingleName(): ?string - { - return $this->singleName; - } - - - /** - * Returns true whether it is a union type. - */ - public function isUnion(): bool - { - return $this->kind === '|'; - } - - - /** - * Returns true whether it is an intersection type. - */ - public function isIntersection(): bool - { - return $this->kind === '&'; - } - - - /** - * 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->singleName !== null; - } - - - #[\Deprecated('use isSimple()')] - public function isSingle(): bool - { - return $this->singleName !== null; - } - - - /** - * Checks whether it is a simple PHP built-in type (int, string, bool, etc.). - */ - public function isBuiltin(): bool - { - return $this->singleName !== null && Validators::isBuiltinType($this->singleName); - } - - - /** - * Checks whether it is a simple class or interface name (not a built-in type). - */ - public function isClass(): bool - { - return $this->singleName !== null && !Validators::isBuiltinType($this->singleName); - } - - - /** - * Determines if type is special class name self/parent/static. - */ - public function isClassKeyword(): bool - { - return $this->singleName !== null && Validators::isClassKeyword($this->singleName); - } - - - /** - * Checks whether a value of the given type could be assigned to this type. - */ - public function allows(string|self $type): bool - { - if ($this->types === ['mixed']) { - return true; - } - - $type = is_string($type) ? self::fromString($type) : $type; - return $type->isUnion() - ? Arrays::every($type->types, fn($t) => $this->allowsAny($t instanceof self ? $t->types : [$t])) - : $this->allowsAny($type->types); - } - - - /** @param array $givenTypes */ - private function allowsAny(array $givenTypes): bool - { - return $this->isUnion() - ? Arrays::some($this->types, fn($t) => $this->allowsAll($t instanceof self ? $t->types : [$t], $givenTypes)) - : $this->allowsAll($this->types, $givenTypes); - } - - - /** - * @param array $ourTypes - * @param array $givenTypes - */ - private function allowsAll(array $ourTypes, array $givenTypes): bool - { - return Arrays::every( - $ourTypes, - fn(string $ourType) => Arrays::some( - $givenTypes, - 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 deleted file mode 100644 index 9e7bd5b..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/Validators.php +++ /dev/null @@ -1,416 +0,0 @@ - 1, 'int' => 1, 'float' => 1, 'bool' => 1, 'array' => 1, 'object' => 1, - 'callable' => 1, 'iterable' => 1, 'void' => 1, 'null' => 1, 'mixed' => 1, 'false' => 1, - 'never' => 1, 'true' => 1, - ]; - - /** @var array */ - protected static $validators = [ - // PHP types - 'array' => 'is_array', - 'bool' => 'is_bool', - 'boolean' => 'is_bool', - 'float' => 'is_float', - 'int' => 'is_int', - 'integer' => 'is_int', - 'null' => 'is_null', - 'object' => 'is_object', - 'resource' => 'is_resource', - 'scalar' => 'is_scalar', - 'string' => 'is_string', - - // pseudo-types - 'callable' => [self::class, 'isCallable'], - 'iterable' => 'is_iterable', - 'list' => [Arrays::class, 'isList'], - 'mixed' => [self::class, 'isMixed'], - 'none' => [self::class, 'isNone'], - 'number' => [self::class, 'isNumber'], - 'numeric' => [self::class, 'isNumeric'], - 'numericint' => [self::class, 'isNumericInt'], - - // string patterns - 'alnum' => 'ctype_alnum', - 'alpha' => 'ctype_alpha', - 'digit' => 'ctype_digit', - 'lower' => 'ctype_lower', - 'pattern' => null, - 'space' => 'ctype_space', - 'unicode' => [self::class, 'isUnicode'], - 'upper' => 'ctype_upper', - 'xdigit' => 'ctype_xdigit', - - // syntax validation - 'email' => [self::class, 'isEmail'], - 'identifier' => [self::class, 'isPhpIdentifier'], - 'uri' => [self::class, 'isUri'], - 'url' => [self::class, 'isUrl'], - - // environment validation - 'class' => 'class_exists', - 'interface' => 'interface_exists', - 'directory' => 'is_dir', - 'file' => 'is_file', - 'type' => [self::class, 'isType'], - ]; - - /** @var array */ - protected static $counters = [ - 'string' => 'strlen', - 'unicode' => [Strings::class, 'length'], - 'array' => 'count', - 'list' => 'count', - 'alnum' => 'strlen', - 'alpha' => 'strlen', - 'digit' => 'strlen', - 'lower' => 'strlen', - 'space' => 'strlen', - 'upper' => 'strlen', - 'xdigit' => 'strlen', - ]; - - - /** - * Verifies that the value is of expected types separated by pipe. - * @throws AssertionException - */ - public static function assert(mixed $value, string $expected, string $label = 'variable'): void - { - if (!static::is($value, $expected)) { - $expected = str_replace(['|', ':'], [' or ', ' in range '], $expected); - $translate = ['boolean' => 'bool', 'integer' => 'int', 'double' => 'float', 'NULL' => 'null']; - $type = $translate[gettype($value)] ?? gettype($value); - if (is_int($value) || is_float($value) || (is_string($value) && strlen($value) < 40)) { - $type .= ' ' . var_export($value, return: true); - } elseif (is_object($value)) { - $type .= ' ' . $value::class; - } - - throw new AssertionException("The $label expects to be $expected, $type given."); - } - } - - - /** - * 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, - int|string $key, - ?string $expected = null, - string $label = "item '%' in array", - ): void - { - if (!array_key_exists($key, $array)) { - throw new AssertionException('Missing ' . str_replace('%', (string) $key, $label) . '.'); - - } elseif ($expected) { - static::assert($array[$key], $expected, str_replace('%', (string) $key, $label)); - } - } - - - /** - * Verifies that the value is of expected types separated by pipe. - */ - public static function is(mixed $value, string $expected): bool - { - foreach (explode('|', $expected) as $item) { - if (str_ends_with($item, '[]')) { - if (is_iterable($value) && self::everyIs($value, substr($item, 0, -2))) { - return true; - } - - continue; - } elseif (str_starts_with($item, '?')) { - $item = substr($item, 1); - if ($value === null) { - return true; - } - } - - [$type] = $item = explode(':', $item, 2); - if (isset(static::$validators[$type])) { - try { - if (!static::$validators[$type]($value)) { - continue; - } - } catch (\TypeError) { - continue; - } - } elseif ($type === 'pattern') { - if (Strings::match($value, '|^' . ($item[1] ?? '') . '$|D')) { - return true; - } - - continue; - } elseif (!$value instanceof $type) { - continue; - } - - if (isset($item[1])) { - $length = $value; - if (isset(static::$counters[$type])) { - $length = static::$counters[$type]($value); - } - - $range = explode('..', $item[1]); - if (!isset($range[1])) { - $range[1] = $range[0]; - } - - if (($range[0] !== '' && $length < $range[0]) || ($range[1] !== '' && $length > $range[1])) { - continue; - } - } - - return true; - } - - return false; - } - - - /** - * Finds whether all values are of expected types separated by pipe. - * @param iterable $values - */ - public static function everyIs(iterable $values, string $expected): bool - { - foreach ($values as $value) { - if (!static::is($value, $expected)) { - return false; - } - } - - return true; - } - - - /** - * Checks if the value is an integer or a float. - * @return ($value is int|float ? true : false) - */ - public static function isNumber(mixed $value): bool - { - return is_int($value) || is_float($value); - } - - - /** - * Checks if the value is an integer or a integer written in a string. - * @return ($value is non-empty-string ? bool : ($value is int ? true : false)) - */ - public static function isNumericInt(mixed $value): bool - { - return is_int($value) || (is_string($value) && preg_match('#^[+-]?[0-9]+$#D', $value)); - } - - - /** - * Checks if the value is a number or a number written in a string. - * @return ($value is non-empty-string ? bool : ($value is int|float ? true : false)) - */ - public static function isNumeric(mixed $value): bool - { - return is_float($value) || is_int($value) || (is_string($value) && preg_match('#^[+-]?([0-9]++\.?[0-9]*|\.[0-9]+)$#D', $value)); - } - - - /** - * Checks if the value is a syntactically correct callback. - */ - public static function isCallable(mixed $value): bool - { - return $value && is_callable($value, syntax_only: true); - } - - - /** - * Checks if the value is a valid UTF-8 string. - */ - public static function isUnicode(mixed $value): bool - { - return is_string($value) && preg_match('##u', $value); - } - - - /** - * Checks if the value is 0, '', false or null. - * @return ($value is 0|0.0|''|false|null ? true : false) - */ - public static function isNone(mixed $value): bool - { - return $value == null; // intentionally == - } - - - /** @internal */ - public static function isMixed(): bool - { - return true; - } - - - /** - * Checks if a variable is a zero-based integer indexed array. - * @deprecated use Nette\Utils\Arrays::isList - * @return ($value is list ? true : false) - */ - public static function isList(mixed $value): bool - { - return Arrays::isList($value); - } - - - /** - * 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 - { - if ($value === null || !(isset($range[0]) || isset($range[1]))) { - return false; - } - - $limit = $range[0] ?? $range[1]; - if (is_string($limit)) { - $value = (string) $value; - } elseif ($limit instanceof \DateTimeInterface) { - if (!$value instanceof \DateTimeInterface) { - return false; - } - } elseif (is_numeric($value)) { - $value *= 1; - } else { - return false; - } - - return (!isset($range[0]) || ($value >= $range[0])) && (!isset($range[1]) || ($value <= $range[1])); - } - - - /** - * Checks if the value is a valid email address. It does not verify that the domain actually exists, only the syntax is verified. - */ - public static function isEmail(string $value): bool - { - $atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]"; // RFC 5322 unquoted characters in local-part - $alpha = "a-z\x80-\xFF"; // superset of IDN - return (bool) preg_match(<< \\? (? [a-zA-Z_\x7f-\xff][\w\x7f-\xff]*) (\\ (?&name))* ) | - (? (?&type) (& (?&type))+ ) | - (? (?&type) | \( (?&intersection) \) ) (\| (?&upart))+ - )$~xAD - XX, $type); - } -} diff --git a/tools/.phpstan/vendor/nette/utils/src/Utils/exceptions.php b/tools/.phpstan/vendor/nette/utils/src/Utils/exceptions.php deleted file mode 100644 index ba1cdfe..0000000 --- a/tools/.phpstan/vendor/nette/utils/src/Utils/exceptions.php +++ /dev/null @@ -1,64 +0,0 @@ -ignoreErrorsOnPackage('nikic/php-parser', [ErrorType::SHADOW_DEPENDENCY]); diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/composer.json b/tools/.phpstan/vendor/tomasvotruba/type-coverage/composer.json index c3defb6..d3493db 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/composer.json +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/composer.json @@ -5,15 +5,41 @@ "license": "MIT", "keywords": ["static analysis", "phpstan-extension"], "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.33", - "nette/utils": "^3.2 || ^4.0" + "php": "^8.4", + "phpstan/phpstan": "^2.2" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4", + "phpunit/phpunit": "^12.5", + "symplify/easy-coding-standard": "^13.1", + "rector/rector": "^2.4", + "tracy/tracy": "^2.12", + "tomasvotruba/unused-public": "^2.2", + "rector/jack": "^1.0", + "shipmonk/composer-dependency-analyser": "^1.8" }, "autoload": { "psr-4": { "TomasVotruba\\TypeCoverage\\": "src" } }, + "autoload-dev": { + "psr-4": { + "TomasVotruba\\TypeCoverage\\Tests\\": "tests" + } + }, + "scripts": { + "check-cs": "vendor/bin/ecs check --ansi", + "fix-cs": "vendor/bin/ecs check --fix --ansi", + "phpstan": "vendor/bin/phpstan --ansi", + "rector": "vendor/bin/rector --dry-run --ansi", + "release": "vendor/bin/monorepo-builder release patch --ansi" + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true + } + }, "extra": { "phpstan": { "includes": [ diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/ConstantTypeDeclarationCollector.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/ConstantTypeDeclarationCollector.php index c3ac810..dafd55b 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/ConstantTypeDeclarationCollector.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/ConstantTypeDeclarationCollector.php @@ -72,12 +72,9 @@ final class ConstantTypeDeclarationCollector implements Collector return false; } - foreach ($classReflection->getParents() as $parentClassReflection) { - if ($parentClassReflection->hasConstant($constName)) { - return true; - } - } - - return false; + return array_any( + $classReflection->getParents(), + fn (ClassReflection $parentClassReflection): bool => $parentClassReflection->hasConstant($constName) + ); } } diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/ParamTypeDeclarationCollector.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/ParamTypeDeclarationCollector.php index c8f2567..8cc40e6 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/ParamTypeDeclarationCollector.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/ParamTypeDeclarationCollector.php @@ -90,13 +90,10 @@ final class ParamTypeDeclarationCollector implements Collector } } - foreach ($classReflection->getInterfaces() as $interfaceReflection) { - if ($interfaceReflection->hasMethod($methodName)) { - return true; - } - } - - return false; + return array_any( + $classReflection->getInterfaces(), + fn (ClassReflection $classReflection): bool => $classReflection->hasMethod($methodName) + ); } private function hasFunctionLikeCallableParam(FunctionLike $functionLike): bool @@ -108,6 +105,6 @@ final class ParamTypeDeclarationCollector implements Collector } $docCommentText = $docComment->getText(); - return strpos($docCommentText, '@param callable') !== false; + return str_contains($docCommentText, '@param callable'); } } diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/PropertyTypeDeclarationCollector.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/PropertyTypeDeclarationCollector.php index 412cd42..4b89cbc 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/PropertyTypeDeclarationCollector.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Collectors/PropertyTypeDeclarationCollector.php @@ -76,7 +76,7 @@ final class PropertyTypeDeclarationCollector implements Collector $docCommentText = $docComment->getText(); // skip as unable to type - return strpos($docCommentText, 'callable') !== false || strpos($docCommentText, 'resource') !== false; + return str_contains($docCommentText, 'callable') || str_contains($docCommentText, 'resource'); } private function isGuardedByParentClassProperty(Scope $scope, Property $property): bool @@ -88,12 +88,9 @@ final class PropertyTypeDeclarationCollector implements Collector return false; } - foreach ($classReflection->getParents() as $parentClassReflection) { - if ($parentClassReflection->hasProperty($propertyName)) { - return true; - } - } - - return false; + return array_any( + $classReflection->getParents(), + fn (ClassReflection $parentClassReflection): bool => $parentClassReflection->hasProperty($propertyName) + ); } } diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Configuration.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Configuration.php index 311d103..bb10672 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Configuration.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Configuration.php @@ -4,26 +4,17 @@ declare(strict_types=1); namespace TomasVotruba\TypeCoverage; -final class Configuration +final readonly class Configuration { - /** - * @var array - * @readonly - */ - private array $parameters; - /** * @param array $parameters */ - public function __construct(array $parameters) - { - $this->parameters = $parameters; + public function __construct( + private array $parameters + ) { } - /** - * @return float|int - */ - public function getRequiredPropertyTypeLevel() + public function getRequiredPropertyTypeLevel(): float|int { return $this->parameters['property'] ?? $this->parameters['property_type']; } @@ -38,34 +29,22 @@ final class Configuration return $this->getRequiredConstantTypeLevel() > 0; } - /** - * @return float|int - */ - public function getRequiredConstantTypeLevel() + public function getRequiredConstantTypeLevel(): float|int { return $this->parameters['constant'] ?? $this->parameters['constant_type']; } - /** - * @return float|int - */ - public function getRequiredParamTypeLevel() + public function getRequiredParamTypeLevel(): float|int { return $this->parameters['param'] ?? $this->parameters['param_type']; } - /** - * @return float|int - */ - public function getRequiredReturnTypeLevel() + public function getRequiredReturnTypeLevel(): float|int { return $this->parameters['return'] ?? $this->parameters['return_type']; } - /** - * @return float|int - */ - public function getRequiredDeclareLevel() + public function getRequiredDeclareLevel(): float|int { return $this->parameters['declare']; } diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Configuration/ScopeConfigurationResolver.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Configuration/ScopeConfigurationResolver.php index 4929c86..4e40be3 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Configuration/ScopeConfigurationResolver.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Configuration/ScopeConfigurationResolver.php @@ -51,9 +51,6 @@ final class ScopeConfigurationResolver private static function getPrivateProperty(object $object, string $propertyName): object { $reflectionProperty = new ReflectionProperty($object, $propertyName); - if (PHP_VERSION_ID < 80100) { - $reflectionProperty->setAccessible(true); - } return $reflectionProperty->getValue($object); } diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Formatter/TypeCoverageFormatter.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Formatter/TypeCoverageFormatter.php index 04d7c39..c31c745 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Formatter/TypeCoverageFormatter.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Formatter/TypeCoverageFormatter.php @@ -12,12 +12,11 @@ final class TypeCoverageFormatter { /** * @return RuleError[] - * @param float|int $minimalLevel */ public function formatErrors( string $message, string $identifier, - $minimalLevel, + float|int $minimalLevel, TypeCountAndMissingTypes $typeCountAndMissingTypes ): array { if ($typeCountAndMissingTypes->getTotalCount() === 0) { diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ConstantTypeCoverageRule.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ConstantTypeCoverageRule.php index 7fe74a9..54414d1 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ConstantTypeCoverageRule.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ConstantTypeCoverageRule.php @@ -21,41 +21,17 @@ use TomasVotruba\TypeCoverage\Formatter\TypeCoverageFormatter; * * @implements Rule */ -final class ConstantTypeCoverageRule implements Rule +final readonly class ConstantTypeCoverageRule implements Rule { - /** - * @var string - */ - public const ERROR_MESSAGE = 'Out of %d possible constant types, only %d - %.1f %% actually have it. Add more constant types to get over %s %%'; + public const string ERROR_MESSAGE = 'Out of %d possible constant types, only %d - %.1f %% actually have it. Add more constant types to get over %s %%'; - /** - * @var string - */ - private const IDENTIFIER = 'typeCoverage.constantTypeCoverage'; - - /** - * @readonly - */ - private TypeCoverageFormatter $typeCoverageFormatter; - - /** - * @readonly - */ - private Configuration $configuration; - - /** - * @readonly - */ - private CollectorDataNormalizer $collectorDataNormalizer; + private const string IDENTIFIER = 'typeCoverage.constantTypeCoverage'; public function __construct( - TypeCoverageFormatter $typeCoverageFormatter, - Configuration $configuration, - CollectorDataNormalizer $collectorDataNormalizer + private TypeCoverageFormatter $typeCoverageFormatter, + private Configuration $configuration, + private CollectorDataNormalizer $collectorDataNormalizer, ) { - $this->typeCoverageFormatter = $typeCoverageFormatter; - $this->configuration = $configuration; - $this->collectorDataNormalizer = $collectorDataNormalizer; } /** diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/DeclareCoverageRule.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/DeclareCoverageRule.php index c051aa4..2df1c6f 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/DeclareCoverageRule.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/DeclareCoverageRule.php @@ -19,26 +19,15 @@ use TomasVotruba\TypeCoverage\Configuration\ScopeConfigurationResolver; * * @implements Rule */ -final class DeclareCoverageRule implements Rule +final readonly class DeclareCoverageRule implements Rule { - /** - * @var string - */ - public const ERROR_MESSAGE = 'Out of %d possible declare(strict_types=1), only %d - %.1f %% actually have it. Add more declares to get over %s %%'; + public const string ERROR_MESSAGE = 'Out of %d possible declare(strict_types=1), only %d - %.1f %% actually have it. Add more declares to get over %s %%'; - /** - * @var string - */ - private const IDENTIFIER = 'typeCoverage.declareCoverage'; + private const string IDENTIFIER = 'typeCoverage.declareCoverage'; - /** - * @readonly - */ - private Configuration $configuration; - - public function __construct(Configuration $configuration) - { - $this->configuration = $configuration; + public function __construct( + private Configuration $configuration, + ) { } /** diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ParamTypeCoverageRule.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ParamTypeCoverageRule.php index 81df458..81f4eaa 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ParamTypeCoverageRule.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ParamTypeCoverageRule.php @@ -21,41 +21,17 @@ use TomasVotruba\TypeCoverage\Formatter\TypeCoverageFormatter; * * @implements Rule */ -final class ParamTypeCoverageRule implements Rule +final readonly class ParamTypeCoverageRule implements Rule { - /** - * @var string - */ - public const ERROR_MESSAGE = 'Out of %d possible param types, only %d - %.1f %% actually have it. Add more param types to get over %s %%'; + public const string ERROR_MESSAGE = 'Out of %d possible param types, only %d - %.1f %% actually have it. Add more param types to get over %s %%'; - /** - * @var string - */ - private const IDENTIFIER = 'typeCoverage.paramTypeCoverage'; - - /** - * @readonly - */ - private TypeCoverageFormatter $typeCoverageFormatter; - - /** - * @readonly - */ - private Configuration $configuration; - - /** - * @readonly - */ - private CollectorDataNormalizer $collectorDataNormalizer; + private const string IDENTIFIER = 'typeCoverage.paramTypeCoverage'; public function __construct( - TypeCoverageFormatter $typeCoverageFormatter, - Configuration $configuration, - CollectorDataNormalizer $collectorDataNormalizer + private TypeCoverageFormatter $typeCoverageFormatter, + private Configuration $configuration, + private CollectorDataNormalizer $collectorDataNormalizer, ) { - $this->typeCoverageFormatter = $typeCoverageFormatter; - $this->configuration = $configuration; - $this->collectorDataNormalizer = $collectorDataNormalizer; } /** diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/PropertyTypeCoverageRule.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/PropertyTypeCoverageRule.php index 74edaa0..107f6f1 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/PropertyTypeCoverageRule.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/PropertyTypeCoverageRule.php @@ -21,41 +21,17 @@ use TomasVotruba\TypeCoverage\Formatter\TypeCoverageFormatter; * * @implements Rule */ -final class PropertyTypeCoverageRule implements Rule +final readonly class PropertyTypeCoverageRule implements Rule { - /** - * @var string - */ - public const ERROR_MESSAGE = 'Out of %d possible property types, only %d - %.1f %% actually have it. Add more property types to get over %s %%'; + public const string ERROR_MESSAGE = 'Out of %d possible property types, only %d - %.1f %% actually have it. Add more property types to get over %s %%'; - /** - * @var string - */ - private const IDENTIFIER = 'typeCoverage.propertyTypeCoverage'; - - /** - * @readonly - */ - private TypeCoverageFormatter $typeCoverageFormatter; - - /** - * @readonly - */ - private Configuration $configuration; - - /** - * @readonly - */ - private CollectorDataNormalizer $collectorDataNormalizer; + private const string IDENTIFIER = 'typeCoverage.propertyTypeCoverage'; public function __construct( - TypeCoverageFormatter $typeCoverageFormatter, - Configuration $configuration, - CollectorDataNormalizer $collectorDataNormalizer + private TypeCoverageFormatter $typeCoverageFormatter, + private Configuration $configuration, + private CollectorDataNormalizer $collectorDataNormalizer, ) { - $this->typeCoverageFormatter = $typeCoverageFormatter; - $this->configuration = $configuration; - $this->collectorDataNormalizer = $collectorDataNormalizer; } /** diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ReturnTypeCoverageRule.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ReturnTypeCoverageRule.php index cee1d65..8af2c39 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ReturnTypeCoverageRule.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/Rules/ReturnTypeCoverageRule.php @@ -21,41 +21,17 @@ use TomasVotruba\TypeCoverage\Formatter\TypeCoverageFormatter; * * @implements Rule */ -final class ReturnTypeCoverageRule implements Rule +final readonly class ReturnTypeCoverageRule implements Rule { - /** - * @var string - */ - public const ERROR_MESSAGE = 'Out of %d possible return types, only %d - %.1f %% actually have it. Add more return types to get over %s %%'; + public const string ERROR_MESSAGE = 'Out of %d possible return types, only %d - %.1f %% actually have it. Add more return types to get over %s %%'; - /** - * @var string - */ - private const IDENTIFIER = 'typeCoverage.returnTypeCoverage'; - - /** - * @readonly - */ - private TypeCoverageFormatter $typeCoverageFormatter; - - /** - * @readonly - */ - private Configuration $configuration; - - /** - * @readonly - */ - private CollectorDataNormalizer $collectorDataNormalizer; + private const string IDENTIFIER = 'typeCoverage.returnTypeCoverage'; public function __construct( - TypeCoverageFormatter $typeCoverageFormatter, - Configuration $configuration, - CollectorDataNormalizer $collectorDataNormalizer + private TypeCoverageFormatter $typeCoverageFormatter, + private Configuration $configuration, + private CollectorDataNormalizer $collectorDataNormalizer, ) { - $this->typeCoverageFormatter = $typeCoverageFormatter; - $this->configuration = $configuration; - $this->collectorDataNormalizer = $collectorDataNormalizer; } /** diff --git a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/ValueObject/TypeCountAndMissingTypes.php b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/ValueObject/TypeCountAndMissingTypes.php index c539839..146294f 100644 --- a/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/ValueObject/TypeCountAndMissingTypes.php +++ b/tools/.phpstan/vendor/tomasvotruba/type-coverage/src/ValueObject/TypeCountAndMissingTypes.php @@ -4,32 +4,16 @@ declare(strict_types=1); namespace TomasVotruba\TypeCoverage\ValueObject; -final class TypeCountAndMissingTypes +final readonly class TypeCountAndMissingTypes { - /** - * @readonly - */ - private int $totalCount; - - /** - * @readonly - */ - private int $missingCount; - - /** - * @var array - * @readonly - */ - private array $missingTypeLinesByFilePath; - /** * @param array $missingTypeLinesByFilePath */ - public function __construct(int $totalCount, int $missingCount, array $missingTypeLinesByFilePath) - { - $this->totalCount = $totalCount; - $this->missingCount = $missingCount; - $this->missingTypeLinesByFilePath = $missingTypeLinesByFilePath; + public function __construct( + private int $totalCount, + private int $missingCount, + private array $missingTypeLinesByFilePath + ) { } public function getTotalCount(): int