diff --git a/.github/workflows/php-cs-fixer.yml b/.github/workflows/php-cs-fixer.yml new file mode 100644 index 0000000..5d8ccbd --- /dev/null +++ b/.github/workflows/php-cs-fixer.yml @@ -0,0 +1,30 @@ +name: Check styling + +on: [pull_request] + +permissions: + contents: read + +jobs: + style: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 7.4 + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install PHP dependencies + run: composer update --no-cache --prefer-stable --no-interaction --no-progress + + - name: Check styling + run: vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --dry-run --stop-on-violation --using-cache=no --path-mode=intersection ./src ./tests diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000..5802ca3 --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,38 @@ +name: PHPStan + +on: + pull_request: + paths: + - '**.php' + - 'phpstan.neon.dist' + +permissions: + contents: read + +jobs: + phpstan: + name: phpstan + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 7.4 + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install PHP dependencies + uses: ramsey/composer-install@v2 + + - name: Run PHPStan + run: | + vendor/bin/phpstan --error-format=github analyse src/ + exit_code=$? + if [ $exit_code -ne 0 ]; then + echo "PHPStan analysis failed with exit code $exit_code" + exit $exit_code + fi diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 0000000..a3e8c3c --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,36 @@ +name: Run tests + +on: [pull_request] + +permissions: + contents: read + +jobs: + php-tests: + runs-on: ubuntu-latest + + strategy: + matrix: + php: [8.3, 8.2, 8.1, 8.0, 7.4] + dependency-version: [prefer-lowest, prefer-stable] + os: [ubuntu-latest] + + name: P${{ matrix.php }} - ${{ matrix.dependency-version }} - ${{ matrix.os }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install PHP dependencies + run: composer update --${{ matrix.dependency-version }} --no-cache --no-interaction --no-progress + + - name: Execute tests + run: composer run phpunit diff --git a/.gitignore b/.gitignore index f57386d..b730043 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ -composer.lock vendor/ coverage/ .phpunit.result.cache .composer/ +build/ +.idea/ diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..fa6dfde --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,20 @@ +in([ + __DIR__ . DIRECTORY_SEPARATOR . 'src', + __DIR__ . DIRECTORY_SEPARATOR . 'tests', + ]) +; + +return (new PhpCsFixer\Config()) + ->setRiskyAllowed(true) + ->setRules([ + '@PSR12' => true, + '@PHP82Migration' => true, + 'strict_param' => true, + 'array_syntax' => ['syntax' => 'short'], + 'declare_strict_types' => true, + ]) + ->setFinder($finder) +; diff --git a/composer.json b/composer.json index 209f191..b8b54ea 100644 --- a/composer.json +++ b/composer.json @@ -21,12 +21,20 @@ "config": { "preferred-install": "dist", "prepend-autoloader": false, - "optimize-autoloader": true + "optimize-autoloader": true, + "allow-plugins": { + "phpstan/extension-installer": true + } }, "scripts": { "phpunit": "./vendor/phpunit/phpunit/phpunit tests" }, "require-dev": { - "phpunit/phpunit": "^9.6" + "phpunit/phpunit": "^9.6", + "friendsofphp/php-cs-fixer": "^3.38", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3" } } diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..5855e13 --- /dev/null +++ b/composer.lock @@ -0,0 +1,3882 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "08aca314bdb70d8f2f713f342853bbb2", + "packages": [ + { + "name": "madesimple/php-arrays", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/pdscopes/php-arrays.git", + "reference": "e0b921ab295a965dbc125c33bdde864721c59f08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pdscopes/php-arrays/zipball/e0b921ab295a965dbc125c33bdde864721c59f08", + "reference": "e0b921ab295a965dbc125c33bdde864721c59f08", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "MadeSimple\\Arrays\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Peter Scopes", + "email": "peter.scopes@gmail.com" + } + ], + "description": "Helper functions for manipulating arrays", + "support": { + "issues": "https://github.com/pdscopes/php-arrays/issues", + "source": "https://github.com/pdscopes/php-arrays/tree/v2.1.0" + }, + "time": "2022-02-25T14:48:55+00:00" + } + ], + "packages-dev": [ + { + "name": "composer/pcre", + "version": "3.1.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/4775f35b2d70865807c89d32c8e7385b86eb0ace", + "reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.1.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-03-07T15:38:35+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2023-08-31T09:50:34+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "ced299686f41dce890debac69273b47ffe98a40c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-02-25T21:32:43+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:15:36+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.51.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "127fa74f010da99053e3f5b62672615b72dd6efd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/127fa74f010da99053e3f5b62672615b72dd6efd", + "reference": "127fa74f010da99053e3f5b62672615b72dd6efd", + "shasum": "" + }, + "require": { + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.3", + "ext-filter": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^5.4 || ^6.0 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", + "symfony/polyfill-mbstring": "^1.28", + "symfony/polyfill-php80": "^1.28", + "symfony/polyfill-php81": "^1.28", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3 || ^2.0", + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^2.1", + "mikey179/vfsstream": "^1.6.11", + "php-coveralls/php-coveralls": "^2.7", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", + "phpunit/phpunit": "^9.6 || ^10.5.5 || ^11.0.2", + "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz RumiƄski", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "keywords": [ + "Static code analysis", + "fixer", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.51.0" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2024-02-28T19:50:06+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.0.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69", + "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.1" + }, + "time": "2024-02-21T19:24:10+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpstan/extension-installer", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/extension-installer.git", + "reference": "f45734bfb9984c6c56c4486b71230355f066a58a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f45734bfb9984c6c56c4486b71230355f066a58a", + "reference": "f45734bfb9984c6c56c4486b71230355f066a58a", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.0" + }, + "require-dev": { + "composer/composer": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPStan\\ExtensionInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPStan\\ExtensionInstaller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer plugin for automatic installation of PHPStan extensions", + "support": { + "issues": "https://github.com/phpstan/extension-installer/issues", + "source": "https://github.com/phpstan/extension-installer/tree/1.3.1" + }, + "time": "2023-05-24T08:59:17+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.10.60", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/95dcea7d6c628a3f2f56d091d8a0219485a86bbe", + "reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2024-03-07T13:30:19+00:00" + }, + { + "name": "phpstan/phpstan-deprecation-rules", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", + "reference": "089d8a8258ed0aeefdc7b68b6c3d25572ebfdbaa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/089d8a8258ed0aeefdc7b68b6c3d25572ebfdbaa", + "reference": "089d8a8258ed0aeefdc7b68b6c3d25572ebfdbaa", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.10.3" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-php-parser": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", + "support": { + "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.1.4" + }, + "time": "2023-08-05T09:02:04+00:00" + }, + { + "name": "phpstan/phpstan-mockery", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-mockery.git", + "reference": "88ae85931768efd3aaf3cce4cb9cb54c4d157d03" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-mockery/zipball/88ae85931768efd3aaf3cce4cb9cb54c4d157d03", + "reference": "88ae85931768efd3aaf3cce4cb9cb54c4d157d03", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.10" + }, + "require-dev": { + "mockery/mockery": "^1.2.4", + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan Mockery extension", + "support": { + "issues": "https://github.com/phpstan/phpstan-mockery/issues", + "source": "https://github.com/phpstan/phpstan-mockery/tree/1.1.2" + }, + "time": "2024-01-10T13:50:05+00:00" + }, + { + "name": "phpstan/phpstan-phpunit", + "version": "1.3.16", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-phpunit.git", + "reference": "d5242a59d035e46774f2e634b374bc39ff62cb95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/d5242a59d035e46774f2e634b374bc39ff62cb95", + "reference": "d5242a59d035e46774f2e634b374bc39ff62cb95", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.10" + }, + "conflict": { + "phpunit/phpunit": "<7.0" + }, + "require-dev": { + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-strict-rules": "^1.5.1", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPUnit extensions and rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-phpunit/issues", + "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.16" + }, + "time": "2024-02-23T09:51:20+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.30", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:47:57+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.16", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "3767b2c56ce02d01e3491046f33466a1ae60a37f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3767b2c56ce02d01e3491046f33466a1ae60a37f", + "reference": "3767b2c56ce02d01e3491046f33466a1ae60a37f", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.28", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.16" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-01-19T07:03:14+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:08:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-05-07T05:35:17+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:03:37+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bde739e7565280bda77be70044ac1047bc007e34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-02T09:26:13+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "symfony/console", + "version": "v5.4.36", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e", + "reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.4.36" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-20T16:33:57+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v5.4.35", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "7a69a85c7ea5bdd1e875806a99c51a87d3a74b38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7a69a85c7ea5bdd1e875806a99c51a87d3a74b38", + "reference": "7a69a85c7ea5bdd1e875806a99c51a87d3a74b38", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.35" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T13:51:25+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.4.35", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "5a553607d4ffbfa9c0ab62facadea296c9db7086" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/5a553607d4ffbfa9c0ab62facadea296c9db7086", + "reference": "5a553607d4ffbfa9c0ab62facadea296c9db7086", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.4.35" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T13:51:25+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.4.35", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "abe6d6f77d9465fed3cd2d029b29d03b56b56435" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/abe6d6f77d9465fed3cd2d029b29d03b56b56435", + "reference": "abe6d6f77d9465fed3cd2d029b29d03b56b56435", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.4.35" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T13:51:25+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-14T08:03:56+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/c565ad1e63f30e7477fc40738343c62b40bc672d", + "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/process", + "version": "v5.4.36", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "4fdf34004f149cc20b2f51d7d119aa500caad975" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/4fdf34004f149cc20b2f51d7d119aa500caad975", + "reference": "4fdf34004f149cc20b2f51d7d119aa500caad975", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v5.4.36" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-12T15:49:53+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-30T19:17:29+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v5.4.35", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "887762aa99ff16f65dc8b48aafead415f942d407" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/887762aa99ff16f65dc8b48aafead415f942d407", + "reference": "887762aa99ff16f65dc8b48aafead415f942d407", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/service-contracts": "^1|^2|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v5.4.35" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T13:51:25+00:00" + }, + { + "name": "symfony/string", + "version": "v5.4.36", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "4e232c83622bd8cd32b794216aa29d0d266d353b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/4e232c83622bd8cd32b794216aa29d0d266d353b", + "reference": "4e232c83622bd8cd32b794216aa29d0d266d353b", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.36" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-01T08:49:30+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2023-11-20T00:12:19+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.4" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..19509c3 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,31 @@ +parameters: + ignoreErrors: + - + message: "#^Argument of an invalid type array\\\\|bool\\|string supplied for foreach, only iterables are supported\\.$#" + count: 1 + path: src/Validator/AbstractValidator.php + + - + message: "#^Parameter \\#1 \\$string of function substr expects string, bool\\|string given\\.$#" + count: 1 + path: src/Validator/AbstractValidator.php + + - + message: "#^Parameter \\#2 \\$key of static method MadeSimple\\\\Arrays\\\\ArrDots\\:\\:get\\(\\) expects string, array\\\\|bool\\|string given\\.$#" + count: 2 + path: src/Validator/AbstractValidator.php + + - + message: "#^Parameter \\#2 \\$replace of function str_replace expects array\\|string, bool\\|string given\\.$#" + count: 1 + path: src/Validator/AbstractValidator.php + + - + message: "#^Possibly invalid array key type array\\\\|bool\\|string\\.$#" + count: 2 + path: src/Validator/AbstractValidator.php + + - + message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, bool\\|string given\\.$#" + count: 1 + path: src/Validator/Helper/Str.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..28b6e3c --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,10 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 8 + paths: + - src + + tmpDir: build/phpstan + checkMissingIterableValueType: true diff --git a/src/Validator/AbstractValidator.php b/src/Validator/AbstractValidator.php index fbb3aea..46f0325 100644 --- a/src/Validator/AbstractValidator.php +++ b/src/Validator/AbstractValidator.php @@ -12,15 +12,21 @@ abstract class AbstractValidator { - const WILD = '*'; + public const WILD = '*'; /** * @var AbstractRule[] */ protected array $rules; + /** + * @var array> + */ protected array $messages; + /** + * @var array>> + */ protected array $errors; protected string $prefix = ''; @@ -28,7 +34,10 @@ abstract class AbstractValidator public function __construct() { $this->rules = []; - $this->messages = ['rules' => [], 'custom' => []]; + $this->messages = [ + 'rules' => [], + 'custom' => [], + ]; $this->errors = []; } @@ -56,10 +65,14 @@ public function addRule(AbstractRule $rule): self return $this; } - public function getValue($array, $pattern) + /** + * @param array> $array + * @return mixed|null + */ + public function getValue(array $array, string $pattern) { $imploded = ArrDots::implode($array); - $pattern = sprintf('/^%s$/', str_replace(static::WILD, '[0-9]+', $pattern)); + $pattern = sprintf('/^%s$/', str_replace(static::WILD, '[0-9]+', $pattern)); foreach ($imploded as $attribute => $value) { if (preg_match($pattern, $attribute) == 0) { @@ -72,14 +85,22 @@ public function getValue($array, $pattern) return null; } - public function getValues($array, $pattern): iterable + /** + * @param array> $array + * @return iterable + */ + public function getValues(array $array, string $pattern): iterable { foreach (ArrDots::collate($array, $pattern, static::WILD) as $attribute => $value) { yield $attribute => $value; } } - public function validate($values, array $ruleSet, string $prefix = null) : bool + /** + * @param array> $values + * @param array $ruleSet + */ + public function validate(array $values, array $ruleSet, string $prefix = null): bool { // If there are no rules, there is nothing to validate if (empty($ruleSet)) { @@ -92,15 +113,18 @@ public function validate($values, array $ruleSet, string $prefix = null) : bool // For each pattern and its rules foreach ($ruleSet as $pattern => $rules) { - if (is_string($rules)) { - $rules = explode('|', $rules); - } + $rules = explode('|', $rules); + foreach ($rules as $rule) { - list($rule, $parameters) = array_pad(explode(':', $rule, 2), 2, ''); + [$rule, $parameters] = array_pad(explode(':', $rule, 2), 2, ''); $parameters = array_map('trim', explode(',', $parameters)); if (Arr::exists($this->rules, $rule)) { - $this->rules[$rule]->validate($this, $values, $pattern, $parameters); + if (!$this->rules[$rule]->validate($this, $values, $pattern, $parameters)) { + // If the rule failed, we stop checking the rest of the rules for this pattern + // @todo: do we need to stop on error for each field separately? + break; + } } } } @@ -114,12 +138,15 @@ public function hasErrors(): bool return count($this->errors) > 0; } - public function addError($attribute, $rule, $replacements = []): void + /** + * @param array $replacements + */ + public function addError(string $attribute, string $rule, array $replacements = []): void { $replacements = array_merge([ ':attribute' => $this->prefix . $attribute, '!(\S+)\|(\S+)' => true, - ], $replacements ?? []); + ], $replacements); $this->errors[] = [ 'attribute' => $this->prefix . $attribute, @@ -128,6 +155,9 @@ public function addError($attribute, $rule, $replacements = []): void ]; } + /** + * @return array> + */ public function getProcessedErrors(): array { $errors = []; diff --git a/src/Validator/Contract/RepositoryInterface.php b/src/Validator/Contract/RepositoryInterface.php index a673993..5fc43df 100644 --- a/src/Validator/Contract/RepositoryInterface.php +++ b/src/Validator/Contract/RepositoryInterface.php @@ -6,7 +6,13 @@ interface RepositoryInterface { + /** + * @return array|null + */ public function find(int $id): ?array; + /** + * @return array> + */ public function findAll(): array; } diff --git a/src/Validator/Exception/IncorrectValidationRuleStructure.php b/src/Validator/Exception/IncorrectValidationRuleStructure.php index 0604309..b959be6 100644 --- a/src/Validator/Exception/IncorrectValidationRuleStructure.php +++ b/src/Validator/Exception/IncorrectValidationRuleStructure.php @@ -1,5 +1,7 @@ name; } - abstract public function validate(AbstractValidator $validator, $data, $pattern, $parameters): void; + /** + * @param array $data + * @param array $parameters + */ + abstract public function validate(AbstractValidator $validator, array $data, string $pattern, array $parameters): bool; + /** + * @param mixed $value + */ protected function isFilled($value): bool { return !( diff --git a/src/Validator/Rules/Comparison/AbstractComparison.php b/src/Validator/Rules/Comparison/AbstractComparison.php new file mode 100644 index 0000000..9ba71e0 --- /dev/null +++ b/src/Validator/Rules/Comparison/AbstractComparison.php @@ -0,0 +1,73 @@ + $data + * @param array $parameters + * @throws IncorrectValidationRuleStructure + */ + public function validate(AbstractValidator $validator, array $data, string $pattern, array $parameters): bool + { + $fieldToCompare = $parameters[0]; + $lowerBound = $validator->getValue($data, $fieldToCompare); + + $values = $validator->getValues($data, $pattern); + if (empty($values)) { + $validator->addError($pattern, $this->getName(), [ + ':fieldToCompare' => $fieldToCompare, + ':valueToCompare' => $lowerBound, + ]); + return false; + } + + $isValid = true; + foreach ($values as $attribute => $value) { + if (!is_numeric($value)) { + $isValid = false; + } + + if ($isValid) { + // here it is not a strict comparison, since it can be 0 and "0" + if (!is_numeric($lowerBound) || empty($lowerBound) && $lowerBound != 0) { + $isValid = false; + break; + } + } + + if ($isValid) { + if (!$this->compare($value, $lowerBound)) { + $isValid = false; + } + } + + if ($isValid) { + break; + } + + $validator->addError($attribute, $this->getName(), [ + ':fieldToCompare' => $fieldToCompare, + ':valueToCompare' => (string) $lowerBound, + ]); + } + + return $isValid; + } + + /** + * @param mixed $value + * @param mixed $lowerBound + * @return bool + */ + abstract protected function compare($value, $lowerBound): bool; +} diff --git a/src/Validator/Rules/Comparison/GreaterThan.php b/src/Validator/Rules/Comparison/GreaterThan.php new file mode 100644 index 0000000..b95df03 --- /dev/null +++ b/src/Validator/Rules/Comparison/GreaterThan.php @@ -0,0 +1,20 @@ + (float) $lowerBound; + } +} diff --git a/src/Validator/Rules/Comparison/LessThan.php b/src/Validator/Rules/Comparison/LessThan.php new file mode 100644 index 0000000..a773e5c --- /dev/null +++ b/src/Validator/Rules/Comparison/LessThan.php @@ -0,0 +1,20 @@ + $data + * @param array $parameters * @throws IncorrectValidationRuleStructure */ - public function validate(AbstractValidator $validator, $data, $pattern, $parameters): void + public function validate(AbstractValidator $validator, array $data, string $pattern, array $parameters): bool { + $isValid = true; foreach ($validator->getValues($data, $pattern) as $attribute => $value) { if (!empty($value)) { if ($this->repository->find((int) $value)) { @@ -31,7 +34,10 @@ public function validate(AbstractValidator $validator, $data, $pattern, $paramet } } - $validator->addError($attribute, $this->getName(), [':id' => $value]); + $validator->addError($attribute, $this->getName(), [':id' => (string) $value]); + $isValid = false; } + + return $isValid; } } diff --git a/src/Validator/Rules/GreaterThan.php b/src/Validator/Rules/GreaterThan.php deleted file mode 100644 index b62f889..0000000 --- a/src/Validator/Rules/GreaterThan.php +++ /dev/null @@ -1,42 +0,0 @@ -getValue($data, $fieldToCompare); - - $values = $validator->getValues($data, $pattern); - if (empty($values)) { - $validator->addError($pattern, $this->getName(), [ - ':fieldToCompare' => $fieldToCompare, - ':valueToCompare' => $lowerBound, - ]); - return; - } - - foreach ($values as $attribute => $value) { - if (is_numeric($value) && is_numeric($lowerBound) && $value > $lowerBound) { - continue; - } - - $validator->addError($attribute, $this->getName(), [ - ':fieldToCompare' => $fieldToCompare, - ':valueToCompare' => $lowerBound, - ]); - } - } -} diff --git a/src/Validator/Rules/LessThan.php b/src/Validator/Rules/LessThan.php deleted file mode 100644 index fdbe2e7..0000000 --- a/src/Validator/Rules/LessThan.php +++ /dev/null @@ -1,42 +0,0 @@ -getValue($data, $fieldToCompare); - - $values = $validator->getValues($data, $pattern); - if (empty($values)) { - $validator->addError($pattern, $this->getName(), [ - ':fieldToCompare' => $fieldToCompare, - ':valueToCompare' => $lowerBound, - ]); - return; - } - - foreach ($values as $attribute => $value) { - if (is_numeric($value) && is_numeric($lowerBound) && $value < $lowerBound) { - continue; - } - - $validator->addError($attribute, $this->getName(), [ - ':fieldToCompare' => $fieldToCompare, - ':valueToCompare' => $lowerBound, - ]); - } - } -} diff --git a/src/Validator/Rules/Min.php b/src/Validator/Rules/Min.php index 490378a..05b0e43 100644 --- a/src/Validator/Rules/Min.php +++ b/src/Validator/Rules/Min.php @@ -6,27 +6,29 @@ use Paysera\DataValidator\Validator\AbstractValidator; use Paysera\DataValidator\Validator\Exception\IncorrectValidationRuleStructure; -use Paysera\DataValidator\Validator\Rules\AbstractRule; class Min extends AbstractRule { protected string $name = 'min'; /** + * @param array $data + * @param array $parameters * @throws IncorrectValidationRuleStructure */ - public function validate(AbstractValidator $validator, $data, $pattern, $parameters): void + public function validate(AbstractValidator $validator, array $data, string $pattern, array $parameters): bool { $min = $parameters[0]; $values = $validator->getValues($data, $pattern); if (empty($values)) { $validator->addError($pattern, $this->getName(), [ ':min' => $min, - ':value' => null, + ':value' => '', ]); - return; + return false; } + $isValid = true; foreach ($values as $attribute => $value) { if ($value === '0') { continue; @@ -37,9 +39,12 @@ public function validate(AbstractValidator $validator, $data, $pattern, $paramet } $validator->addError($attribute, $this->getName(), [ - ':min' => $min, - ':value' => $value, + ':min' => (string) $min, + ':value' => (string) $value, ]); + $isValid = false; } + + return $isValid; } } diff --git a/src/Validator/Rules/Required.php b/src/Validator/Rules/Required.php index 67abca3..05792c2 100644 --- a/src/Validator/Rules/Required.php +++ b/src/Validator/Rules/Required.php @@ -5,14 +5,20 @@ namespace Paysera\DataValidator\Validator\Rules; use Paysera\DataValidator\Validator\AbstractValidator; +use Paysera\DataValidator\Validator\Exception\IncorrectValidationRuleStructure; class Required extends AbstractRule { protected string $name = 'required'; - public function validate(AbstractValidator $validator, $data, $pattern, $parameters): void + /** + * @param array $data + * @param array $parameters + * @throws IncorrectValidationRuleStructure + */ + public function validate(AbstractValidator $validator, array $data, string $pattern, array $parameters): bool { - // Check value is not null + $isValid = true; foreach ($validator->getValues($data, $pattern) as $attribute => $value) { // not allowed: null, '', [], empty instance Countable if ($this->isFilled($value)) { @@ -20,6 +26,9 @@ public function validate(AbstractValidator $validator, $data, $pattern, $paramet } $validator->addError($attribute, $this->getName()); + $isValid = false; } + + return $isValid; } } diff --git a/tests/Validator/AbstractValidatorTest.php b/tests/Validator/AbstractValidatorTest.php index 3236ac0..a9bc6c3 100644 --- a/tests/Validator/AbstractValidatorTest.php +++ b/tests/Validator/AbstractValidatorTest.php @@ -1,17 +1,23 @@ assertTrue($validator->validate([], [])); } @@ -24,7 +30,7 @@ public function getTestedData(): iterable ->method('find') ->with($entityId) ->willReturn([ - 2 => 'some value that means that the entity exists', + 3 => 'some value that means that the entity exists', ]); yield 'entity exists' => [ @@ -32,7 +38,9 @@ public function getTestedData(): iterable $repositoryMock, [ 'field' => "3", - 'custom_field' => 'some value', + ], + [ + 'field' => 'entity-exists', ], true, [], @@ -50,57 +58,285 @@ public function getTestedData(): iterable [ 'field' => "3", ], + [ + 'field' => 'entity-exists', + ], false, [ 'field' => [ 'entity-exists' => 'error message for entity-exists rule', - ] + ], + ], + ]; + + $repositoryMock = $this->createMock(RepositoryInterface::class); + $repositoryMock->expects($this->once()) + ->method('find') + ->with($entityId) + ->willReturn([ + 3 => 'some value that means that the entity exists', + ]); + + yield 'min validation rule, comparison is correct ' => [ + $entityId, + $repositoryMock, + [ + 'min__correct_field' => 0, + 'min_incorrect_field' => 1, + ], + [ + 'min_field' => 'min:0', + 'min_incorrect_field' => 'min:5', + ], + false, + [ + 'min_incorrect_field' => [ + 'min' => 'the value must be numeric and at least 5', + ], ], ]; } - /** - * @dataProvider getTestedData - */ - public function testRealValidator( - string $entityId, - RepositoryInterface $repositoryMock, - array $values, - bool $validationResult, - array $errors - ): void + public function testRealValidator(): void { - $realValidator = new class($repositoryMock) extends AbstractValidator { + $entityId = 3; + $repositoryMock = $this->createMock(RepositoryInterface::class); + $repositoryMock->expects($this->exactly(3)) + ->method('find') + ->withConsecutive( + [$entityId], + [4], + [5] + ) + ->willReturnOnConsecutiveCalls( + [ + 3 => 'some value that means that the entity exists', + ], + [], + [] + ); + + $realValidator = new class ($repositoryMock) extends AbstractValidator { public function __construct(RepositoryInterface $repository) { parent::__construct(); - $rule = new EntityExists($repository); - $this->addRule($rule); - $this->setRuleMessage($rule->getName(), 'error message for entity-exists rule'); - $this->setAttributeMessage('custom_field', 'customized error message for specific field'); + $this->addRule(new EntityExists($repository)); + $this->addRule(new Required()); + $this->addRule(new Min()); + $this->addRule(new LessThan()); + $this->addRule(new GreaterThan()); + + $this->setRuleMessage('entity-exists', 'error message for entity-exists rule'); + $this->setRuleMessage('required', 'the field is required and cannot be empty'); + $this->setRuleMessage('min', 'the value must be numeric and at least :min'); + $this->setRuleMessage( + 'less-than', + 'The field must be numeric and must have a value less than in the ":fieldToCompare".' + ); + $this->setRuleMessage( + 'greater-than', + 'The field must be numeric and must have a value greater than in the ":fieldToCompare".' + ); + + $this->setAttributeMessage( + 'field_entity_exists_incorrect_with_custom_error_message', + 'customized error message for specific field' + ); + $this->setAttributeMessage( + 'field_required_incorrect_with_custom_error_message', + 'The field is required and cannot be empty' + ); + $this->setAttributeMessage( + 'min_incorrect_field_min_value_5_with_custom_error_message', + 'the value must be numeric and at least :min. Provided value is :value' + ); + $this->setAttributeMessage( + 'less_than_incorrect_field_fieldToCompare_is_min_correct_field_with_custom_error_message', + 'The field must be numeric and must have a value less than in the ":fieldToCompare". ' + . 'Provided value is ":valueToCompare"' + ); + $this->setAttributeMessage( + 'greater_than_incorrect_field_fieldToCompare_is_min_correct_field_with_custom_error_message', + 'The field must be numeric and must have a value greater than in the ":fieldToCompare". ' + . 'Provided value is ":valueToCompare"' + ); } }; + $values = [ + 'field_entity_exists_correct' => $entityId, + 'field_entity_exists_incorrect' => 4, + 'field_entity_exists_incorrect_with_custom_error_message' => 5, + + 'field_required_correct' => 'value', + 'field_required_incorrect' => '', + 'field_required_incorrect_with_custom_error_message' => '', + + 'min_correct_field' => 0, + 'min_incorrect_field_min_value_5' => 0, + 'min_incorrect_field_min_value_5_with_custom_error_message' => 0, + + 'less_than_correct_field_fieldToCompare_is_min_correct_field' => -1, + 'less_than_incorrect_field_fieldToCompare_is_min_correct_field' => 5, + 'less_than_incorrect_field_fieldToCompare_is_min_correct_field_with_custom_error_message' => 5, + + 'greater_than_correct_field_fieldToCompare_is_min_correct_field' => 5, + 'greater_than_incorrect_field_fieldToCompare_is_min_correct_field' => 0, + 'greater_than_incorrect_field_fieldToCompare_is_min_correct_field_with_custom_error_message' => 0, + ]; + $rules = [ - 'field' => 'entity-exists', - 'custom_field' => 'required' + 'field_entity_exists_correct' => 'entity-exists', + 'field_entity_exists_incorrect' => 'entity-exists', + 'field_entity_exists_incorrect_with_custom_error_message' => 'entity-exists', + + 'field_required_correct' => 'required', + 'field_required_incorrect' => 'required', + 'field_required_incorrect_with_custom_error_message' => 'required', + + 'min_correct_field' => 'min:0', + 'min_incorrect_field_min_value_5' => 'min:5', + 'min_incorrect_field_min_value_5_with_custom_error_message' => 'min:5', + + 'less_than_correct_field_fieldToCompare_is_min_correct_field' => 'less-than:min_correct_field', + 'less_than_incorrect_field_fieldToCompare_is_min_correct_field' => 'less-than:min_correct_field', + 'less_than_incorrect_field_fieldToCompare_is_min_correct_field_with_custom_error_message' => + 'less-than:min_correct_field', + + 'greater_than_correct_field_fieldToCompare_is_min_correct_field' => 'greater-than:min_correct_field', + 'greater_than_incorrect_field_fieldToCompare_is_min_correct_field' => 'greater-than:min_correct_field', + 'greater_than_incorrect_field_fieldToCompare_is_min_correct_field_with_custom_error_message' => + 'greater-than:min_correct_field', + ]; + + $errors = [ + 'field_entity_exists_incorrect' => [ + 'entity-exists' => 'error message for entity-exists rule', + ], + 'field_entity_exists_incorrect_with_custom_error_message' => [ + 'entity-exists' => 'customized error message for specific field', + ], + 'field_required_incorrect' => [ + 'required' => 'the field is required and cannot be empty', + ], + 'field_required_incorrect_with_custom_error_message' => [ + 'required' => 'The field is required and cannot be empty', + ], + + 'min_incorrect_field_min_value_5' => [ + 'min' => 'the value must be numeric and at least 5', + ], + 'min_incorrect_field_min_value_5_with_custom_error_message' => [ + 'min' => 'the value must be numeric and at least 5. Provided value is 0', + ], + + 'less_than_incorrect_field_fieldToCompare_is_min_correct_field' => [ + 'less-than' => 'The field must be numeric and must have a value less than in the "Min correct field".', + ], + 'less_than_incorrect_field_fieldToCompare_is_min_correct_field_with_custom_error_message' => [ + 'less-than' => 'The field must be numeric and must have a value less than in the "Min correct field". ' + . 'Provided value is "0"', + ], + + 'greater_than_incorrect_field_fieldToCompare_is_min_correct_field' => [ + 'greater-than' => 'The field must be numeric and must have a value greater than in the "Min correct field".', + ], + 'greater_than_incorrect_field_fieldToCompare_is_min_correct_field_with_custom_error_message' => [ + 'greater-than' => 'The field must be numeric and must have a value greater than in the "Min correct field". ' + . 'Provided value is "0"', + ], ]; + $this->assertFalse($realValidator->validate($values, $rules)); + $this->assertEquals( - $validationResult, - $realValidator->validate($values, $rules) + $errors, + $realValidator->getProcessedErrors() ); + } + + public function getComplexTestedData(): iterable + { + $values = [ + 'min_correct_field' => 5, + 'field_with_two_validation_rules' => 4, + ]; + + $rules = [ + 'min_correct_field' => 'min:5|less-than:field_with_two_validation_rules', + 'field_with_two_validation_rules' => 'min:5|greater-than:min_correct_field', + ]; + + $errors = [ + 'field_with_two_validation_rules' => [ + 'min' => 'the value must be numeric and at least 5', + ], + ]; + + yield 'only min error is expected' => [ + $values, + $rules, + $errors, + 'min', + ]; + + $values = [ + 'min_correct_field' => 5, + 'field_with_two_validation_rules' => 5, + ]; + + $errors = [ + 'field_with_two_validation_rules' => [ + 'greater-than' => 'The field must be numeric and must have a value greater than in the "Min correct field".', + ], + ]; + + yield 'only greater-than error is expected' => [ + $values, + $rules, + $errors, + 'greater-than', + ]; + } + + /** + * @dataProvider getComplexTestedData + */ + public function testComplexValidationRulesStopOnError(array $values, array $rules, array $errors, string $wrongRule) + { + $realValidator = new class () extends AbstractValidator { + public function __construct() + { + parent::__construct(); + + $this->addRule(new Min()); + $this->addRule(new GreaterThan()); + + $this->setRuleMessage('min', 'the value must be numeric and at least :min'); + $this->setRuleMessage( + 'greater-than', + 'The field must be numeric and must have a value greater than in the ":fieldToCompare".' + ); + } + }; + + $this->assertFalse($realValidator->validate($values, $rules)); + + $processedErrors = $realValidator->getProcessedErrors(); $this->assertEquals( $errors, - $realValidator->getProcessedErrors() + $processedErrors ); + + $this->assertArrayHasKey($wrongRule, $processedErrors['field_with_two_validation_rules']); + $this->assertCount(1, $processedErrors['field_with_two_validation_rules']); } public function testGetValue() { - $validator = new class extends AbstractValidator { }; + $validator = new class () extends AbstractValidator { }; $values = [ 'a' => [ @@ -122,7 +358,7 @@ public function testGetValue() public function testGetValues() { - $validator = new class extends AbstractValidator { }; + $validator = new class () extends AbstractValidator { }; $values = [ 'a' => [ diff --git a/tests/Validator/Helper/StrTest.php b/tests/Validator/Helper/StrTest.php index 40970c3..21dfedf 100644 --- a/tests/Validator/Helper/StrTest.php +++ b/tests/Validator/Helper/StrTest.php @@ -1,5 +1,7 @@ expects($this->once()) ->method('addError') ->with($pattern, 'entity-exists', [':id' => null]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('entity-exists', $ruleName); }); @@ -71,6 +74,7 @@ public function getTestedData(): iterable '', ], $repositoryMock, + false, ]; $data = [ @@ -80,7 +84,7 @@ public function getTestedData(): iterable $validatorMock->expects($this->once()) ->method('addError') ->with($pattern, 'entity-exists', [':id' => '']) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('entity-exists', $ruleName); }); @@ -97,6 +101,7 @@ public function getTestedData(): iterable '', ], $repositoryMock, + false, ]; $data = [ @@ -106,7 +111,7 @@ public function getTestedData(): iterable $validatorMock->expects($this->once()) ->method('addError') ->with($pattern, 'entity-exists', [':id' => false]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('entity-exists', $ruleName); }); @@ -123,6 +128,7 @@ public function getTestedData(): iterable '', ], $repositoryMock, + false, ]; $orderStatusId = 555; @@ -133,7 +139,7 @@ public function getTestedData(): iterable $validatorMock->expects($this->once()) ->method('addError') ->with($pattern, 'entity-exists', [':id' => $orderStatusId]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('entity-exists', $ruleName); }); @@ -152,16 +158,26 @@ public function getTestedData(): iterable '', ], $repositoryMock, + false, ]; } /** * @dataProvider getTestedData */ - public function testValidate($validatorMock, $data, $pattern, $parameters, $repositoryMock) - { + public function testValidate( + AbstractValidator $validatorMock, + array $data, + string $pattern, + array $parameters, + RepositoryInterface $repositoryMock, + bool $validationResult + ) { $entityExistsRule = new EntityExists($repositoryMock); - $entityExistsRule->validate($validatorMock, $data, $pattern, $parameters); + $this->assertEquals( + $validationResult, + $entityExistsRule->validate($validatorMock, $data, $pattern, $parameters) + ); } } diff --git a/tests/Validator/Rules/GreaterThanTest.php b/tests/Validator/Rules/GreaterThanTest.php index 44d87fe..9312b6c 100644 --- a/tests/Validator/Rules/GreaterThanTest.php +++ b/tests/Validator/Rules/GreaterThanTest.php @@ -1,8 +1,11 @@ createMock(AbstractValidator::class); $validatorMock->expects($this->once()) ->method('getValue') @@ -67,13 +70,14 @@ public function getTestedData(): iterable $validatorMock->expects($this->never()) ->method('addError'); - yield 'value is correct' => [ + yield 'value is correct; value to compare is correct' => [ $validatorMock, $data, $pattern, 'parameters' => [ $fieldToComparePattern, ], + true, ]; $value = 3; @@ -92,9 +96,9 @@ public function getTestedData(): iterable ->method('addError') ->with($pattern, 'greater-than', [ ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue + ':valueToCompare' => $fieldToCompareValue, ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('greater-than', $ruleName); }); @@ -106,6 +110,7 @@ public function getTestedData(): iterable 'parameters' => [ $fieldToComparePattern, ], + false, ]; $data = [ @@ -126,9 +131,9 @@ public function getTestedData(): iterable ->method('addError') ->with($pattern, 'greater-than', [ ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue + ':valueToCompare' => $fieldToCompareValue, ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('greater-than', $ruleName); }); @@ -140,6 +145,7 @@ public function getTestedData(): iterable 'parameters' => [ $fieldToComparePattern, ], + false, ]; $fieldToCompareValue = null; @@ -153,26 +159,20 @@ public function getTestedData(): iterable $fieldToComparePattern, $fieldToCompareValue ); - $validatorMock->expects($this->once()) - ->method('addError') - ->with($pattern, 'greater-than', [ - ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue - ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { - $this->assertEquals($pattern, $field); - $this->assertEquals('greater-than', $ruleName); - }); + $validatorMock->expects($this->never()) + ->method('addError'); - yield 'value to compare is not sent' => [ + yield 'value is numeric; value to compare is not sent; nothing to compare' => [ $validatorMock, $data, $pattern, 'parameters' => [ $fieldToComparePattern, ], + false, ]; + $value = 0; $fieldToCompareValue = '0'; $data = [ $pattern => $value, @@ -185,16 +185,25 @@ public function getTestedData(): iterable $fieldToComparePattern, $fieldToCompareValue ); - $validatorMock->expects($this->never()) - ->method('addError'); + $validatorMock->expects($this->once()) + ->method('addError') + ->with($pattern, 'greater-than', [ + ':fieldToCompare' => $fieldToComparePattern, + ':valueToCompare' => $fieldToCompareValue, + ]) + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { + $this->assertEquals($pattern, $field); + $this->assertEquals('greater-than', $ruleName); + }); - yield 'value to compare is 0' => [ + yield 'value is numeric; value to compare is a numeric string; value is not greater than valueToCompare' => [ $validatorMock, $data, $pattern, 'parameters' => [ $fieldToComparePattern, ], + false, ]; $value = '0'; @@ -213,13 +222,14 @@ public function getTestedData(): iterable $validatorMock->expects($this->never()) ->method('addError'); - yield 'value is 0 and value to compare is -1' => [ + yield 'value is "0" and value to compare is "-1"; the value is not less than valueToCompare' => [ $validatorMock, $data, $pattern, 'parameters' => [ $fieldToComparePattern, ], + true, ]; $value = 'dagsh'; @@ -239,9 +249,9 @@ public function getTestedData(): iterable ->method('addError') ->with($pattern, 'greater-than', [ ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue + ':valueToCompare' => $fieldToCompareValue, ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('greater-than', $ruleName); }); @@ -253,6 +263,7 @@ public function getTestedData(): iterable 'parameters' => [ $fieldToComparePattern, ], + false, ]; $value = 5; @@ -268,33 +279,60 @@ public function getTestedData(): iterable $fieldToComparePattern, $fieldToCompareValue ); - $validatorMock->expects($this->once()) - ->method('addError') - ->with($pattern, 'greater-than', [ - ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue - ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { - $this->assertEquals($pattern, $field); - $this->assertEquals('greater-than', $ruleName); - }); + $validatorMock->expects($this->never()) + ->method('addError'); + + yield 'value is numeric; value to compare is not numeric; nothing to compare' => [ + $validatorMock, + $data, + $pattern, + 'parameters' => [ + $fieldToComparePattern, + ], + false, + ]; + + $fieldToCompareValue = ''; + $data = [ + $pattern => $value, + $fieldToComparePattern => $fieldToCompareValue, + ]; + $validatorMock = $this->createAbstractValidatorMock( + $data, + $pattern, + $value, + $fieldToComparePattern, + $fieldToCompareValue + ); + $validatorMock->expects($this->never()) + ->method('addError'); - yield 'value to compare is not numeric' => [ + yield 'value is numeric; value to compare is empty string; nothing to compare' => [ $validatorMock, $data, $pattern, 'parameters' => [ $fieldToComparePattern, ], + false, ]; } /** * @dataProvider getTestedData */ - public function testValidate($validator, $data, $pattern, $parameters) - { + public function testValidate( + AbstractValidator $validator, + array $data, + string $pattern, + array $parameters, + bool $validationResult + ) { $greaterThanRule = new GreaterThan(); - $greaterThanRule->validate($validator, $data, $pattern, $parameters); + + $this->assertEquals( + $validationResult, + $greaterThanRule->validate($validator, $data, $pattern, $parameters) + ); } } diff --git a/tests/Validator/Rules/LessThanTest.php b/tests/Validator/Rules/LessThanTest.php index b9287a5..2d45147 100644 --- a/tests/Validator/Rules/LessThanTest.php +++ b/tests/Validator/Rules/LessThanTest.php @@ -1,8 +1,11 @@ createMock(AbstractValidator::class); $validatorMock->expects($this->once()) ->method('getValue') @@ -67,13 +70,14 @@ public function getTestedData(): iterable $validatorMock->expects($this->never()) ->method('addError'); - yield 'value is correct' => [ + yield 'value is correct; value to compare is correct' => [ $validatorMock, $data, $pattern, 'parameters' => [ $fieldToComparePattern, ], + true, ]; $value = 5; @@ -92,9 +96,9 @@ public function getTestedData(): iterable ->method('addError') ->with($pattern, 'less-than', [ ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue + ':valueToCompare' => $fieldToCompareValue, ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('less-than', $ruleName); }); @@ -106,6 +110,7 @@ public function getTestedData(): iterable 'parameters' => [ $fieldToComparePattern, ], + false, ]; $data = [ @@ -126,9 +131,9 @@ public function getTestedData(): iterable ->method('addError') ->with($pattern, 'less-than', [ ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue + ':valueToCompare' => $fieldToCompareValue, ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('less-than', $ruleName); }); @@ -140,6 +145,7 @@ public function getTestedData(): iterable 'parameters' => [ $fieldToComparePattern, ], + false, ]; $fieldToCompareValue = null; @@ -153,24 +159,17 @@ public function getTestedData(): iterable $fieldToComparePattern, $fieldToCompareValue ); - $validatorMock->expects($this->once()) - ->method('addError') - ->with($pattern, 'less-than', [ - ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue - ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { - $this->assertEquals($pattern, $field); - $this->assertEquals('less-than', $ruleName); - }); + $validatorMock->expects($this->never()) + ->method('addError'); - yield 'value to compare is not sent' => [ + yield 'value is numeric; value to compare is not sent; nothing to compare' => [ $validatorMock, $data, $pattern, 'parameters' => [ $fieldToComparePattern, ], + false, ]; $fieldToCompareValue = '0'; @@ -189,20 +188,21 @@ public function getTestedData(): iterable ->method('addError') ->with($pattern, 'less-than', [ ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue + ':valueToCompare' => $fieldToCompareValue, ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('less-than', $ruleName); }); - yield 'value to compare is 0' => [ + yield 'value is numeric; value to compare is a numeric string; value is not less than valueToCompare' => [ $validatorMock, $data, $pattern, 'parameters' => [ $fieldToComparePattern, ], + false, ]; $value = '0'; @@ -222,20 +222,21 @@ public function getTestedData(): iterable ->method('addError') ->with($pattern, 'less-than', [ ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue + ':valueToCompare' => $fieldToCompareValue, ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('less-than', $ruleName); }); - yield 'value is 0 and value to compare is -1' => [ + yield 'value is "0" and value to compare is "-1"; the value is not less than valueToCompare' => [ $validatorMock, $data, $pattern, 'parameters' => [ $fieldToComparePattern, ], + false, ]; $value = 'dagsh'; @@ -255,9 +256,9 @@ public function getTestedData(): iterable ->method('addError') ->with($pattern, 'less-than', [ ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue + ':valueToCompare' => $fieldToCompareValue, ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('less-than', $ruleName); }); @@ -269,6 +270,7 @@ public function getTestedData(): iterable 'parameters' => [ $fieldToComparePattern, ], + false, ]; $value = 5; @@ -284,33 +286,60 @@ public function getTestedData(): iterable $fieldToComparePattern, $fieldToCompareValue ); - $validatorMock->expects($this->once()) - ->method('addError') - ->with($pattern, 'less-than', [ - ':fieldToCompare' => $fieldToComparePattern, - ':valueToCompare' => $fieldToCompareValue - ]) - ->willReturnCallback(function($field, $ruleName) use ($pattern) { - $this->assertEquals($pattern, $field); - $this->assertEquals('less-than', $ruleName); - }); + $validatorMock->expects($this->never()) + ->method('addError'); + + yield 'value is numeric; value to compare is not numeric; nothing to compare' => [ + $validatorMock, + $data, + $pattern, + 'parameters' => [ + $fieldToComparePattern, + ], + false, + ]; - yield 'value to compare is not numeric' => [ + $fieldToCompareValue = ''; + $data = [ + $pattern => $value, + $fieldToComparePattern => $fieldToCompareValue, + ]; + $validatorMock = $this->createAbstractValidatorMock( + $data, + $pattern, + $value, + $fieldToComparePattern, + $fieldToCompareValue + ); + $validatorMock->expects($this->never()) + ->method('addError'); + + yield 'value is numeric; value to compare is empty string; nothing to compare' => [ $validatorMock, $data, $pattern, 'parameters' => [ $fieldToComparePattern, ], + false, ]; } /** * @dataProvider getTestedData */ - public function testValidate($validator, $data, $pattern, $parameters) - { + public function testValidate( + AbstractValidator $validator, + array $data, + string $pattern, + array $parameters, + bool $validationResult + ) { $greaterThanRule = new LessThan(); - $greaterThanRule->validate($validator, $data, $pattern, $parameters); + + $this->assertEquals( + $validationResult, + $greaterThanRule->validate($validator, $data, $pattern, $parameters) + ); } } diff --git a/tests/Validator/Rules/MinTest.php b/tests/Validator/Rules/MinTest.php index 2604b38..0b20872 100644 --- a/tests/Validator/Rules/MinTest.php +++ b/tests/Validator/Rules/MinTest.php @@ -1,5 +1,7 @@ [ 5, ], + true, ]; $data = [ @@ -54,8 +57,9 @@ public function getTestedData(): iterable $validatorMock->expects($this->once()) ->method('addError') ->with($pattern, 'min', [':min' => 5, ':value' => 4]) - ->willReturnCallback(function() { - $this->assertTrue(true); + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { + $this->assertEquals($pattern, $field); + $this->assertEquals('min', $ruleName); }); yield 'value is less than has to be' => [ @@ -65,6 +69,7 @@ public function getTestedData(): iterable 'parameters' => [ 5, ], + false, ]; $data = []; @@ -72,8 +77,9 @@ public function getTestedData(): iterable $validatorMock->expects($this->once()) ->method('addError') ->with($pattern, 'min', [':min' => 5, ':value' => null]) - ->willReturnCallback(function() { - $this->assertTrue(true); + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { + $this->assertEquals($pattern, $field); + $this->assertEquals('min', $ruleName); }); yield 'value is not sent' => [ @@ -83,6 +89,7 @@ public function getTestedData(): iterable 'parameters' => [ 5, ], + false, ]; $data = [ @@ -92,8 +99,9 @@ public function getTestedData(): iterable $validatorMock->expects($this->once()) ->method('addError') ->with($pattern, 'min', [':min' => 5, ':value' => null]) - ->willReturnCallback(function() { - $this->assertTrue(true); + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { + $this->assertEquals($pattern, $field); + $this->assertEquals('min', $ruleName); }); yield 'value is null' => [ @@ -103,6 +111,7 @@ public function getTestedData(): iterable 'parameters' => [ 5, ], + false, ]; $data = [ @@ -119,6 +128,7 @@ public function getTestedData(): iterable 'parameters' => [ 5, ], + true, ]; $data = [ @@ -128,8 +138,9 @@ public function getTestedData(): iterable $validatorMock->expects($this->once()) ->method('addError') ->with($pattern, 'min', [':min' => 5, ':value' => '']) - ->willReturnCallback(function() { - $this->assertTrue(true); + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { + $this->assertEquals($pattern, $field); + $this->assertEquals('min', $ruleName); }); yield 'value is empty' => [ @@ -139,6 +150,7 @@ public function getTestedData(): iterable 'parameters' => [ 5, ], + false, ]; $data = [ @@ -148,8 +160,9 @@ public function getTestedData(): iterable $validatorMock->expects($this->once()) ->method('addError') ->with($pattern, 'min', [':min' => 5, ':value' => 'fewt']) - ->willReturnCallback(function() { - $this->assertTrue(true); + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { + $this->assertEquals($pattern, $field); + $this->assertEquals('min', $ruleName); }); yield 'value is not numeric' => [ @@ -159,6 +172,7 @@ public function getTestedData(): iterable 'parameters' => [ 5, ], + false, ]; } diff --git a/tests/Validator/Rules/RequiredTest.php b/tests/Validator/Rules/RequiredTest.php index 3a88274..01d7301 100644 --- a/tests/Validator/Rules/RequiredTest.php +++ b/tests/Validator/Rules/RequiredTest.php @@ -1,5 +1,7 @@ [ '', ], + true, ]; $value = [ @@ -67,6 +70,7 @@ public function getDataset(): iterable 'parameters' => [ '', ], + true, ]; $value = ''; @@ -77,7 +81,7 @@ public function getDataset(): iterable $validatorMock ->method('addError') ->with($pattern, 'required') - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('required', $ruleName); }); @@ -89,6 +93,7 @@ public function getDataset(): iterable 'parameters' => [ '', ], + false, ]; $value = null; @@ -99,7 +104,7 @@ public function getDataset(): iterable $validatorMock ->method('addError') ->with($pattern, 'required') - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('required', $ruleName); }); @@ -111,6 +116,7 @@ public function getDataset(): iterable 'parameters' => [ '', ], + false, ]; $value = false; @@ -121,7 +127,7 @@ public function getDataset(): iterable $validatorMock ->method('addError') ->with($pattern, 'required') - ->willReturnCallback(function($field, $ruleName) use ($pattern) { + ->willReturnCallback(function ($field, $ruleName) use ($pattern) { $this->assertEquals($pattern, $field); $this->assertEquals('required', $ruleName); }); @@ -133,6 +139,7 @@ public function getDataset(): iterable 'parameters' => [ '', ], + false, ]; }