diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aba44fa..54414bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,22 +10,34 @@ on: jobs: php-tests: runs-on: ${{ matrix.os }} + name: ${{ matrix.label }} strategy: matrix: include: + - php: '8.4' + os: 'ubuntu-latest' + config: 'phpunit.xml.dist' + label: 'PHP 8.4 · PHPUnit 13' - php: '8.3' os: 'ubuntu-latest' + config: 'phpunit.xml.dist' + label: 'PHP 8.3 · PHPUnit 12' - php: '8.2' os: 'ubuntu-latest' + config: 'phpunit.xml.dist' + label: 'PHP 8.2 · PHPUnit 11' + - php: '8.1' + os: 'ubuntu-latest' + config: 'phpunit.xml.dist' + coverage: true + label: 'PHP 8.1 · PHPUnit 10' - php: '8.1' os: 'ubuntu-latest' - - php: '8.0' - os: 'ubuntu-24.04' - - php: '7.4' - os: 'ubuntu-24.04' + config: 'phpunit.xml.dist' + composer_flags: '--prefer-lowest' + label: 'PHP 8.1 · PHPUnit 10 (lowest deps)' fail-fast: false env: - COVERAGE_CACHE_PATH: phpunit-coverage-cache PHP_VERSION: ${{ matrix.php }} steps: @@ -39,86 +51,92 @@ jobs: - name: Get Composer cache directory id: composer-cache - run: | - echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-php${{ matrix.php }}-composer-${{ matrix.composer_flags }}-${{ hashFiles('composer.json') }} restore-keys: | - ${{ runner.os }}-composer- + ${{ runner.os }}-php${{ matrix.php }}-composer- + # Resolve dependencies per PHP version: a single committed lock cannot satisfy + # every supported PHP/PHPUnit pair (PHPUnit 10–13 span PHP 8.1–8.4), so each leg + # updates to the highest PHPUnit its PHP allows (Composer picks 10/11/12/13). - name: Install dependencies - run: composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist + run: composer update ${{ matrix.composer_flags }} --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist - - name: Restore phpunit coverage cache - uses: actions/cache@v4 - with: - path: ${{ env.COVERAGE_CACHE_PATH }} - key: ${{ runner.os }}-coverage-${{ github.ref }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-coverage-${{ github.ref }}- - ${{ runner.os }}-coverage- + # Tests should be run randomly to catch any test dependency issue. + - name: Execute tests with PHPUnit + if: ${{ !matrix.coverage }} + run: vendor/bin/phpunit -c ${{ matrix.config }} --order-by=random - name: Execute tests with PHPUnit and output code coverage report - env: - DB_CONNECTION: sqlite - DB_DATABASE: database/database.sqlite - # Generate coverage file, so it can be uploaded later if we choose. - # Otherwise, current coverage can be viewed in the action output. - # Tests should be run randomly to catch any test dependency issue. - run: | - vendor/bin/phpunit --order-by="random" --coverage-cache="$COVERAGE_CACHE_PATH" --coverage-clover=./clover.xml --coverage-text + if: ${{ matrix.coverage }} + run: vendor/bin/phpunit -c ${{ matrix.config }} --order-by=random --coverage-clover=./clover.xml --coverage-text - name: Upload test coverage results to Coveralls - if: ${{ env.PHP_VERSION == '8.1' }} + if: ${{ matrix.coverage }} env: COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - vendor/bin/php-coveralls --coverage_clover="./clover.xml" --json_path="./coveralls-upload.json" -v + run: vendor/bin/php-coveralls --coverage_clover="./clover.xml" --json_path="./coveralls-upload.json" -v php-compatibility: runs-on: ubuntu-latest + name: PHP compatibility (8.1+) steps: - uses: actions/checkout@v4 + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + coverage: none + - name: Get Composer Cache Directory id: composer-cache - run: | - echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-phpcompat-composer-${{ hashFiles('composer.json') }} restore-keys: | - ${{ runner.os }}-composer- + ${{ runner.os }}-phpcompat-composer- - name: Install Dependencies - run: composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --ignore-platform-req php + run: composer update --no-ansi --no-interaction --no-progress --prefer-dist --ignore-platform-req=php - name: Run PHP Code Sniffer using the PHPCompatibility standard run: vendor/bin/phpcs php-static-analysis: runs-on: ubuntu-latest + name: Static analysis steps: - uses: actions/checkout@v4 + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + coverage: none + - name: Get Composer Cache Directory id: composer-cache - run: | - echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-phpstan-composer-${{ hashFiles('composer.json') }} restore-keys: | - ${{ runner.os }}-composer- + ${{ runner.os }}-phpstan-composer- + - name: Install Dependencies - run: | - composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist + run: composer update --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist + - name: Run phpstan - run: vendor/bin/phpstan \ No newline at end of file + run: vendor/bin/phpstan analyse --no-progress diff --git a/CHANGELOG.md b/CHANGELOG.md index e05343c..8e57578 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.0](https://github.com/10up/wp_mock/compare/1.1.1...2.0.0) - Unreleased + +WP_Mock 2.0 modernizes the test harness for current PHPUnit. It now **requires PHP 8.1+ and PHPUnit 10+**, and supports **PHPUnit 10, 11, 12 and 13** from a single codebase; Composer installs the highest PHPUnit version your PHP allows. The public assertion API is unchanged, so most projects on a supported PHP/PHPUnit upgrade by bumping only `10up/wp_mock` — see [UPGRADE.md](https://github.com/10up/wp_mock/blob/trunk/UPGRADE.md). + +### Added +- `TestCase::assertOutputEqualsHtml(string $expectedHtml, callable $callback)` for whitespace-insensitive assertions on echoed HTML output + +### Changed +- **BREAKING:** raised the minimum PHP version to **8.1** (was 7.4) and dropped support for **PHPUnit 9**. Projects on PHP 7.4/8.0, or pinned to PHPUnit 9, should stay on WP_Mock 1.x. +- **BREAKING:** deprecated WP_Mock methods now emit a native `E_USER_DEPRECATED` notice (via `trigger_error()`) instead of forcing a test to be marked "risky". Set `failOnDeprecation="true"` in your PHPUnit configuration to fail tests on these. +- **BREAKING:** removed the implicit output filtering and the `@stripTabsAndNewlinesFromOutput` annotation — including the `TestCase::expectOutputString()` override — because PHPUnit 10 removed `setOutputCallback()` and made `expectOutputString()` `final`. Use `assertOutputEqualsHtml()` (or PHPUnit's native `expectOutputString()` for exact matches). +- `IsEqualHtml` now implements `matches()`/`toString()` and takes a single constructor argument +- Internal test metadata moved to PHP 8 attributes (`#[DataProvider]`, `#[CoversClass]`, …); doc-comment annotations were removed (they no longer work on PHPUnit 12+) +- Raised minimum dependencies: `mockery/mockery ^1.6.12`, PHPStan tooling to `^2` + +### Removed +- The abandoned `sempro/phpunit-pretty-print` dev dependency (use `--testdox`) +- `DeprecatedMethodListener::setTestResult()`, `setTestCase()`, `checkCalls()` and the `TestCase::run()` override (relied on PHPUnit's removed `TestResult`/`RiskyTestError`) + +### Fixed +- `WP_Mock::expectFilterNotAdded()` defaulted `$args` to `10` instead of `1`, so the "not added" expectation never matched a standard `add_filter()` call and silently passed; it now correctly guards the hook + ## [1.1.1](https://github.com/10up/wp_mock/compare/1.1.0...1.1.1) - 2025-12-03 ### Fixed - Address PHP deprecation warnings about implicitly nullable parameters diff --git a/README.md b/README.md index 1ffe370..73d8e8e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > WP_Mock is an API mocking framework, built and maintained by [10up](https://10up.com) and [GoDaddy](https://godaddy.com) for the purpose of making it possible to properly unit test within a WordPress project. -![Support Level][support-level-image] ![PHP 7.4+][php-image] [![Coverage Status][coveralls-image]][coveralls-url] [![Packagist][packagist-image]][packagist-url] [![BSD-3-Clause License][license-image]][license-url] +![Support Level][support-level-image] ![PHP 8.1+][php-image] [![Coverage Status][coveralls-image]][coveralls-url] [![Packagist][packagist-image]][packagist-url] [![BSD-3-Clause License][license-image]][license-url] ## Installation @@ -39,7 +39,7 @@ A special thanks to all [WP_Mock contributors](https://github.com/10up/wp_mock/b [support-level-image]: https://img.shields.io/badge/support-active-green.svg -[php-image]: https://img.shields.io/badge/php-7.4%2B-green.svg +[php-image]: https://img.shields.io/badge/php-8.1%2B-green.svg [packagist-image]: https://img.shields.io/packagist/dt/10up/wp_mock.svg [packagist-url]: https://packagist.org/packages/10up/wp_mock [coveralls-image]: https://coveralls.io/repos/github/10up/wp_mock/badge.svg?branch=trunk diff --git a/UPGRADE.md b/UPGRADE.md new file mode 100644 index 0000000..d39b34d --- /dev/null +++ b/UPGRADE.md @@ -0,0 +1,62 @@ +# Upgrade Guide + +## 1.x → 2.0 + +WP_Mock 2.0 modernizes the test harness for current PHPUnit. The headline change is a higher floor: + +> **WP_Mock 2.0 requires PHP 8.1+ and PHPUnit 10+.** +> If your project runs on **PHP 7.4 or 8.0**, or is pinned to **PHPUnit 9**, stay on WP_Mock **1.x** — it continues to work. WP_Mock 2.0 supports PHPUnit 10, 11, 12 and 13 from a single codebase. + +Composer installs the highest PHPUnit version compatible with your PHP: + +| Your PHP | PHPUnit installed | +|----------|-------------------| +| 8.1 | 10 | +| 8.2 | 11 | +| 8.3 | 12 | +| 8.4 | 13 | + +For most projects on a supported PHP/PHPUnit, upgrading is just: + +```shell +composer require --dev 10up/wp_mock:^2.0 +``` + +The public assertion API (`assertConditionsMet()`, `assertHooksAdded()`, `assertActionsCalled()`, `assertEqualsHtml()`, `mockStaticMethod()`, …) is unchanged. + +There are two behavior changes to be aware of. + +### 1. Deprecated-method detection + +If you (or your tooling) relied on WP_Mock marking a test **risky** when a deprecated WP_Mock method was called, that signal is now a native PHP **deprecation** (`E_USER_DEPRECATED`) surfaced through PHPUnit's own deprecation reporting. + +To make these fail your test suite, set `failOnDeprecation="true"` on the root `` element of your configuration. With default configuration, the deprecation is reported but does not fail the run. + +### 2. Output assertions + +Earlier versions overrode PHPUnit's `expectOutputString()` to automatically strip tabs and newlines from output (toggled with the `@stripTabsAndNewlinesFromOutput` annotation). PHPUnit 10 removed `setOutputCallback()` and made `expectOutputString()` `final`, so this is no longer possible. + +If you relied on that whitespace-insensitive output matching, switch to the new helper: + +```php +// Before (1.x): output was silently stripped of tabs/newlines before comparison +$this->expectOutputString('
Test
'); +my_function_that_echoes_html(); + +// After (2.0): wrap the output-producing code in a callback +$this->assertOutputEqualsHtml('
Test
', static function () { + my_function_that_echoes_html(); +}); +``` + +PHPUnit's native `expectOutputString()` is still available if you want an **exact** (whitespace-sensitive) match. + +### Removed internals + +These were internal/rarely-used and are gone in 2.0 (they depended on PHPUnit APIs removed in PHPUnit 10): + +- `WP_Mock\DeprecatedMethodListener::setTestResult()`, `setTestCase()`, `checkCalls()` +- The `WP_Mock\Tools\TestCase::run()` override +- The `@stripTabsAndNewlinesFromOutput` annotation and `TestCase::stripTabsAndNewlines()` + +`WP_Mock::getDeprecatedMethodListener()` and `DeprecatedMethodListener::logDeprecatedCall()` remain available. diff --git a/composer.json b/composer.json index 38108df..57cff23 100644 --- a/composer.json +++ b/composer.json @@ -4,24 +4,22 @@ "license": "BSD-3-Clause", "prefer-stable": true, "require": { - "php": ">=7.4 < 9", - "phpunit/phpunit": "^9.6", - "mockery/mockery": "^1.6", - "antecedent/patchwork": "^2.1" + "php": ">=8.1", + "phpunit/phpunit": "^10 || ^11 || ^12 || ^13", + "mockery/mockery": "^1.6.12", + "antecedent/patchwork": "^2.1.27" }, "require-dev": { "behat/behat": "^v3.11.0", - "sebastian/comparator": "^4.0.8", "php-coveralls/php-coveralls": "^v2.7", - "sempro/phpunit-pretty-print": "^1.4", - "phpstan/phpstan": "^1.10", - "phpstan/phpstan-phpunit": "^1.3", - "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-mockery": "^2.0", "phpcompatibility/php-compatibility": "^9.3", "php-stubs/wordpress-globals": "^0.2", "php-stubs/wordpress-stubs": "^6.3", "friendsofphp/php-cs-fixer": "^3.4", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7" + "dealerdirect/phpcodesniffer-composer-installer": "^1.0" }, "autoload": { "psr-4": { @@ -40,17 +38,14 @@ ] }, "config": { - "platform": { - "php": "7.4" - }, "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true } }, "scripts": { "test:behat": "behat", - "test:phpunit": "phpunit", - "test:phpunitcov": "phpunit --coverage-clover build/logs/clover.xml", + "test:phpunit": "phpunit --testdox", + "test:phpunitcov": "phpunit --testdox --coverage-clover build/logs/clover.xml", "test": [ "@test:behat", "@test:phpunit" diff --git a/composer.lock b/composer.lock index 0104ad1..cbec9dd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,24 +4,24 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a1855a9cad4977b6e16eb92ce3a72929", + "content-hash": "320f46c0020de661db877e853eabd0e4", "packages": [ { "name": "antecedent/patchwork", - "version": "2.1.27", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/antecedent/patchwork.git", - "reference": "16a1ab81559aabf14acb616141e801b32777f085" + "reference": "8b6b235f405af175259c8f56aea5fc23ab9f03ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/antecedent/patchwork/zipball/16a1ab81559aabf14acb616141e801b32777f085", - "reference": "16a1ab81559aabf14acb616141e801b32777f085", + "url": "https://api.github.com/repos/antecedent/patchwork/zipball/8b6b235f405af175259c8f56aea5fc23ab9f03ce", + "reference": "8b6b235f405af175259c8f56aea5fc23ab9f03ce", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": ">=7.1.0" }, "require-dev": { "phpunit/phpunit": ">=4" @@ -50,96 +50,26 @@ ], "support": { "issues": "https://github.com/antecedent/patchwork/issues", - "source": "https://github.com/antecedent/patchwork/tree/2.1.27" - }, - "time": "2023-12-03T18:46:49+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" + "source": "https://github.com/antecedent/patchwork/tree/2.2.3" }, - "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" + "time": "2025-09-17T09:00:56+00:00" }, { "name": "hamcrest/hamcrest-php", - "version": "v2.0.1", + "version": "v2.1.1", "source": { "type": "git", "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", "shasum": "" }, "require": { - "php": "^5.3|^7.0|^8.0" + "php": "^7.4|^8.0" }, "replace": { "cordoval/hamcrest-php": "*", @@ -147,8 +77,8 @@ "kodova/hamcrest-php": "*" }, "require-dev": { - "phpunit/php-file-iterator": "^1.4 || ^2.0", - "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" }, "type": "library", "extra": { @@ -171,22 +101,22 @@ ], "support": { "issues": "https://github.com/hamcrest/hamcrest-php/issues", - "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" }, - "time": "2020-07-09T08:09:16+00:00" + "time": "2025-04-30T06:54:44+00:00" }, { "name": "mockery/mockery", - "version": "1.6.7", + "version": "1.6.12", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06" + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06", - "reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", "shasum": "" }, "require": { @@ -198,8 +128,8 @@ "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.6.10", - "symplify/easy-coding-standard": "^12.0.8" + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" }, "type": "library", "autoload": { @@ -256,20 +186,20 @@ "security": "https://github.com/mockery/mockery/security/advisories", "source": "https://github.com/mockery/mockery" }, - "time": "2023-12-10T02:24:34+00:00" + "time": "2024-05-16T03:13:13+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -277,11 +207,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -307,7 +238,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -315,29 +246,31 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "nikic/php-parser", - "version": "v4.18.0", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.0" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -345,7 +278,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -369,26 +302,27 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2023-12-10T21:03:43+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", @@ -429,9 +363,15 @@ "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" + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", @@ -486,35 +426,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.30", + "version": "14.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" + "reference": "10d7da3628a99289cdf4c662dd7f0d73f1baec83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/10d7da3628a99289cdf4c662dd7f0d73f1baec83", + "reference": "10d7da3628a99289cdf4c662dd7f0d73f1baec83", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", + "ext-mbstring": "*", "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" + "nikic/php-parser": "^5.7.0", + "php": ">=8.4", + "phpunit/php-text-template": "^6.0", + "sebastian/complexity": "^6.0", + "sebastian/environment": "^9.3.2", + "sebastian/git-state": "^1.0", + "sebastian/lines-of-code": "^5.0.1", + "sebastian/version": "^7.0", + "theseer/tokenizer": "^2.0.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.2.0" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -523,7 +463,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "14.2.x-dev" } }, "autoload": { @@ -552,40 +492,52 @@ "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" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/14.2.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" } ], - "time": "2023-12-22T06:47:57+00:00" + "time": "2026-06-08T11:50:38+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "version": "7.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "6e5aa1fb0a95b1703d83e721299ee18bb4e2de50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6e5aa1fb0a95b1703d83e721299ee18bb4e2de50", + "reference": "6e5aa1fb0a95b1703d83e721299ee18bb4e2de50", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -612,36 +564,49 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/7.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", + "type": "tidelift" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2026-02-06T04:33:26+00:00" }, { "name": "phpunit/php-invoker", - "version": "3.1.1", + "version": "7.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "reference": "42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88", + "reference": "42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.0" }, "suggest": { "ext-pcntl": "*" @@ -649,7 +614,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -675,40 +640,53 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/7.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-invoker", + "type": "tidelift" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2026-02-06T04:34:47+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.4", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "reference": "a47af19f93f76aa3368303d752aa5272ca3299f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/a47af19f93f76aa3368303d752aa5272ca3299f4", + "reference": "a47af19f93f76aa3368303d752aa5272ca3299f4", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -734,40 +712,53 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/6.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-text-template", + "type": "tidelift" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2026-02-06T04:36:37+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "9.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "a0e12065831f6ab0d83120dc61513eb8d9a966f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/a0e12065831f6ab0d83120dc61513eb8d9a966f6", + "reference": "a0e12065831f6ab0d83120dc61513eb8d9a966f6", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "9.0-dev" } }, "autoload": { @@ -793,62 +784,72 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/9.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-timer", + "type": "tidelift" } ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2026-02-06T04:37:53+00:00" }, { "name": "phpunit/phpunit", - "version": "9.6.15", + "version": "13.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" + "reference": "60da0ff1e10a0f72ee18a24117ec3b613a346bba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/60da0ff1e10a0f72ee18a24117ec3b613a346bba", + "reference": "60da0ff1e10a0f72ee18a24117ec3b613a346bba", "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" + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.4.1", + "phpunit/php-code-coverage": "^14.2.2", + "phpunit/php-file-iterator": "^7.0.0", + "phpunit/php-invoker": "^7.0.0", + "phpunit/php-text-template": "^6.0.0", + "phpunit/php-timer": "^9.0.0", + "sebastian/cli-parser": "^5.0.0", + "sebastian/comparator": "^8.3.0", + "sebastian/diff": "^9.0", + "sebastian/environment": "^9.3.2", + "sebastian/exporter": "^8.1.0", + "sebastian/file-filter": "^1.0", + "sebastian/git-state": "^1.0", + "sebastian/global-state": "^9.0.1", + "sebastian/object-enumerator": "^8.0.0", + "sebastian/recursion-context": "^8.0.0", + "sebastian/type": "^7.0.1", + "sebastian/version": "^7.0.0", + "staabm/side-effects-detector": "^1.0.5" }, "bin": [ "phpunit" @@ -856,7 +857,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-main": "13.2-dev" } }, "autoload": { @@ -888,48 +889,40 @@ "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.15" + "source": "https://github.com/sebastianbergmann/phpunit/tree/13.2.1" }, "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" + "url": "https://phpunit.de/sponsoring.html", + "type": "other" } ], - "time": "2023-12-01T16:55:19+00:00" + "time": "2026-06-15T13:14:22+00:00" }, { "name": "sebastian/cli-parser", - "version": "1.0.1", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "reference": "48a4654fa5e48c1c81214e9930048a572d4b23ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/48a4654fa5e48c1c81214e9930048a572d4b23ca", + "reference": "48a4654fa5e48c1c81214e9930048a572d4b23ca", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -952,153 +945,60 @@ "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" + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/5.0.0" }, "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": [ + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, { - "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://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser", + "type": "tidelift" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2026-02-06T04:39:44+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "8.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "c025fc7604afab3f195fab7cdaf72327331af241" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/c025fc7604afab3f195fab7cdaf72327331af241", + "reference": "c025fc7604afab3f195fab7cdaf72327331af241", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.4", + "sebastian/diff": "^9.0", + "sebastian/exporter": "^8.1.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.2" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "8.3-dev" } }, "autoload": { @@ -1137,41 +1037,54 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/8.3.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2026-06-05T03:06:45+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.3", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + "reference": "c5651c795c98093480df79350cb050813fc7a2f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c5651c795c98093480df79350cb050813fc7a2f3", + "reference": "c5651c795c98093480df79350cb050813fc7a2f3", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "nikic/php-parser": "^5.0", + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1194,41 +1107,54 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/6.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/complexity", + "type": "tidelift" } ], - "time": "2023-12-22T06:19:30+00:00" + "time": "2026-02-06T04:41:32+00:00" }, { "name": "sebastian/diff", - "version": "4.0.5", + "version": "9.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + "reference": "a3fb6a298a265ff487a91bbea46e03cd01dbb226" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/a3fb6a298a265ff487a91bbea46e03cd01dbb226", + "reference": "a3fb6a298a265ff487a91bbea46e03cd01dbb226", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^13.2", + "symfony/process": "^7.4.13" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "9.0-dev" } }, "autoload": { @@ -1260,35 +1186,48 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/9.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/diff", + "type": "tidelift" } ], - "time": "2023-05-07T05:35:17+00:00" + "time": "2026-06-05T03:04:51+00:00" }, { "name": "sebastian/environment", - "version": "5.1.5", + "version": "9.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "reference": "6c9e487c9eb706a8d258102a1c0b0a3e53e86c2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6c9e487c9eb706a8d258102a1c0b0a3e53e86c2e", + "reference": "6c9e487c9eb706a8d258102a1c0b0a3e53e86c2e", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.1.11" }, "suggest": { "ext-posix": "*" @@ -1296,7 +1235,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-main": "9.3-dev" } }, "autoload": { @@ -1315,7 +1254,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -1323,42 +1262,55 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/9.3.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" } ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2026-05-25T13:41:38+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.5", + "version": "8.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + "reference": "c0d29a945f8cf82f300a05e69874508e307ca4c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c0d29a945f8cf82f300a05e69874508e307ca4c6", + "reference": "c0d29a945f8cf82f300a05e69874508e307ca4c6", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "ext-mbstring": "*", + "php": ">=8.4", + "sebastian/recursion-context": "^8.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.1.10" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "8.1-dev" } }, "autoload": { @@ -1400,46 +1352,53 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/8.1.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2022-09-14T06:03:37+00:00" + "time": "2026-05-21T11:50:56+00:00" }, { - "name": "sebastian/global-state", - "version": "5.0.6", + "name": "sebastian/file-filter", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" + "url": "https://github.com/sebastianbergmann/file-filter.git", + "reference": "33a26f394330f6faa7684bb9cc73afb7727aae93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", + "url": "https://api.github.com/repos/sebastianbergmann/file-filter/zipball/33a26f394330f6faa7684bb9cc73afb7727aae93", + "reference": "33a26f394330f6faa7684bb9cc73afb7727aae93", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.4" }, "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^13.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "1.0-dev" } }, "autoload": { @@ -1454,51 +1413,61 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], + "description": "Library for filtering files", + "homepage": "https://github.com/sebastianbergmann/file-filter", "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" + "issues": "https://github.com/sebastianbergmann/file-filter/issues", + "security": "https://github.com/sebastianbergmann/file-filter/security/policy", + "source": "https://github.com/sebastianbergmann/file-filter/tree/1.0.0" }, "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", + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/file-filter", + "type": "tidelift" + } + ], + "time": "2026-04-22T07:20:04+00:00" + }, + { + "name": "sebastian/git-state", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + "url": "https://github.com/sebastianbergmann/git-state.git", + "reference": "792a952e0eba55b6960a48aeceb9f371aad1f76b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "url": "https://api.github.com/repos/sebastianbergmann/git-state/zipball/792a952e0eba55b6960a48aeceb9f371aad1f76b", + "reference": "792a952e0eba55b6960a48aeceb9f371aad1f76b", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "1.0-dev" } }, "autoload": { @@ -1517,46 +1486,60 @@ "role": "lead" } ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "description": "Library for describing the state of a Git checkout", + "homepage": "https://github.com/sebastianbergmann/git-state", "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + "issues": "https://github.com/sebastianbergmann/git-state/issues", + "security": "https://github.com/sebastianbergmann/git-state/security/policy", + "source": "https://github.com/sebastianbergmann/git-state/tree/1.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/git-state", + "type": "tidelift" } ], - "time": "2023-12-22T06:20:34+00:00" + "time": "2026-03-21T12:54:28+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "4.0.4", + "name": "sebastian/global-state", + "version": "9.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "ba68ba79da690cf7eddefd3ce5b78b20b9ba9945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/ba68ba79da690cf7eddefd3ce5b78b20b9ba9945", + "reference": "ba68ba79da690cf7eddefd3ce5b78b20b9ba9945", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.4", + "sebastian/object-reflector": "^6.0", + "sebastian/recursion-context": "^8.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "ext-dom": "*", + "phpunit/phpunit": "^13.1.13" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "9.0-dev" } }, "autoload": { @@ -1574,44 +1557,61 @@ "email": "sebastian@phpunit.de" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/9.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2026-06-01T15:11:33+00:00" }, { - "name": "sebastian/object-reflector", - "version": "2.0.4", + "name": "sebastian/lines-of-code", + "version": "5.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d2cff273a90c79b0eb590baa682d4b5c318bdbb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d2cff273a90c79b0eb590baa682d4b5c318bdbb7", + "reference": "d2cff273a90c79b0eb590baa682d4b5c318bdbb7", "shasum": "" }, "require": { - "php": ">=7.3" + "nikic/php-parser": "^5.7.0", + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.1.10" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1626,47 +1626,63 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "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/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/5.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/lines-of-code", + "type": "tidelift" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2026-05-19T16:23:37+00:00" }, { - "name": "sebastian/recursion-context", - "version": "4.0.5", + "name": "sebastian/object-enumerator", + "version": "8.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "b39ab125fd9a7434b0ecbc4202eebce11a98cfc5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/b39ab125fd9a7434b0ecbc4202eebce11a98cfc5", + "reference": "b39ab125fd9a7434b0ecbc4202eebce11a98cfc5", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4", + "sebastian/object-reflector": "^6.0", + "sebastian/recursion-context": "^8.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^13.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "8.0-dev" } }, "autoload": { @@ -1682,54 +1698,127 @@ { "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", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" }, { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" }, { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/object-enumerator", + "type": "tidelift" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", + "time": "2026-02-06T04:46:36+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "3ca042c2c60b0eab094f8a1b6a7093f4d4c72200" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/3ca042c2c60b0eab094f8a1b6a7093f4d4c72200", + "reference": "3ca042c2c60b0eab094f8a1b6a7093f4d4c72200", + "shasum": "" + }, + "require": { + "php": ">=8.4" + }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.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/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/6.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/object-reflector", + "type": "tidelift" } ], - "time": "2023-02-03T06:07:39+00:00" + "time": "2026-02-06T04:47:13+00:00" }, { - "name": "sebastian/resource-operations", - "version": "3.0.3", + "name": "sebastian/recursion-context", + "version": "8.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "74c5af21f6a5833e91767ca068c4d3dfec15317e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/74c5af21f6a5833e91767ca068c4d3dfec15317e", + "reference": "74c5af21f6a5833e91767ca068c4d3dfec15317e", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^13.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "8.0-dev" } }, "autoload": { @@ -1745,46 +1834,67 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/8.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2026-02-06T04:51:28+00:00" }, { "name": "sebastian/type", - "version": "3.2.1", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "reference": "fee0309275847fefd7636167085e379c1dbf6990" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fee0309275847fefd7636167085e379c1dbf6990", + "reference": "fee0309275847fefd7636167085e379c1dbf6990", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^13.1.10" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -1807,37 +1917,50 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/7.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2026-05-20T06:49:11+00:00" }, { "name": "sebastian/version", - "version": "3.0.2", + "version": "7.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "reference": "ad37a5552c8e2b88572249fdc19b6da7792e021b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ad37a5552c8e2b88572249fdc19b6da7792e021b", + "reference": "ad37a5552c8e2b88572249fdc19b6da7792e021b", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -1860,35 +1983,100 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/7.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/version", + "type": "tidelift" + } + ], + "time": "2026-02-06T04:52:52+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2024-10-20T05:08:20+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.2", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/7989e43bf381af0eac72e4f0ca5bcbfa81658be4", + "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" + "php": "^8.1" }, "type": "library", "autoload": { @@ -1910,7 +2098,7 @@ "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" + "source": "https://github.com/theseer/tokenizer/tree/2.0.1" }, "funding": [ { @@ -1918,43 +2106,49 @@ "type": "github" } ], - "time": "2023-11-20T00:12:19+00:00" + "time": "2025-12-08T11:19:18+00:00" } ], "packages-dev": [ { "name": "behat/behat", - "version": "v3.13.0", + "version": "v3.32.0", "source": { "type": "git", "url": "https://github.com/Behat/Behat.git", - "reference": "9dd7cdb309e464ddeab095cd1a5151c2dccba4ab" + "reference": "b9b89cf7a3b24c04d6e2d2865ed51bc5e1700de9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Behat/zipball/9dd7cdb309e464ddeab095cd1a5151c2dccba4ab", - "reference": "9dd7cdb309e464ddeab095cd1a5151c2dccba4ab", + "url": "https://api.github.com/repos/Behat/Behat/zipball/b9b89cf7a3b24c04d6e2d2865ed51bc5e1700de9", + "reference": "b9b89cf7a3b24c04d6e2d2865ed51bc5e1700de9", "shasum": "" }, "require": { - "behat/gherkin": "^4.9.0", - "behat/transliterator": "^1.2", + "behat/gherkin": "^4.17.0", + "composer-runtime-api": "^2.2", + "composer/xdebug-handler": "^1.4 || ^2.0 || ^3.0", "ext-mbstring": "*", - "php": "^7.2 || ^8.0", + "nikic/php-parser": "^4.19.2 || ^5.2", + "php": ">=8.2 <8.6", "psr/container": "^1.0 || ^2.0", - "symfony/config": "^4.4 || ^5.0 || ^6.0", - "symfony/console": "^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/translation": "^4.4 || ^5.0 || ^6.0", - "symfony/yaml": "^4.4 || ^5.0 || ^6.0" + "symfony/config": "^5.4 || ^6.4 || ^7.0", + "symfony/console": "^5.4.9 || ^6.4 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", + "symfony/translation": "^5.4 || ^6.4 || ^7.0", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" }, "require-dev": { - "herrera-io/box": "~1.6.1", - "phpspec/prophecy": "^1.15", - "phpunit/phpunit": "^8.5 || ^9.0", - "symfony/process": "^4.4 || ^5.0 || ^6.0", - "vimeo/psalm": "^4.8" + "opis/json-schema": "^2.5", + "php-cs-fixer/shim": "^3.89", + "phpstan/phpstan": "2.1.46", + "phpunit/phpunit": "^9.6", + "rector/rector": "2.3.9", + "sebastian/diff": "^4.0", + "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", + "symfony/polyfill-php84": "^1.31", + "symfony/process": "^5.4 || ^6.4 || ^7.0" }, "suggest": { "ext-dom": "Needed to output test results in JUnit format." @@ -1963,17 +2157,14 @@ "bin/behat" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "autoload": { "psr-4": { "Behat\\Hook\\": "src/Behat/Hook/", "Behat\\Step\\": "src/Behat/Step/", "Behat\\Behat\\": "src/Behat/Behat/", - "Behat\\Testwork\\": "src/Behat/Testwork/" + "Behat\\Config\\": "src/Behat/Config/", + "Behat\\Testwork\\": "src/Behat/Testwork/", + "Behat\\Transformation\\": "src/Behat/Transformation/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1988,7 +2179,7 @@ } ], "description": "Scenario-oriented BDD framework for PHP", - "homepage": "http://behat.org/", + "homepage": "https://behat.org/", "keywords": [ "Agile", "BDD", @@ -2005,31 +2196,51 @@ ], "support": { "issues": "https://github.com/Behat/Behat/issues", - "source": "https://github.com/Behat/Behat/tree/v3.13.0" + "source": "https://github.com/Behat/Behat/tree/v3.32.0" }, - "time": "2023-04-18T15:40:53+00:00" + "funding": [ + { + "url": "https://github.com/acoulton", + "type": "github" + }, + { + "url": "https://github.com/carlos-granados", + "type": "github" + }, + { + "url": "https://github.com/stof", + "type": "github" + } + ], + "time": "2026-06-20T08:34:52+00:00" }, { "name": "behat/gherkin", - "version": "v4.9.0", + "version": "v4.17.0", "source": { "type": "git", "url": "https://github.com/Behat/Gherkin.git", - "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4" + "reference": "5c8b3149fac39b5a79942b64eeec59a5ee4001c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/0bc8d1e30e96183e4f36db9dc79caead300beff4", - "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/5c8b3149fac39b5a79942b64eeec59a5ee4001c0", + "reference": "5c8b3149fac39b5a79942b64eeec59a5ee4001c0", "shasum": "" }, "require": { - "php": "~7.2|~8.0" + "composer-runtime-api": "^2.2", + "php": ">=8.1 <8.6" }, "require-dev": { - "cucumber/cucumber": "dev-gherkin-22.0.0", - "phpunit/phpunit": "~8|~9", - "symfony/yaml": "~3|~4|~5" + "cucumber/gherkin-monorepo": "dev-gherkin-v39.1.0", + "friendsofphp/php-cs-fixer": "^3.77", + "mikey179/vfsstream": "^1.6", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^2", + "phpstan/phpstan-phpunit": "^2", + "phpunit/phpunit": "^10.5", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" }, "suggest": { "symfony/yaml": "If you want to parse features, represented in YAML files" @@ -2041,8 +2252,8 @@ } }, "autoload": { - "psr-0": { - "Behat\\Gherkin": "src/" + "psr-4": { + "Behat\\Gherkin\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2053,11 +2264,11 @@ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "homepage": "https://everzet.com" } ], "description": "Gherkin DSL parser for PHP", - "homepage": "http://behat.org/", + "homepage": "https://behat.org/", "keywords": [ "BDD", "Behat", @@ -2068,83 +2279,121 @@ ], "support": { "issues": "https://github.com/Behat/Gherkin/issues", - "source": "https://github.com/Behat/Gherkin/tree/v4.9.0" + "source": "https://github.com/Behat/Gherkin/tree/v4.17.0" }, - "time": "2021-10-12T13:05:09+00:00" + "funding": [ + { + "url": "https://github.com/acoulton", + "type": "github" + }, + { + "url": "https://github.com/carlos-granados", + "type": "github" + }, + { + "url": "https://github.com/stof", + "type": "github" + } + ], + "time": "2026-05-18T09:33:47+00:00" }, { - "name": "behat/transliterator", - "version": "v1.5.0", + "name": "clue/ndjson-react", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/Behat/Transliterator.git", - "reference": "baac5873bac3749887d28ab68e2f74db3a4408af" + "url": "https://github.com/clue/reactphp-ndjson.git", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Transliterator/zipball/baac5873bac3749887d28ab68e2f74db3a4408af", - "reference": "baac5873bac3749887d28ab68e2f74db3a4408af", + "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=5.3", + "react/stream": "^1.2" }, "require-dev": { - "chuyskywalker/rolling-curl": "^3.1", - "php-yaoi/php-yaoi": "^1.0", - "phpunit/phpunit": "^8.5.25 || ^9.5.19" + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, "autoload": { "psr-4": { - "Behat\\Transliterator\\": "src/Behat/Transliterator" + "Clue\\React\\NDJson\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Artistic-1.0" + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } ], - "description": "String transliterator", + "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", + "homepage": "https://github.com/clue/reactphp-ndjson", "keywords": [ - "i18n", - "slug", - "transliterator" + "NDJSON", + "json", + "jsonlines", + "newline", + "reactphp", + "streaming" ], "support": { - "issues": "https://github.com/Behat/Transliterator/issues", - "source": "https://github.com/Behat/Transliterator/tree/v1.5.0" + "issues": "https://github.com/clue/reactphp-ndjson/issues", + "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" }, - "time": "2022-03-30T09:27:43+00:00" + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-12-23T10:58:28+00:00" }, { "name": "composer/pcre", - "version": "3.1.1", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9" + "reference": "d5a341b3fb61f3001970940afb1d332968a183ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9", - "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9", + "url": "https://api.github.com/repos/composer/pcre/zipball/d5a341b3fb61f3001970940afb1d332968a183ed", + "reference": "d5a341b3fb61f3001970940afb1d332968a183ed", "shasum": "" }, "require": { "php": "^7.4 || ^8.0" }, + "conflict": { + "phpstan/phpstan": "<2.2.2" + }, "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^9" }, "type": "library", "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, "branch-alias": { "dev-main": "3.x-dev" } @@ -2174,7 +2423,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.1" + "source": "https://github.com/composer/pcre/tree/3.4.0" }, "funding": [ { @@ -2184,34 +2433,30 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2023-10-11T07:11:09+00:00" + "time": "2026-06-07T11:47:49+00:00" }, { "name": "composer/semver", - "version": "3.4.0", + "version": "3.4.4", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" }, "type": "library", "extra": { @@ -2255,7 +2500,7 @@ "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" + "source": "https://github.com/composer/semver/tree/3.4.4" }, "funding": [ { @@ -2265,26 +2510,22 @@ { "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" + "time": "2025-08-20T19:15:30+00:00" }, { "name": "composer/xdebug-handler", - "version": "3.0.3", + "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ced299686f41dce890debac69273b47ffe98a40c" + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", - "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", "shasum": "" }, "require": { @@ -2295,7 +2536,7 @@ "require-dev": { "phpstan/phpstan": "^1.0", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" }, "type": "library", "autoload": { @@ -2319,9 +2560,9 @@ "performance" ], "support": { - "irc": "irc://irc.freenode.org/composer", + "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" }, "funding": [ { @@ -2337,39 +2578,42 @@ "type": "tidelift" } ], - "time": "2022-02-25T21:32:43+00:00" + "time": "2024-05-06T16:37:16+00:00" }, { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v0.7.2", + "version": "v1.2.1", "source": { "type": "git", - "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", - "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" + "url": "https://github.com/PHPCSStandards/composer-installer.git", + "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", - "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/963f0c67bffde0eac41b56be71ac0e8ba132f0bd", + "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + "composer-plugin-api": "^2.2", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" }, "require-dev": { - "composer/composer": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0" + "composer/composer": "^2.2", + "ext-json": "*", + "ext-zip": "*", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", + "yoast/phpunit-polyfills": "^1.0" }, "type": "composer-plugin", "extra": { - "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" }, "autoload": { "psr-4": { - "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2379,17 +2623,16 @@ "authors": [ { "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" + "email": "opensource@frenck.dev", + "homepage": "https://frenck.dev", + "role": "Open source developer" }, { "name": "Contributors", - "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" + "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", "keywords": [ "PHPCodeSniffer", "PHP_CodeSniffer", @@ -2409,54 +2652,262 @@ "tests" ], "support": { - "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", - "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", + "source": "https://github.com/PHPCSStandards/composer-installer" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2026-05-06T08:26:05+00:00" + }, + { + "name": "ergebnis/agent-detector", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/ergebnis/agent-detector.git", + "reference": "e211f17928c8b95a51e06040792d57f5462fb271" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ergebnis/agent-detector/zipball/e211f17928c8b95a51e06040792d57f5462fb271", + "reference": "e211f17928c8b95a51e06040792d57f5462fb271", + "shasum": "" + }, + "require": { + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0 || ~8.6.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.51.0", + "ergebnis/license": "^2.7.0", + "ergebnis/php-cs-fixer-config": "^6.60.2", + "ergebnis/phpstan-rules": "^2.13.1", + "ergebnis/phpunit-slow-test-detector": "^2.24.0", + "ergebnis/rector-rules": "^1.18.1", + "fakerphp/faker": "^1.24.1", + "infection/infection": "^0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.54", + "phpstan/phpstan-deprecation-rules": "^2.0.4", + "phpstan/phpstan-phpunit": "^2.0.16", + "phpstan/phpstan-strict-rules": "^2.0.10", + "phpunit/phpunit": "^9.6.34", + "rector/rector": "^2.4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" + } + }, + "autoload": { + "psr-4": { + "Ergebnis\\AgentDetector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" + } + ], + "description": "Provides a detector for detecting the presence of an agent.", + "homepage": "https://github.com/ergebnis/agent-detector", + "support": { + "issues": "https://github.com/ergebnis/agent-detector/issues", + "security": "https://github.com/ergebnis/agent-detector/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/agent-detector" + }, + "time": "2026-05-07T08:19:07+00:00" + }, + { + "name": "evenement/evenement", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Evenement\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" }, - "time": "2022-02-04T12:51:07+00:00" + "time": "2023-08-08T05:53:35+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2025-08-14T07:29:31+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.42.0", + "version": "v3.95.10", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "632ef1be3447a9b890bef06147475facee535d0f" + "reference": "93e1ab3e1f153024bd3ab23c8a349556063c6f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/632ef1be3447a9b890bef06147475facee535d0f", - "reference": "632ef1be3447a9b890bef06147475facee535d0f", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/93e1ab3e1f153024bd3ab23c8a349556063c6f17", + "reference": "93e1ab3e1f153024bd3ab23c8a349556063c6f17", "shasum": "" }, "require": { + "clue/ndjson-react": "^1.3", "composer/semver": "^3.4", - "composer/xdebug-handler": "^3.0.3", + "composer/xdebug-handler": "^3.0.5", + "ergebnis/agent-detector": "^1.2", + "ext-filter": "*", + "ext-hash": "*", "ext-json": "*", "ext-tokenizer": "*", + "fidry/cpu-core-counter": "^1.3", "php": "^7.4 || ^8.0", - "sebastian/diff": "^4.0 || ^5.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" + "react/child-process": "^0.6.6", + "react/event-loop": "^1.5", + "react/socket": "^1.16", + "react/stream": "^1.4", + "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0 || ^9.0", + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.37", + "symfony/polyfill-php80": "^1.37", + "symfony/polyfill-php81": "^1.37", + "symfony/polyfill-php84": "^1.37", + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.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", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + "facile-it/paraunit": "^1.3.1 || ^2.11.0", + "infection/infection": "^0.32.7", + "justinrainbow/json-schema": "^6.9.0", + "keradus/cli-executor": "^2.3", + "mikey179/vfsstream": "^1.6.12", + "php-coveralls/php-coveralls": "^2.9.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.8", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.8", + "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.55", + "symfony/polyfill-php85": "^1.38", + "symfony/var-dumper": "^5.4.48 || ^6.4.36 || ^7.4.8 || ^8.1.0", + "symfony/yaml": "^5.4.53 || ^6.4.41 || ^7.4.13 || ^8.1.0" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -2469,7 +2920,10 @@ "autoload": { "psr-4": { "PhpCsFixer\\": "src/" - } + }, + "exclude-from-classmap": [ + "src/**/Internal/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2494,7 +2948,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.42.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.10" }, "funding": [ { @@ -2502,29 +2956,30 @@ "type": "github" } ], - "time": "2023-12-24T14:38:51+00:00" + "time": "2026-06-19T14:45:22+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.8.1", + "version": "7.12.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + "reference": "9aa17bcdd777ee31df9fc83c337ca4ca2340def3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/9aa17bcdd777ee31df9fc83c337ca4ca2340def3", + "reference": "9aa17bcdd777ee31df9fc83c337ca4ca2340def3", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.1", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "guzzlehttp/promises": "^2.5", + "guzzlehttp/psr7": "^2.12.3", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", - "symfony/deprecation-contracts": "^2.2 || ^3.0" + "symfony/deprecation-contracts": "^2.5 || ^3.0", + "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-client-implementation": "1.0" @@ -2532,9 +2987,10 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "guzzle/client-integration-tests": "3.0.2", + "guzzlehttp/test-server": "^0.5.1", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.52 || ^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -2612,7 +3068,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + "source": "https://github.com/guzzle/guzzle/tree/7.12.3" }, "funding": [ { @@ -2628,28 +3084,29 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:35:24+00:00" + "time": "2026-06-23T15:29:02+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.2", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + "reference": "4360e982f87f5f258bf872d094647791db2f4c8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "url": "https://api.github.com/repos/guzzle/promises/zipball/4360e982f87f5f258bf872d094647791db2f4c8e", + "reference": "4360e982f87f5f258bf872d094647791db2f4c8e", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0" + "php": "^7.2.5 || ^8.0", + "symfony/deprecation-contracts": "^2.5 || ^3.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "type": "library", "extra": { @@ -2695,7 +3152,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.2" + "source": "https://github.com/guzzle/promises/tree/2.5.0" }, "funding": [ { @@ -2711,27 +3168,29 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:19:20+00:00" + "time": "2026-06-02T12:23:43+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.6.2", + "version": "2.12.3", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + "reference": "7ec62dc3f44aa218487dbed81a9bf9bc647be55d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/7ec62dc3f44aa218487dbed81a9bf9bc647be55d", + "reference": "7ec62dc3f44aa218487dbed81a9bf9bc647be55d", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.1 || ^2.0", - "ralouphie/getallheaders": "^3.0" + "ralouphie/getallheaders": "^3.0", + "symfony/deprecation-contracts": "^2.5 || ^3.0", + "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-factory-implementation": "1.0", @@ -2739,8 +3198,9 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "http-interop/http-factory-tests": "1.1.0", + "jshttp/mime-db": "1.54.0.1", + "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -2811,7 +3271,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.2" + "source": "https://github.com/guzzle/psr7/tree/2.12.3" }, "funding": [ { @@ -2827,36 +3287,36 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:05:35+00:00" + "time": "2026-06-23T15:21:08+00:00" }, { "name": "php-coveralls/php-coveralls", - "version": "v2.7.0", + "version": "v2.9.1", "source": { "type": "git", "url": "https://github.com/php-coveralls/php-coveralls.git", - "reference": "b36fa4394e519dafaddc04ae03976bc65a25ba15" + "reference": "916bdb118597f61ce6715fb738ab8f234b89a2cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/b36fa4394e519dafaddc04ae03976bc65a25ba15", - "reference": "b36fa4394e519dafaddc04ae03976bc65a25ba15", + "url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/916bdb118597f61ce6715fb738ab8f234b89a2cb", + "reference": "916bdb118597f61ce6715fb738ab8f234b89a2cb", "shasum": "" }, "require": { "ext-json": "*", "ext-simplexml": "*", "guzzlehttp/guzzle": "^6.0 || ^7.0", - "php": "^7.0 || ^8.0", - "psr/log": "^1.0 || ^2.0", - "symfony/config": "^2.1 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/console": "^2.1 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/stopwatch": "^2.0 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/yaml": "^2.0.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0" + "php": "^7.4 || ^8.0", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "symfony/config": "^5.4 || ^6.4 || ^7.0 || ^8.0", + "symfony/console": "^5.4 || ^6.4 || ^7.0 || ^8.0", + "symfony/stopwatch": "^5.4 || ^6.4 || ^7.0 || ^8.0", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.4.3 || ^6.0 || ^7.0 || >=8.0 <8.5.29 || >=9.0 <9.5.23", - "sanmai/phpunit-legacy-adapter": "^6.1 || ^8.0" + "phpspec/prophecy-phpunit": "^2.4", + "phpunit/phpunit": "^9.6.29 || ^10.5.58 || ^11.5.43" }, "suggest": { "symfony/http-kernel": "Allows Symfony integration" @@ -2908,9 +3368,9 @@ ], "support": { "issues": "https://github.com/php-coveralls/php-coveralls/issues", - "source": "https://github.com/php-coveralls/php-coveralls/tree/v2.7.0" + "source": "https://github.com/php-coveralls/php-coveralls/tree/v2.9.1" }, - "time": "2023-11-22T10:21:01+00:00" + "time": "2025-12-18T13:08:37+00:00" }, { "name": "php-stubs/wordpress-globals", @@ -2955,27 +3415,32 @@ }, { "name": "php-stubs/wordpress-stubs", - "version": "v6.4.1", + "version": "v6.9.4", "source": { "type": "git", "url": "https://github.com/php-stubs/wordpress-stubs.git", - "reference": "6d6063cf9464a306ca2a0529705d41312b08500b" + "reference": "90a9412826b9944f93b10bf41d795b5fe68abcd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/6d6063cf9464a306ca2a0529705d41312b08500b", - "reference": "6d6063cf9464a306ca2a0529705d41312b08500b", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/90a9412826b9944f93b10bf41d795b5fe68abcd5", + "reference": "90a9412826b9944f93b10bf41d795b5fe68abcd5", "shasum": "" }, + "conflict": { + "phpdocumentor/reflection-docblock": "5.6.1" + }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "nikic/php-parser": "^4.13", - "php": "^7.4 || ~8.0.0", - "php-stubs/generator": "^0.8.3", - "phpdocumentor/reflection-docblock": "^5.3", - "phpstan/phpstan": "^1.10.12", + "nikic/php-parser": "^5.5", + "php": "^7.4 || ^8.0", + "php-stubs/generator": "^0.8.6", + "phpdocumentor/reflection-docblock": "^6.0", + "phpstan/phpstan": "^2.1", "phpunit/phpunit": "^9.5", - "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^0.8" + "symfony/polyfill-php80": "*", + "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.1.1", + "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" }, "suggest": { "paragonie/sodium_compat": "Pure PHP implementation of libsodium", @@ -2996,9 +3461,9 @@ ], "support": { "issues": "https://github.com/php-stubs/wordpress-stubs/issues", - "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.4.1" + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.9.4" }, - "time": "2023-11-10T00:33:47+00:00" + "time": "2026-05-01T20:36:01+00:00" }, { "name": "phpcompatibility/php-compatibility", @@ -3064,20 +3529,15 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.50", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "06a98513ac72c03e8366b5a0cb00750b487032e4" - }, + "version": "2.2.2", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/06a98513ac72c03e8366b5a0cb00750b487032e4", - "reference": "06a98513ac72c03e8366b5a0cb00750b487032e4", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e5cc34d491a90e79c216d824f60fe21fd4d93bd6", + "reference": "e5cc34d491a90e79c216d824f60fe21fd4d93bd6", "shasum": "" }, "require": { - "php": "^7.2|^8.0" + "php": "^7.4|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" @@ -3096,6 +3556,17 @@ "license": [ "MIT" ], + "authors": [ + { + "name": "Ondřej Mirtes" + }, + { + "name": "Markus Staab" + }, + { + "name": "Vincent Langlet" + } + ], "description": "PHPStan - PHP Static Analysis Tool", "keywords": [ "dev", @@ -3116,39 +3587,34 @@ { "url": "https://github.com/phpstan", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2023-12-13T10:59:42+00:00" + "time": "2026-06-05T09:00:01+00:00" }, { "name": "phpstan/phpstan-mockery", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-mockery.git", - "reference": "6aa86bd8e9c9a1be97baf0558d4a2ed1374736a6" + "reference": "89a949d0ac64298e88b7c7fa00caee565c198394" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-mockery/zipball/6aa86bd8e9c9a1be97baf0558d4a2ed1374736a6", - "reference": "6aa86bd8e9c9a1be97baf0558d4a2ed1374736a6", + "url": "https://api.github.com/repos/phpstan/phpstan-mockery/zipball/89a949d0ac64298e88b7c7fa00caee565c198394", + "reference": "89a949d0ac64298e88b7c7fa00caee565c198394", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.10" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0" }, "require-dev": { - "mockery/mockery": "^1.2.4", - "nikic/php-parser": "^4.13.0", + "mockery/mockery": "^1.6.11", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5" + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6" }, "type": "phpstan-extension", "extra": { @@ -3170,36 +3636,37 @@ "description": "PHPStan Mockery extension", "support": { "issues": "https://github.com/phpstan/phpstan-mockery/issues", - "source": "https://github.com/phpstan/phpstan-mockery/tree/1.1.1" + "source": "https://github.com/phpstan/phpstan-mockery/tree/2.0.0" }, - "time": "2023-02-18T13:54:03+00:00" + "time": "2024-10-14T03:18:12+00:00" }, { "name": "phpstan/phpstan-phpunit", - "version": "1.3.15", + "version": "2.0.16", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a" + "reference": "6ab598e1bc106e6827fd346ae4a12b4a5d634c32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/70ecacc64fe8090d8d2a33db5a51fe8e88acd93a", - "reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6ab598e1bc106e6827fd346ae4a12b4a5d634c32", + "reference": "6ab598e1bc106e6827fd346ae4a12b4a5d634c32", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.10" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.1.32" }, "conflict": { "phpunit/phpunit": "<7.0" }, "require-dev": { - "nikic/php-parser": "^4.13.0", + "nikic/php-parser": "^5", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^9.5" + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6" }, "type": "phpstan-extension", "extra": { @@ -3220,30 +3687,38 @@ "MIT" ], "description": "PHPUnit extensions and rules for PHPStan", + "keywords": [ + "static analysis" + ], "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.15" + "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.16" }, - "time": "2023-10-09T18:58:39+00:00" + "time": "2026-02-14T09:05:21+00:00" }, { "name": "psr/container", - "version": "1.1.2", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { "php": ">=7.4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -3270,9 +3745,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/event-dispatcher", @@ -3299,7 +3774,310 @@ }, "autoload": { "psr-4": { - "Psr\\EventDispatcher\\": "src/" + "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/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "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/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "react/cache", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Cache\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3308,49 +4086,74 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" } ], - "description": "Standard interfaces for event handling.", + "description": "Async, Promise-based cache interface for ReactPHP", "keywords": [ - "events", - "psr", - "psr-14" + "cache", + "caching", + "promise", + "reactphp" ], "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" }, - "time": "2019-01-08T18:20:26+00:00" + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" }, { - "name": "psr/http-client", - "version": "1.0.3", + "name": "react/child-process", + "version": "v0.6.7", "source": { "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + "url": "https://github.com/reactphp/child-process.git", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3", "shasum": "" }, "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.0" + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/event-loop": "^1.2", + "react/stream": "^1.4" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/socket": "^1.16", + "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" }, + "type": "library", "autoload": { "psr-4": { - "Psr\\Http\\Client\\": "src/" + "React\\ChildProcess\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3359,50 +4162,73 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" } ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", + "description": "Event-driven library for executing child processes with ReactPHP.", "keywords": [ - "http", - "http-client", - "psr", - "psr-18" + "event-driven", + "process", + "reactphp" ], "support": { - "source": "https://github.com/php-fig/http-client" + "issues": "https://github.com/reactphp/child-process/issues", + "source": "https://github.com/reactphp/child-process/tree/v0.6.7" }, - "time": "2023-09-23T14:17:50+00:00" + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-12-23T15:25:20+00:00" }, { - "name": "psr/http-factory", - "version": "1.0.2", + "name": "react/dns", + "version": "v1.14.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "url": "https://github.com/reactphp/dns.git", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", "shasum": "" }, "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.0 || ^2.0" + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.7 || ^1.2.1" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3 || ^2", + "react/promise-timer": "^1.11" }, + "type": "library", "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" + "React\\Dns\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3411,52 +4237,72 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "Async DNS resolver for ReactPHP", "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" + "async", + "dns", + "dns-resolver", + "reactphp" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.14.0" }, - "time": "2023-04-10T20:10:41+00:00" + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-11-18T19:34:28+00:00" }, { - "name": "psr/http-message", - "version": "2.0", + "name": "react/event-loop", + "version": "v1.6.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + "url": "https://github.com/reactphp/event-loop.git", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": ">=5.3.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "suggest": { + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" }, + "type": "library", "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" + "React\\EventLoop\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3465,51 +4311,71 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" + "asynchronous", + "event-loop" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" }, - "time": "2023-04-04T09:54:51+00:00" + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-11-17T20:46:25+00:00" }, { - "name": "psr/log", - "version": "1.1.4", + "name": "react/promise", + "version": "v3.3.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "url": "https://github.com/reactphp/promise.git", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.1.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } + "require-dev": { + "phpstan/phpstan": "1.12.28 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" }, + "type": "library", "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "React\\Promise\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3518,48 +4384,76 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "A lightweight implementation of CommonJS Promises/A for PHP", "keywords": [ - "log", - "psr", - "psr-3" + "promise", + "promises" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.3.0" }, - "time": "2021-05-03T11:20:27+00:00" + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-08-19T18:57:03+00:00" }, { - "name": "ralouphie/getallheaders", - "version": "3.0.3", + "name": "react/socket", + "version": "v1.17.0", "source": { "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" + "url": "https://github.com/reactphp/socket.git", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", + "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", "shasum": "" }, "require": { - "php": ">=5.6" + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.13", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" }, "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3.3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.11" }, "type": "library", "autoload": { - "files": [ - "src/getallheaders.php" - ] + "psr-4": { + "React\\Socket\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3567,67 +4461,136 @@ ], "authors": [ { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" } ], - "description": "A polyfill for getallheaders.", + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.17.0" }, - "time": "2019-03-08T08:55:37+00:00" + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-11-19T20:47:34+00:00" }, { - "name": "sempro/phpunit-pretty-print", - "version": "1.4.0", + "name": "react/stream", + "version": "v1.4.0", "source": { "type": "git", - "url": "https://github.com/s360digital/phpunit-pretty-print.git", - "reference": "fa623aa8a17aece4a2b69e54b07a5e37572d1f1d" + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s360digital/phpunit-pretty-print/zipball/fa623aa8a17aece4a2b69e54b07a5e37572d1f1d", - "reference": "fa623aa8a17aece4a2b69e54b07a5e37572d1f1d", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", "shasum": "" }, "require": { - "php": ">=7.1.0", - "phpunit/phpunit": "^7 || ^8 || ^9" + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16" + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" }, "type": "library", "autoload": { "psr-4": { - "Sempro\\PHPUnitPrettyPrinter\\": "src/" + "React\\Stream\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Prettify PHPUnit output", + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], "support": { - "issues": "https://github.com/s360digital/phpunit-pretty-print/issues", - "source": "https://github.com/s360digital/phpunit-pretty-print/tree/1.4.0" + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" }, - "time": "2021-01-04T13:25:10+00:00" + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.8.0", + "version": "3.13.5", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "5805f7a4e4958dbb5e944ef1e6edae0a303765e7" + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5805f7a4e4958dbb5e944ef1e6edae0a303765e7", - "reference": "5805f7a4e4958dbb5e944ef1e6edae0a303765e7", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4", + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4", "shasum": "" }, "require": { @@ -3637,18 +4600,13 @@ "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "bin": [ - "bin/phpcs", - "bin/phpcbf" + "bin/phpcbf", + "bin/phpcs" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -3692,44 +4650,44 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2023-12-08T12:32:31+00:00" + "time": "2025-11-04T16:30:35+00:00" }, { "name": "symfony/config", - "version": "v5.4.31", + "version": "v7.4.10", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9" + "reference": "d91b6c7cd2a8c9a9c2b8d26c8f5ed48edf99ef57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/dd5ea39de228813aba0c23c3a4153da2a4cf3cd9", - "reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9", + "url": "https://api.github.com/repos/symfony/config/zipball/d91b6c7cd2a8c9a9c2b8d26c8f5ed48edf99ef57", + "reference": "d91b6c7cd2a8c9a9c2b8d26c8f5ed48edf99ef57", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/filesystem": "^7.1|^8.0", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { - "symfony/finder": "<4.4" + "symfony/finder": "<6.4", + "symfony/service-contracts": "<2.5" }, "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/messenger": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -3757,7 +4715,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v5.4.31" + "source": "https://github.com/symfony/config/tree/v7.4.10" }, "funding": [ { @@ -3768,61 +4726,60 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-11-09T08:22:43+00:00" + "time": "2026-05-03T14:20:49+00:00" }, { "name": "symfony/console", - "version": "v5.4.32", + "version": "v7.4.13", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c70df1ffaf23a8d340bded3cfab1b86752ad6ed7" + "reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c70df1ffaf23a8d340bded3cfab1b86752ad6ed7", - "reference": "c70df1ffaf23a8d340bded3cfab1b86752ad6ed7", + "url": "https://api.github.com/repos/symfony/console/zipball/85095d2573eaefaf35e40b9513a9bf09f72cd217", + "reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^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" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^7.2|^8.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" + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" }, "provide": { - "psr/log-implementation": "1.0|2.0" + "psr/log-implementation": "1.0|2.0|3.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": "" + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -3856,7 +4813,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.32" + "source": "https://github.com/symfony/console/tree/v7.4.13" }, "funding": [ { @@ -3867,57 +4824,52 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-11-18T18:23:04+00:00" + "time": "2026-05-24T08:56:14+00:00" }, { "name": "symfony/dependency-injection", - "version": "v5.4.33", + "version": "v7.4.13", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "14969a558cd6382b2a12b14b20ef9a851a02da79" + "reference": "f299e20ce983be6c0744952533c6dfeaaa1448e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/14969a558cd6382b2a12b14b20ef9a851a02da79", - "reference": "14969a558cd6382b2a12b14b20ef9a851a02da79", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f299e20ce983be6c0744952533c6dfeaaa1448e2", + "reference": "f299e20ce983be6c0744952533c6dfeaaa1448e2", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1.1", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22", - "symfony/service-contracts": "^1.1.6|^2" + "php": ">=8.2", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^3.6", + "symfony/var-exporter": "^6.4.20|^7.2.5|^8.0" }, "conflict": { "ext-psr": "<1.1|>=2", - "symfony/config": "<5.3", - "symfony/finder": "<4.4", - "symfony/proxy-manager-bridge": "<4.4", - "symfony/yaml": "<4.4.26" + "symfony/config": "<6.4", + "symfony/finder": "<6.4", + "symfony/yaml": "<6.4" }, "provide": { - "psr/container-implementation": "1.0", - "symfony/service-implementation": "1.0|2.0" + "psr/container-implementation": "1.1|2.0", + "symfony/service-implementation": "1.1|2.0|3.0" }, "require-dev": { - "symfony/config": "^5.3|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4.26|^5.0|^6.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -3945,7 +4897,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v5.4.33" + "source": "https://github.com/symfony/dependency-injection/tree/v7.4.13" }, "funding": [ { @@ -3956,38 +4908,42 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-11-30T08:15:37+00:00" + "time": "2026-05-20T14:07:29+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.2", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b", + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" } }, "autoload": { @@ -4012,7 +4968,7 @@ "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" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0" }, "funding": [ { @@ -4023,53 +4979,53 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2026-04-13T15:52:40+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.4.26", + "version": "v7.4.9", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "5dcc00e03413f05c1e7900090927bb7247cb0aac" + "reference": "e4a2e29753c7801f7a8340e066cfa788f3bc8101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/5dcc00e03413f05c1e7900090927bb7247cb0aac", - "reference": "5dcc00e03413f05c1e7900090927bb7247cb0aac", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e4a2e29753c7801f7a8340e066cfa788f3bc8101", + "reference": "e4a2e29753c7801f7a8340e066cfa788f3bc8101", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<4.4" + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" + "symfony/event-dispatcher-implementation": "2.0|3.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": "" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -4097,7 +5053,7 @@ "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.26" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.9" }, "funding": [ { @@ -4108,42 +5064,43 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-07-06T06:34:20+00:00" + "time": "2026-04-18T13:18:21+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.2", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/ccba7060602b7fed0b03c85bf025257f76d9ef32", + "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "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" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" } }, "autoload": { @@ -4176,7 +5133,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.0" }, "funding": [ { @@ -4187,32 +5144,39 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2026-01-05T13:30:16+00:00" }, { "name": "symfony/filesystem", - "version": "v5.4.25", + "version": "v8.1.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364" + "reference": "99aec13b82b4967ec5088222c4a3ecca955949c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", - "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/99aec13b82b4967ec5088222c4a3ecca955949c2", + "reference": "99aec13b82b4967ec5088222c4a3ecca955949c2", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.4.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -4240,7 +5204,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.25" + "source": "https://github.com/symfony/filesystem/tree/v8.1.0" }, "funding": [ { @@ -4251,31 +5215,36 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-05-31T13:04:02+00:00" + "time": "2026-05-29T05:06:50+00:00" }, { "name": "symfony/finder", - "version": "v5.4.27", + "version": "v8.1.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "ff4bce3c33451e7ec778070e45bd23f74214cd5d" + "reference": "58d2e767a66052c1487356f953445634a8194c64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ff4bce3c33451e7ec778070e45bd23f74214cd5d", - "reference": "ff4bce3c33451e7ec778070e45bd23f74214cd5d", + "url": "https://api.github.com/repos/symfony/finder/zipball/58d2e767a66052c1487356f953445634a8194c64", + "reference": "58d2e767a66052c1487356f953445634a8194c64", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.4.1" + }, + "require-dev": { + "symfony/filesystem": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -4303,7 +5272,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.27" + "source": "https://github.com/symfony/finder/tree/v8.1.0" }, "funding": [ { @@ -4314,32 +5283,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-07-31T08:02:31+00:00" + "time": "2026-05-29T05:06:50+00:00" }, { "name": "symfony/options-resolver", - "version": "v5.4.21", + "version": "v8.1.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" + "reference": "88f9c561f678a02d54b897014049fa839e33ff82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/88f9c561f678a02d54b897014049fa839e33ff82", + "reference": "88f9c561f678a02d54b897014049fa839e33ff82", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.4.1", + "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", "autoload": { @@ -4372,7 +5343,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" + "source": "https://github.com/symfony/options-resolver/tree/v8.1.0" }, "funding": [ { @@ -4383,29 +5354,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-02-14T08:03:56+00:00" + "time": "2026-05-29T05:06:50+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -4415,12 +5390,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4454,7 +5426,94 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-04-10T16:19:22+00:00" + }, + { + "name": "symfony/polyfill-deepclone", + "version": "v1.40.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-deepclone.git", + "reference": "dca4ccba5f360070b574414dce4c1e7a559844fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-deepclone/zipball/dca4ccba5f360070b574414dce4c1e7a559844fa", + "reference": "dca4ccba5f360070b574414dce4c1e7a559844fa", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "provide": { + "ext-deepclone": "*" + }, + "suggest": { + "ext-deepclone": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\DeepClone\\": "" + }, + "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 the deepclone extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "deepclone", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-deepclone/tree/v1.40.0" }, "funding": [ { @@ -4465,41 +5524,42 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2026-06-12T07:27:17+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.38.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "e9247d281d694a5120554d9afaf54e070e88a603" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/e9247d281d694a5120554d9afaf54e070e88a603", + "reference": "e9247d281d694a5120554d9afaf54e070e88a603", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4535,7 +5595,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1" }, "funding": [ { @@ -4546,41 +5606,42 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2026-05-26T05:58:03+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.38.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b", + "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4619,7 +5680,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0" }, "funding": [ { @@ -4630,29 +5691,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2026-05-25T13:48:31+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.38.2", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -4662,12 +5728,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4702,7 +5765,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" }, "funding": [ { @@ -4713,38 +5776,39 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" + "time": "2026-05-27T06:59:30+00:00" }, { - "name": "symfony/polyfill-php73", - "version": "v1.28.0", + "name": "symfony/polyfill-php80", + "version": "v1.37.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fe2f306d1d9d346a7fee353d0d5012e401e984b5", - "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4752,7 +5816,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" + "Symfony\\Polyfill\\Php80\\": "" }, "classmap": [ "Resources/stubs" @@ -4763,6 +5827,10 @@ "MIT" ], "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -4772,7 +5840,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -4781,7 +5849,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.37.0" }, "funding": [ { @@ -4792,25 +5860,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { - "name": "symfony/polyfill-php80", - "version": "v1.31.0", + "name": "symfony/polyfill-php81", + "version": "v1.38.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "6bfb9c766cacffbc8e118cb87217d08ed84e5cd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/6bfb9c766cacffbc8e118cb87217d08ed84e5cd7", + "reference": "6bfb9c766cacffbc8e118cb87217d08ed84e5cd7", "shasum": "" }, "require": { @@ -4819,8 +5891,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4828,7 +5900,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Php81\\": "" }, "classmap": [ "Resources/stubs" @@ -4839,10 +5911,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -4852,7 +5920,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -4861,7 +5929,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.38.1" }, "funding": [ { @@ -4872,38 +5940,39 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-05-26T12:45:58+00:00" }, { - "name": "symfony/polyfill-php81", - "version": "v1.28.0", + "name": "symfony/polyfill-php84", + "version": "v1.38.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa", + "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4911,7 +5980,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" + "Symfony\\Polyfill\\Php84\\": "" }, "classmap": [ "Resources/stubs" @@ -4931,7 +6000,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -4940,7 +6009,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.38.1" }, "funding": [ { @@ -4951,30 +6020,33 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2026-05-26T12:51:13+00:00" }, { "name": "symfony/process", - "version": "v5.4.46", + "version": "v8.1.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "01906871cb9b5e3cf872863b91aba4ec9767daf4" + "reference": "c4a9e58f235a6bf7f97ffbfedae2687353ac79e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/01906871cb9b5e3cf872863b91aba4ec9767daf4", - "reference": "01906871cb9b5e3cf872863b91aba4ec9767daf4", + "url": "https://api.github.com/repos/symfony/process/zipball/c4a9e58f235a6bf7f97ffbfedae2687353ac79e5", + "reference": "c4a9e58f235a6bf7f97ffbfedae2687353ac79e5", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.4.1" }, "type": "library", "autoload": { @@ -5002,7 +6074,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.46" + "source": "https://github.com/symfony/process/tree/v8.1.0" }, "funding": [ { @@ -5013,52 +6085,56 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-06T09:18:28+00:00" + "time": "2026-05-29T05:06:50+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.5.2", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d25d82433a80eba6aa0e6c24b61d7370d99e444a", + "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^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" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5085,7 +6161,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.7.0" }, "funding": [ { @@ -5096,30 +6172,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-05-30T19:17:29+00:00" + "time": "2026-03-28T09:44:51+00:00" }, { "name": "symfony/stopwatch", - "version": "v5.4.21", + "version": "v8.1.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee" + "reference": "21c07b026905d596e8379caeb115d87aa479499d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee", - "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/21c07b026905d596e8379caeb115d87aa479499d", + "reference": "21c07b026905d596e8379caeb115d87aa479499d", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" + "php": ">=8.4.1", + "symfony/service-contracts": "^2.5|^3" }, "type": "library", "autoload": { @@ -5147,7 +6227,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.21" + "source": "https://github.com/symfony/stopwatch/tree/v8.1.0" }, "funding": [ { @@ -5158,43 +6238,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-02-14T08:03:56+00:00" + "time": "2026-05-29T05:06:50+00:00" }, { "name": "symfony/string", - "version": "v5.4.32", + "version": "v8.1.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "91bf4453d65d8231688a04376c3a40efe0770f04" + "reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/91bf4453d65d8231688a04376c3a40efe0770f04", - "reference": "91bf4453d65d8231688a04376c3a40efe0770f04", + "url": "https://api.github.com/repos/symfony/string/zipball/afd5944f4005862d961efb85c8bbd5c523c4e3c9", + "reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9", "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" + "php": ">=8.4.1", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.5" }, "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" + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -5233,7 +6317,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.32" + "source": "https://github.com/symfony/string/tree/v8.1.0" }, "funding": [ { @@ -5244,62 +6328,65 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-11-26T13:43:46+00:00" + "time": "2026-05-29T05:06:50+00:00" }, { "name": "symfony/translation", - "version": "v5.4.31", + "version": "v7.4.10", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "ba72f72fceddf36f00bd495966b5873f2d17ad8f" + "reference": "ada7578c30dd5feaa8259cff3e885069ea81ddde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/ba72f72fceddf36f00bd495966b5873f2d17ad8f", - "reference": "ba72f72fceddf36f00bd495966b5873f2d17ad8f", + "url": "https://api.github.com/repos/symfony/translation/zipball/ada7578c30dd5feaa8259cff3e885069ea81ddde", + "reference": "ada7578c30dd5feaa8259cff3e885069ea81ddde", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/translation-contracts": "^2.3" + "symfony/translation-contracts": "^2.5.3|^3.3" }, "conflict": { - "symfony/config": "<4.4", - "symfony/console": "<5.3", - "symfony/dependency-injection": "<5.0", - "symfony/http-kernel": "<5.0", - "symfony/twig-bundle": "<5.0", - "symfony/yaml": "<4.4" + "nikic/php-parser": "<5.0", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" }, "provide": { - "symfony/translation-implementation": "2.3" + "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { + "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", - "symfony/http-kernel": "^5.0|^6.0", - "symfony/intl": "^4.4|^5.0|^6.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/service-contracts": "^1.1.2|^2|^3", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" + "symfony/routing": "^6.4|^7.0|^8.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -5330,7 +6417,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.4.31" + "source": "https://github.com/symfony/translation/tree/v7.4.10" }, "funding": [ { @@ -5341,47 +6428,51 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-11-03T16:16:43+00:00" + "time": "2026-05-06T11:19:24+00:00" }, { "name": "symfony/translation-contracts", - "version": "v2.5.2", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe" + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe", - "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/0ab302977a952b42fd51475c4ebac81f8da0a95d", + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d", "shasum": "" }, "require": { - "php": ">=7.2.5" - }, - "suggest": { - "symfony/translation-implementation": "" + "php": ">=8.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5408,7 +6499,90 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/translation-contracts/tree/v3.7.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-05T13:30:16+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v8.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "2dd18582c5f6c024db9fc0ff9c76d873af726f34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/2dd18582c5f6c024db9fc0ff9c76d873af726f34", + "reference": "2dd18582c5f6c024db9fc0ff9c76d873af726f34", + "shasum": "" + }, + "require": { + "php": ">=8.4.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-deepclone": "^1.37" + }, + "require-dev": { + "symfony/property-access": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "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 tools to export, instantiate, hydrate, clone and lazy-load PHP objects", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "deep-clone", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v8.1.0" }, "funding": [ { @@ -5419,40 +6593,41 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2022-06-27T16:58:25+00:00" + "time": "2026-05-29T05:06:50+00:00" }, { "name": "symfony/yaml", - "version": "v5.4.31", + "version": "v7.4.13", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "f387675d7f5fc4231f7554baa70681f222f73563" + "reference": "a7ec3b1156faf8815db7683ec7c1e7338e6f977c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/f387675d7f5fc4231f7554baa70681f222f73563", - "reference": "f387675d7f5fc4231f7554baa70681f222f73563", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a7ec3b1156faf8815db7683ec7c1e7338e6f977c", + "reference": "a7ec3b1156faf8815db7683ec7c1e7338e6f977c", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/console": "<5.3" + "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^5.3|^6.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "symfony/console": "^6.4|^7.0|^8.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -5483,7 +6658,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.31" + "source": "https://github.com/symfony/yaml/tree/v7.4.13" }, "funding": [ { @@ -5494,25 +6669,26 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-11-03T14:41:28+00:00" + "time": "2026-05-25T06:06:12+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": ">=7.4 < 9" - }, - "platform-dev": [], - "platform-overrides": { - "php": "7.4" + "php": ">=8.1" }, - "plugin-api-version": "2.6.0" + "platform-dev": {}, + "plugin-api-version": "2.9.0" } diff --git a/docs/general/configuration.md b/docs/general/configuration.md index f76a90f..2992e44 100644 --- a/docs/general/configuration.md +++ b/docs/general/configuration.md @@ -30,13 +30,13 @@ The bootstrap file can do a few things: ## Configure PHPUnit with WP_Mock -You can run PHPUnit using a `--bootstrap` flag to include your bootstrap configuration while executing your tests (see [PHPUnit documentation](https://docs.phpunit.de/en/9.5/textui.html?highlight=--bootstrap#command-line-options)): +You can run PHPUnit using a `--bootstrap` flag to include your bootstrap configuration while executing your tests (see [PHPUnit documentation](https://docs.phpunit.de/en/10.5/textui.html#command-line-options)): ```shell ./vendor/bin/phpunit --bootstrap /path/to/bootstrap.php ``` -A more convenient way though would be to add the following to the phpunit.xml configuration file (see [PHPUnit documentation](https://docs.phpunit.de/en/9.5/configuration.html)): +A more convenient way though would be to add the following to the phpunit.xml configuration file (see [PHPUnit documentation](https://docs.phpunit.de/en/10.5/configuration.html)): ```shell bootstrap="/path/to/bootstrap.php" diff --git a/docs/general/installation.md b/docs/general/installation.md index 071fbdc..c496f7e 100644 --- a/docs/general/installation.md +++ b/docs/general/installation.md @@ -2,7 +2,7 @@ ## Requirements -* PHP 7.4+ +* PHP 8.1+ * Composer 2.0+ ## Install WP_Mock @@ -17,11 +17,11 @@ composer require --dev 10up/wp_mock WP_Mock needs the following dependencies to work: -* PHPUnit ^9.5 (BSD 3-Clause license) -* Mockery ^1.6 (BSD 3-Clause license) +* PHPUnit ^10 || ^11 || ^12 || ^13 (BSD 3-Clause license) +* Mockery ^1.6.12 (BSD 3-Clause license) * Patchwork ^2.1 (MIT license) -They will be installed for you by Composer. +They will be installed for you by Composer. WP_Mock supports PHPUnit 10 through 13 from a single codebase; Composer installs the highest PHPUnit version your PHP version allows (for example PHP 8.1 resolves PHPUnit 10, while PHP 8.4 resolves PHPUnit 13). Next, you will need to configure PHPUnit first before enabling WP_Mock. [Consult PHPUnit documentation](https://phpunit.de/documentation.html) for this step. diff --git a/docs/tools/wp-mock-test-case.md b/docs/tools/wp-mock-test-case.md index 5ea065b..b3d6bf4 100644 --- a/docs/tools/wp-mock-test-case.md +++ b/docs/tools/wp-mock-test-case.md @@ -54,9 +54,9 @@ final class MyTestCase extends TestCase } ``` -### Expect output string +### Assert output equals HTML -The `TestCase::expectOutputString()` function will assert that the output of a function matches a given string. This is useful when you want to test the output of a function that echoes HTML. +The `TestCase::assertOutputEqualsHtml()` function runs a callback, captures everything it echoes, and asserts that the captured output equals the expected HTML — ignoring insignificant whitespace (tabs, newlines and collapsed runs of spaces). This is useful when you want to test a function that echoes HTML without having to match its exact formatting. ```php use WP_Mock\Tools\TestCase as TestCase; @@ -65,13 +65,15 @@ final class MyTestCase extends TestCase { public function testMyFunction() : void { - $this->expectOutputString('
Test
'); - - echo '
Test
'; + $this->assertOutputEqualsHtml('
Test
', static function () { + my_function_that_echoes_html(); + }); } } ``` +> **Changed in 2.0.0:** earlier versions overrode PHPUnit's `expectOutputString()` to transparently strip tabs and newlines from output (toggled with the `@stripTabsAndNewlinesFromOutput` annotation). PHPUnit 10 removed `setOutputCallback()` and made `expectOutputString()` `final`, so that automatic behavior is no longer possible. Use `assertOutputEqualsHtml()` for whitespace-insensitive output assertions; PHPUnit's native `expectOutputString()` remains available for exact-match assertions. + ### Mock static method The `TestCase::mockStaticMethod()` function will mock a static method on a class, via Patchwork, returning a Mockery object. diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 8d02f6e..8a48ea0 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -44,7 +44,8 @@ public function ensureStrictModeOn() { public static function forceStrictModeOn() { $property = new ReflectionProperty( 'WP_Mock', '__strict_mode' ); $property->setAccessible( true ); - $property->setValue( true ); + // Two-arg form (null object for a static property) — single-arg setValue() is deprecated since PHP 8.3. + $property->setValue( null, true ); } /** @@ -57,7 +58,8 @@ public function ensureStrictModeOff() { public static function forceStrictModeOff() { $property = new ReflectionProperty( 'WP_Mock', '__strict_mode' ); $property->setAccessible( true ); - $property->setValue( false ); + // Two-arg form (null object for a static property) — single-arg setValue() is deprecated since PHP 8.3. + $property->setValue( null, false ); } /** diff --git a/features/bootstrap/FunctionsContext.php b/features/bootstrap/FunctionsContext.php index e4325af..2da3b92 100644 --- a/features/bootstrap/FunctionsContext.php +++ b/features/bootstrap/FunctionsContext.php @@ -88,12 +88,10 @@ public function iExpectWhenIRunWithArgs( $return, $function, TableNode $args ) { } /** - * @Then I expect :return when I run :function - * - * @deprected use static::iExpectWhenIRun instead + * @deprecated use iExpectWhenIRun() instead */ public function iExcpectWhenIRun( $return, $function ) { - static::iExpectWhenIRun( $return, $function ) + $this->iExpectWhenIRun( $return, $function ); } /** diff --git a/php/WP_Mock.php b/php/WP_Mock.php index 49ef1f3..1c44a29 100644 --- a/php/WP_Mock.php +++ b/php/WP_Mock.php @@ -335,7 +335,7 @@ public static function expectFilterAdded(string $filter, $callback, int $priorit * @param int $args the number of arguments that should be allowed * @return void */ - public static function expectFilterNotAdded(string $filter, $callback, int $priority = 10, int $args = 10) : void + public static function expectFilterNotAdded(string $filter, $callback, int $priority = 10, int $args = 1) : void { self::expectHookNotAdded('filter', $filter, $callback, $priority, $args); } diff --git a/php/WP_Mock/DeprecatedMethodListener.php b/php/WP_Mock/DeprecatedMethodListener.php index dffbfc6..81dbc70 100644 --- a/php/WP_Mock/DeprecatedMethodListener.php +++ b/php/WP_Mock/DeprecatedMethodListener.php @@ -2,19 +2,16 @@ namespace WP_Mock; -use Mockery\MockInterface; -use PHPUnit\Framework\RiskyTestError; -use PHPUnit\Framework\TestCase; -use PHPUnit\Framework\TestResult; - /** * Internal handler for deprecated method calls. * - * This handler is used by WP_Mock to alert developers if they are using any WP_Mock deprecated methods. - * Test cases using WP_Mock deprecated methods will report as risky. - * In this way we can ensure that developers are aware of the deprecation and can update their code before any deprecated methods are permanently removed. + * Flags usage of deprecated WP_Mock methods by emitting an {@see E_USER_DEPRECATED} notice, + * which PHPUnit captures and attributes to the running test natively: it is reported per test + * and fails the suite when `failOnDeprecation="true"` is set in the PHPUnit configuration. + * + * To flag a method as deprecated, call the following from within the deprecated method's logic: * - * To flag a method as deprecated use {@see \WP_Mock::getDeprecatedMethodListener()->logDeprecatedCall()} within a deprecated method's logic. + * \WP_Mock::getDeprecatedMethodListener()->logDeprecatedCall(__METHOD__, func_get_args()); */ class DeprecatedMethodListener { @@ -24,12 +21,6 @@ class DeprecatedMethodListener /** @var string */ protected $testName = 'test'; - /** @var TestCase|MockInterface */ - protected $testCase; - - /** @var TestResult|MockInterface */ - protected $testResult; - /** * Sets the test name in context. * @@ -44,33 +35,11 @@ public function setTestName(string $testName): DeprecatedMethodListener } /** - * Sets the test case in context. + * Logs a deprecated method call and emits a deprecation notice. * - * @param TestCase|MockInterface $testCase - * @return $this - */ - public function setTestCase($testCase): DeprecatedMethodListener - { - $this->testCase = $testCase; - - return $this; - } - - /** - * Sets the test result in context. - * - * @param TestResult|MockInterface $testResult - * @return $this - */ - public function setTestResult($testResult): DeprecatedMethodListener - { - $this->testResult = $testResult; - - return $this; - } - - /** - * Logs a deprecated method call. + * The call is recorded (for inspection via {@see DeprecatedMethodListener::reset()} consumers) + * and an {@see E_USER_DEPRECATED} notice is triggered immediately so PHPUnit reports it against + * the running test. * * @param string $method * @param array $args @@ -80,6 +49,8 @@ public function logDeprecatedCall(string $method, array $args = []): DeprecatedM { $this->deprecatedCalls[] = [$method, $args]; + trigger_error($this->buildMessage($method, $args), E_USER_DEPRECATED); + return $this; } @@ -96,98 +67,23 @@ public function reset(): DeprecatedMethodListener } /** - * Checks for deprecated method calls. - * - * Adds failures to the test result if any are found. - * - * @return void - */ - public function checkCalls(): void - { - if (empty($this->deprecatedCalls)) { - return; - } - - $error = new RiskyTestError($this->buildErrorMessage()); - - /** @phpstan-ignore-next-line */ - $this->testResult->addFailure($this->testCase, $error, 0); - } - - /** - * Gets a deprecated method call usage message. + * Builds the deprecation message for a single deprecated method call. * + * @param string $method + * @param array $args * @return string */ - protected function buildErrorMessage(): string + protected function buildMessage(string $method, array $args): string { - $maxLength = array_reduce($this->getDeprecatedMethods(), function ($carry, $item) { - return max($carry, strlen($item)); - }, 0) + 1; - - $message = sprintf('Deprecated WP Mock calls inside %s:', $this->testName); - - foreach ($this->getDeprecatedMethodsWithArgs() as $method => $args) { - $firstRun = true; - $extra = $maxLength - strlen($method); - - foreach ($args as $arg) { - $message .= "\n "; - - if ($firstRun) { - $message .= $method . str_repeat(' ', $extra); - $firstRun = false; - $extra = $maxLength; - } else { - $message .= str_repeat(' ', $extra); - } + $message = sprintf('Deprecated WP_Mock call inside %s: %s', $this->testName, $method); - $message .= $arg; - } + if (! empty($args)) { + $message .= ' '.json_encode(array_map([$this, 'toScalar'], $args)); } return $message; } - /** - * Gets a list of deprecated methods having been called. - * - * @return string[] - */ - protected function getDeprecatedMethods(): array - { - $methods = []; - - foreach ($this->deprecatedCalls as $call) { - $methods[] = $call[0]; - } - - return array_unique($methods); - } - - /** - * Gets a list of deprecated methods having been called, with their arguments formatted as JSON. - * - * @return array> - */ - protected function getDeprecatedMethodsWithArgs(): array - { - $collection = []; - - foreach ($this->deprecatedCalls as $call) { - $method = $call[0]; - $args = json_encode(array_map([$this, 'toScalar'], $call[1])); - - if (empty($collection[$method])) { - $collection[$method] = []; - } - - $collection[$method][] = $args; - } - - return array_map('array_unique', $collection); - } - /** * Transforms a value for use in a JSON string. * diff --git a/php/WP_Mock/Tools/Constraints/IsEqualHtml.php b/php/WP_Mock/Tools/Constraints/IsEqualHtml.php index 0d0b525..8b13fb3 100644 --- a/php/WP_Mock/Tools/Constraints/IsEqualHtml.php +++ b/php/WP_Mock/Tools/Constraints/IsEqualHtml.php @@ -2,93 +2,66 @@ namespace WP_Mock\Tools\Constraints; -use Exception; use PHPUnit\Framework\Constraint\Constraint; -use PHPUnit\Framework\Constraint\IsEqual; -use PHPUnit\Framework\ExpectationFailedException; /** * HTML string constraint. + * + * Compares two HTML strings for equality while ignoring insignificant whitespace + * (tabs, newlines, carriage returns and collapsed runs of whitespace). */ class IsEqualHtml extends Constraint { /** @var string */ protected $value; - /** @var float */ - private $delta; - - /** @var bool */ - private $canonicalize; - - /** @var bool */ - private $ignoreCase; - /** * Constructor. * - * @param string $value - * @param float $delta - * @param bool $canonicalize - * @param bool $ignoreCase + * @param string $value the expected HTML */ - public function __construct(string $value, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false) + public function __construct(string $value) { $this->value = $value; - $this->delta = $delta; - $this->canonicalize = $canonicalize; - $this->ignoreCase = $ignoreCase; } /** - * Trims and removes tabs, newlines and return carriages from a string. + * Evaluates whether $other equals the expected HTML, ignoring insignificant whitespace. * - * @param string $value - * @return string + * @param mixed $other value to evaluate + * @return bool */ - protected function clean(string $value): string + public function matches(mixed $other): bool { - $value = preg_replace('/\n\s+/', '', $value) ?: ''; - $value = preg_replace('/\s\s+/', ' ', $value) ?: ''; + $actual = is_scalar($other) ? (string) $other : ''; - return str_replace(array( "\r", "\n", "\t" ), '', $value); + return $this->clean($actual) === $this->clean($this->value); } /** - * Evaluates the constraint for parameter $other. + * Returns a string representation of the constraint. * - * If $returnResult is false (default), an exception is thrown in case of a failure. null is returned otherwise. - * If $returnResult is true, the result of the evaluation is returned as a boolean instead, based on success or failure. + * @see Constraint::toString() * - * @param string $other value to evaluate - * @param string $description message used in failures - * @param bool $returnResult whether to throw an exception in case of failure or return boolean - * @return bool|null - * @throws ExpectationFailedException + * @return string */ - public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + public function toString(): string { - $other = $this->clean($other); - $this->value = $this->clean($this->value); - - $isEqual = new IsEqual($this->value, $this->delta, $this->canonicalize, $this->ignoreCase); - $result = $isEqual->evaluate($other, $description, $returnResult); - - return $returnResult ? $result : null; + // Note: do NOT use Constraint::exporter() here — it was removed in PHPUnit 11.0. + return sprintf("html is equal to '%s'", $this->clean($this->value)); } /** - * Returns a string representation of the constraint. - * - * @see Constraint::toString() + * Trims and removes tabs, newlines and return carriages from a string. * + * @param string $value * @return string - * @throws Exception */ - public function toString(): string + protected function clean(string $value): string { - $isEqual = new IsEqual($this->value, $this->delta, $this->canonicalize, $this->ignoreCase); + $value = preg_replace('/\n\s+/', '', $value) ?: ''; + $value = preg_replace('/\s\s+/', ' ', $value) ?: ''; - return 'html '.$isEqual->toString(); + return str_replace(["\r", "\n", "\t"], '', $value); } } diff --git a/php/WP_Mock/Tools/TestCase.php b/php/WP_Mock/Tools/TestCase.php index 28d5f3c..4927639 100644 --- a/php/WP_Mock/Tools/TestCase.php +++ b/php/WP_Mock/Tools/TestCase.php @@ -7,8 +7,6 @@ use Mockery; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\TestCase as PhpUnitTestCase; -use PHPUnit\Framework\TestResult; -use PHPUnit\Util\Test; use ReflectionException; use ReflectionMethod; use RuntimeException; @@ -40,9 +38,6 @@ abstract class TestCase extends PhpUnitTestCase /** @var array */ protected $__default_request = []; - /** @var bool|callable */ - protected $__contentFilterCallback = false; - /** @var array */ protected $testFiles = []; @@ -64,7 +59,6 @@ public function setUp(): void $_POST = (array) $this->__default_post; $_REQUEST = (array) $this->__default_request; - $this->setUpContentFiltering(); $this->cleanGlobals(); } @@ -101,53 +95,6 @@ public function tearDown(): void $_GET = $_POST = $_REQUEST = []; } - /** - * Runs the test case and collects the results in a {@see TestResult} object. - * - * If no {@see TestResult} object is passed a new one will be created. - * - * @param TestResult|null $result - * @return TestResult - * @throws Exception - */ - public function run(?TestResult $result = null): TestResult - { - if ($result === null) { - $result = $this->createResult(); - } - - WP_Mock::getDeprecatedMethodListener() - ->setTestResult($result) - ->setTestCase($this); - - return parent::run($result); - } - - /** - * Runs logic after every test. - * - * @after - * - * @return void - */ - public function after(): void - { - $this->checkDeprecatedCalls(); - } - - /** - * Checks for deprecated usage calls. - * - * This method is called after every test to check if any deprecated WP_Mock functions are used. - * - * @return void - */ - protected function checkDeprecatedCalls(): void - { - WP_Mock::getDeprecatedMethodListener()->checkCalls(); - WP_Mock::getDeprecatedMethodListener()->reset(); - } - /** * Cleans common WordPress globals that may have been used in between tests. * @@ -167,49 +114,6 @@ protected function cleanGlobals(): void } } - /** - * Sets up content filtering. - * - * @return void - * @throws Exception - */ - protected function setUpContentFiltering(): void - { - $this->__contentFilterCallback = false; - - $annotations = Test::parseTestMethodAnnotations( - static::class, - $this->getName(false) - ); - - if ( - ! isset($annotations['stripTabsAndNewlinesFromOutput']) || - $annotations['stripTabsAndNewlinesFromOutput'][0] !== 'disabled' || - ( - /** @phpstan-ignore-next-line */ - is_numeric($annotations['stripTabsAndNewlinesFromOutput'][0]) && - (int) $annotations['stripTabsAndNewlinesFromOutput'][0] !== 0 - ) - ) { - $this->__contentFilterCallback = [$this, 'stripTabsAndNewlines']; - $this->setOutputCallback($this->__contentFilterCallback); - } - } - - /** - * Strips tabs, newlines and carriage returns from a value. - * - * @internal may change to protected access in future versions - * @see TestCase::setUpContentFiltering() - * - * @param string|string[] $value - * @return string|string[] - */ - public function stripTabsAndNewlines($value) - { - return str_replace([ "\t", "\r", "\n"], '', $value); - } - /** * Asserts that all actions have been called. * @@ -292,23 +196,29 @@ public function assertEqualsHtml(string $expected, string $actual, string $messa } /** - * Sets the expectation that a string will be output. + * Asserts that the HTML output produced by the given callback equals the expected HTML, ignoring insignificant whitespace. + * + * Cross-version replacement for the implicit output filtering that previously relied on + * PHPUnit's setOutputCallback() (removed in PHPUnit 10) and the expectOutputString() override + * (expectOutputString() became final in PHPUnit 10). * - * @param string $expectedString + * @param string $expectedHtml the expected HTML + * @param callable $callback code that echoes or prints output + * @param string $message * @return void - * @throws InvalidArgumentException + * @throws ExpectationFailedException|Exception */ - public function expectOutputString(string $expectedString): void + public function assertOutputEqualsHtml(string $expectedHtml, callable $callback, string $message = ''): void { - if (is_callable($this->__contentFilterCallback)) { - $expectedString = call_user_func($this->__contentFilterCallback, $expectedString); - } + ob_start(); - if (! is_string($expectedString)) { - throw new InvalidArgumentException(sprintf('%1$s expects string, %2$s passed from content filter callback.', __METHOD__, gettype($expectedString))); + try { + $callback(); + } finally { + $actual = ob_get_clean(); } - parent::expectOutputString($expectedString); + $this->assertThat((string) $actual, new IsEqualHtml($expectedHtml), $message); } /** diff --git a/phpcs.xml b/phpcs.xml index e18853e..5b46ceb 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -4,5 +4,5 @@ ./tests - + \ No newline at end of file diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 9ca9448..bcf4e70 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,396 +1,757 @@ parameters: ignoreErrors: - - message: "#^Call to an undefined method Mockery\\\\ExpectationInterface\\|Mockery\\\\HigherOrderMessage\\:\\:atLeast\\(\\)\\.$#" + message: '#^Call to an undefined method Mockery\\ExpectationInterface\|Mockery\\HigherOrderMessage\:\:atLeast\(\)\.$#' + identifier: method.notFound count: 3 path: php/WP_Mock.php - - message: "#^Cannot call method perform\\(\\) on mixed\\.$#" + message: '#^Cannot call method andReturnUsing\(\) on mixed\.$#' + identifier: method.nonObject count: 1 path: php/WP_Mock.php - - message: "#^Cannot call method reply\\(\\) on mixed\\.$#" + message: '#^Cannot call method once\(\) on mixed\.$#' + identifier: method.nonObject + count: 3 + path: php/WP_Mock.php + + - + message: '#^Cannot call method perform\(\) on mixed\.$#' + identifier: method.nonObject + count: 1 + path: php/WP_Mock.php + + - + message: '#^Cannot call method reply\(\) on mixed\.$#' + identifier: method.nonObject + count: 1 + path: php/WP_Mock.php + + - + message: '#^Method WP_Mock\:\:activateStrictMode\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:activateStrictMode\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\:\:addAction\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:addAction\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\:\:addAction\(\) has parameter \$hook with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:addAction\\(\\) has parameter \\$hook with no type specified\\.$#" + message: '#^Method WP_Mock\:\:addFilter\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:addFilter\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\:\:addFilter\(\) has parameter \$hook with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:addFilter\\(\\) has parameter \\$hook with no type specified\\.$#" + message: '#^Method WP_Mock\:\:addHook\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:addHook\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\:\:addHook\(\) has parameter \$hook with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:addHook\\(\\) has parameter \\$hook with no type specified\\.$#" + message: '#^Method WP_Mock\:\:addHook\(\) has parameter \$type with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:addHook\\(\\) has parameter \\$type with no type specified\\.$#" + message: '#^Method WP_Mock\:\:assertActionsCalled\(\) throws checked exception PHPUnit\\Framework\\ExpectationFailedException but it''s missing from the PHPDoc @throws tag\.$#' + identifier: missingType.checkedException count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:assertActionsCalled\\(\\) throws checked exception PHPUnit\\\\Framework\\\\ExpectationFailedException but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\:\:assertFiltersCalled\(\) throws checked exception PHPUnit\\Framework\\ExpectationFailedException but it''s missing from the PHPDoc @throws tag\.$#' + identifier: missingType.checkedException count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:assertActionsCalled\\(\\) throws checked exception SebastianBergmann\\\\RecursionContext\\\\InvalidArgumentException but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\:\:assertHooksAdded\(\) throws checked exception PHPUnit\\Framework\\ExpectationFailedException but it''s missing from the PHPDoc @throws tag\.$#' + identifier: missingType.checkedException count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:assertFiltersCalled\\(\\) throws checked exception PHPUnit\\\\Framework\\\\ExpectationFailedException but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\:\:invokeAction\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:assertFiltersCalled\\(\\) throws checked exception SebastianBergmann\\\\RecursionContext\\\\InvalidArgumentException but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\:\:onHookAdded\(\) should return WP_Mock\\HookedCallback but returns mixed\.$#' + identifier: return.type count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:assertHooksAdded\\(\\) throws checked exception PHPUnit\\\\Framework\\\\ExpectationFailedException but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\:\:setUsePatchwork\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:assertHooksAdded\\(\\) throws checked exception SebastianBergmann\\\\RecursionContext\\\\InvalidArgumentException but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\:\:usingPatchwork\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:invokeAction\\(\\) has no return type specified\\.$#" + message: '#^Parameter \#1 \$callable of class WP_Mock\\InvokedFilterValue constructor expects callable\(\)\: mixed, array\{Mockery\\MockInterface, ''intercepted''\} given\.$#' + identifier: argument.type count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:setUsePatchwork\\(\\) has no return type specified\\.$#" + message: '#^Parameter \#1 \(mixed\) of echo cannot be converted to string\.$#' + identifier: echo.nonString count: 1 path: php/WP_Mock.php - - message: "#^Method WP_Mock\\:\\:usingPatchwork\\(\\) has no return type specified\\.$#" + message: '#^Parameter \#2 \$args of method WP_Mock\\Functions\:\:register\(\) expects array\, array\ given\.$#' + identifier: argument.type count: 1 path: php/WP_Mock.php - - message: "#^Parameter \\#1 \\$callable of class WP_Mock\\\\InvokedFilterValue constructor expects callable\\(\\)\\: mixed, array\\{Mockery\\\\LegacyMockInterface, 'intercepted'\\} given\\.$#" + message: '#^Parameter \#2 \$array of function implode expects array\, array given\.$#' + identifier: argument.type + count: 3 + path: php/WP_Mock.php + + - + message: '#^Part \$hook \(mixed\) of encapsed string cannot be cast to string\.$#' + identifier: encapsedStringPart.nonString count: 1 path: php/WP_Mock.php - - message: "#^Property WP_Mock\\:\\:\\$__bootstrapped has no type specified\\.$#" + message: '#^Part \$type \(mixed\) of encapsed string cannot be cast to string\.$#' + identifier: encapsedStringPart.nonString count: 1 path: php/WP_Mock.php - - message: "#^Property WP_Mock\\:\\:\\$__strict_mode has no type specified\\.$#" + message: '#^Property WP_Mock\:\:\$__bootstrapped has no type specified\.$#' + identifier: missingType.property count: 1 path: php/WP_Mock.php - - message: "#^Property WP_Mock\\:\\:\\$__use_patchwork has no type specified\\.$#" + message: '#^Property WP_Mock\:\:\$__strict_mode has no type specified\.$#' + identifier: missingType.property count: 1 path: php/WP_Mock.php - - message: "#^Function add_action\\(\\) has no return type specified\\.$#" + message: '#^Property WP_Mock\:\:\$__use_patchwork has no type specified\.$#' + identifier: missingType.property + count: 1 + path: php/WP_Mock.php + + - + message: '#^Function add_action\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/API/function-mocks.php - - message: "#^Function add_filter\\(\\) has no return type specified\\.$#" + message: '#^Function add_filter\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/API/function-mocks.php - - message: "#^PHPDoc tag @param references unknown parameter\\: \\$var$#" + message: '#^Function do_action\(\) should return null but returns mixed\.$#' + identifier: return.type count: 1 path: php/WP_Mock/API/function-mocks.php - - message: "#^Cannot access offset string on mixed\\.$#" + message: '#^PHPDoc tag @param references unknown parameter\: \$var$#' + identifier: parameter.notFound + count: 1 + path: php/WP_Mock/API/function-mocks.php + + - + message: '#^Cannot access offset int\<0, max\> on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible count: 2 path: php/WP_Mock/Action.php - - message: "#^Cannot call method react\\(\\) on mixed\\.$#" + message: '#^Cannot access offset string on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible count: 1 path: php/WP_Mock/Action.php - - message: "#^Method WP_Mock\\\\Action\\:\\:new_responder\\(\\) has no return type specified\\.$#" + message: '#^Cannot call method react\(\) on mixed\.$#' + identifier: method.nonObject + count: 2 + path: php/WP_Mock/Action.php + + - + message: '#^Method WP_Mock\\Action\:\:new_responder\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/Action.php - - message: "#^Method WP_Mock\\\\Action\\:\\:react\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\Action\:\:react\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/Action.php - - message: "#^Method WP_Mock\\\\Action\\:\\:react\\(\\) has parameter \\$args with no type specified\\.$#" + message: '#^Method WP_Mock\\Action\:\:react\(\) has parameter \$args with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock/Action.php - - message: "#^Method WP_Mock\\\\Action\\:\\:react\\(\\) throws checked exception PHPUnit\\\\Framework\\\\ExpectationFailedException but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\\Action\:\:react\(\) throws checked exception PHPUnit\\Framework\\ExpectationFailedException but it''s missing from the PHPDoc @throws tag\.$#' + identifier: missingType.checkedException count: 3 path: php/WP_Mock/Action.php - - message: "#^Method WP_Mock\\\\Action_Responder\\:\\:perform\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\Action_Responder\:\:perform\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/Action.php - - message: "#^Method WP_Mock\\\\Action_Responder\\:\\:perform\\(\\) has parameter \\$callable with no type specified\\.$#" + message: '#^Method WP_Mock\\Action_Responder\:\:perform\(\) has parameter \$callable with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock/Action.php - - message: "#^Method WP_Mock\\\\Action_Responder\\:\\:react\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\Action_Responder\:\:react\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/Action.php - - message: "#^Parameter \\#1 \\$function of function call_user_func expects callable\\(\\)\\: mixed, mixed given\\.$#" + message: '#^Parameter \#1 \$callback of function call_user_func expects callable\(\)\: mixed, mixed given\.$#' + identifier: argument.type count: 1 path: php/WP_Mock/Action.php - - message: "#^Method WP_Mock\\\\EventManager\\:\\:callback\\(\\) has no return type specified\\.$#" + message: '#^Parameter \#1 \$value of function count expects array\|Countable, mixed given\.$#' + identifier: argument.type count: 1 + path: php/WP_Mock/Action.php + + - + message: '#^Cannot access offset non\-falsy\-string on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 2 path: php/WP_Mock/EventManager.php - - message: "#^Method WP_Mock\\\\EventManager\\:\\:callback\\(\\) has parameter \\$name with no type specified\\.$#" + message: '#^Method WP_Mock\\EventManager\:\:action\(\) should return WP_Mock\\Action but returns mixed\.$#' + identifier: return.type count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Method WP_Mock\\\\EventManager\\:\\:callback\\(\\) has parameter \\$type with no type specified\\.$#" + message: '#^Method WP_Mock\\EventManager\:\:callback\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Method WP_Mock\\\\EventManager\\:\\:called\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\EventManager\:\:callback\(\) has parameter \$name with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Method WP_Mock\\\\EventManager\\:\\:expectedActions\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method WP_Mock\\EventManager\:\:callback\(\) has parameter \$type with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Method WP_Mock\\\\EventManager\\:\\:expectedFilters\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method WP_Mock\\EventManager\:\:called\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Method WP_Mock\\\\EventManager\\:\\:expectedHooks\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method WP_Mock\\EventManager\:\:expectedActions\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Method WP_Mock\\\\EventManager\\:\\:flush\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\EventManager\:\:expectedFilters\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Parameter \\#2 \\$offset of function array_splice expects int, int\\|string\\|false given\\.$#" + message: '#^Method WP_Mock\\EventManager\:\:expectedHooks\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Property WP_Mock\\\\EventManager\\:\\:\\$actions type has no value type specified in iterable type array\\.$#" + message: '#^Method WP_Mock\\EventManager\:\:filter\(\) should return WP_Mock\\Filter but returns mixed\.$#' + identifier: return.type count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Property WP_Mock\\\\EventManager\\:\\:\\$callbacks has no type specified\\.$#" + message: '#^Method WP_Mock\\EventManager\:\:flush\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Property WP_Mock\\\\EventManager\\:\\:\\$expected type has no value type specified in iterable type array\\.$#" + message: '#^Parameter \#1 \$array of function array_keys expects array, mixed given\.$#' + identifier: argument.type count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Property WP_Mock\\\\EventManager\\:\\:\\$filters type has no value type specified in iterable type array\\.$#" + message: '#^Parameter \#1 \$haystack of function strpos expects string, mixed given\.$#' + identifier: argument.type + count: 3 + path: php/WP_Mock/EventManager.php + + - + message: '#^Parameter \#1 \$name of class WP_Mock\\HookedCallback constructor expects string, mixed given\.$#' + identifier: argument.type + count: 1 + path: php/WP_Mock/EventManager.php + + - + message: '#^Parameter \#1 \$type of method WP_Mock\\HookedCallback\:\:setType\(\) expects string, mixed given\.$#' + identifier: argument.type count: 1 path: php/WP_Mock/EventManager.php - - message: "#^Cannot call method send\\(\\) on mixed\\.$#" + message: '#^Parameter \#2 \$offset of function array_splice expects int, int\|string\|false given\.$#' + identifier: argument.type + count: 1 + path: php/WP_Mock/EventManager.php + + - + message: '#^Part \$name \(mixed\) of encapsed string cannot be cast to string\.$#' + identifier: encapsedStringPart.nonString + count: 1 + path: php/WP_Mock/EventManager.php + + - + message: '#^Part \$type \(mixed\) of encapsed string cannot be cast to string\.$#' + identifier: encapsedStringPart.nonString + count: 1 + path: php/WP_Mock/EventManager.php + + - + message: '#^Property WP_Mock\\EventManager\:\:\$actions type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: php/WP_Mock/EventManager.php + + - + message: '#^Property WP_Mock\\EventManager\:\:\$callbacks has no type specified\.$#' + identifier: missingType.property + count: 1 + path: php/WP_Mock/EventManager.php + + - + message: '#^Property WP_Mock\\EventManager\:\:\$expected type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: php/WP_Mock/EventManager.php + + - + message: '#^Property WP_Mock\\EventManager\:\:\$filters type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: php/WP_Mock/EventManager.php + + - + message: '#^Cannot call method send\(\) on mixed\.$#' + identifier: method.nonObject count: 1 path: php/WP_Mock/Filter.php - - message: "#^Method WP_Mock\\\\Filter\\:\\:apply\\(\\) has parameter \\$args with no value type specified in iterable type array\\.$#" + message: '#^Method WP_Mock\\Filter\:\:apply\(\) has parameter \$args with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: php/WP_Mock/Filter.php - - message: "#^Method WP_Mock\\\\Filter\\:\\:apply\\(\\) throws checked exception PHPUnit\\\\Framework\\\\ExpectationFailedException but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\\Filter\:\:apply\(\) throws checked exception PHPUnit\\Framework\\ExpectationFailedException but it''s missing from the PHPDoc @throws tag\.$#' + identifier: missingType.checkedException count: 2 path: php/WP_Mock/Filter.php - - message: "#^Method WP_Mock\\\\Filter\\:\\:new_responder\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\Filter_Responder\:\:reply\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/Filter.php - - message: "#^Method WP_Mock\\\\Filter_Responder\\:\\:reply\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\Filter_Responder\:\:reply\(\) has parameter \$value with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock/Filter.php - - message: "#^Method WP_Mock\\\\Filter_Responder\\:\\:reply\\(\\) has parameter \\$value with no type specified\\.$#" + message: '#^Method WP_Mock\\Filter_Responder\:\:send\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/Filter.php - - message: "#^Method WP_Mock\\\\Filter_Responder\\:\\:send\\(\\) has no return type specified\\.$#" + message: '#^Parameter \#1 \$callback of function call_user_func_array expects callable\(\)\: mixed, array\{mixed, ''send''\} given\.$#' + identifier: argument.type count: 1 path: php/WP_Mock/Filter.php - - message: "#^Parameter \\#1 \\$function of function call_user_func_array expects callable\\(\\)\\: mixed, array\\{mixed, 'send'\\} given\\.$#" + message: '#^Call to an undefined method Mockery\\CompositeExpectation\|Mockery\\Expectation\:\:atLeast\(\)\.$#' + identifier: method.notFound count: 1 - path: php/WP_Mock/Filter.php + path: php/WP_Mock/Functions.php - - message: "#^Cannot access offset string on mixed\\.$#" - count: 4 + message: '#^Call to an undefined method Mockery\\CompositeExpectation\|Mockery\\Expectation\:\:atMost\(\)\.$#' + identifier: method.notFound + count: 1 + path: php/WP_Mock/Functions.php + + - + message: '#^Method WP_Mock\\Functions\:\:replaceFunction\(\) throws checked exception PHPUnit\\Framework\\ExpectationFailedException but it''s missing from the PHPDoc @throws tag\.$#' + identifier: missingType.checkedException + count: 1 + path: php/WP_Mock/Functions.php + + - + message: '#^Method WP_Mock\\Functions\:\:setExpectedTimes\(\) throws checked exception InvalidArgumentException but it''s missing from the PHPDoc @throws tag\.$#' + identifier: missingType.checkedException + count: 1 + path: php/WP_Mock/Functions.php + + - + message: '#^Parameter \#1 \$expectation of method WP_Mock\\Functions\:\:setExpectedReturn\(\) expects Mockery\\Expectation, Mockery\\CompositeExpectation\|Mockery\\Expectation given\.$#' + identifier: argument.type + count: 1 + path: php/WP_Mock/Functions.php + + - + message: '#^Cannot access offset string on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 3 + path: php/WP_Mock/Hook.php + + - + message: '#^Method WP_Mock\\Hook\:\:new_responder\(\) has no return type specified\.$#' + identifier: missingType.return + count: 1 path: php/WP_Mock/Hook.php - - message: "#^Method WP_Mock\\\\Hook\\:\\:new_responder\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\Hook\:\:with\(\) should return WP_Mock\\Action_Responder\|WP_Mock\\Filter_Responder\|WP_Mock\\HookedCallbackResponder but returns mixed\.$#' + identifier: return.type count: 1 path: php/WP_Mock/Hook.php - - message: "#^Cannot access offset 0 on callable\\(\\)\\: mixed\\.$#" + message: '#^Cannot access offset 0 on callable\(\)\: mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Cannot access offset 1 on callable\\(\\)\\: mixed\\.$#" + message: '#^Cannot access offset 1 on callable\(\)\: mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Cannot access offset mixed on mixed\\.$#" - count: 5 + message: '#^Cannot access offset mixed on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 2 + path: php/WP_Mock/HookedCallback.php + + - + message: '#^Cannot call method react\(\) on mixed\.$#' + identifier: method.nonObject + count: 1 + path: php/WP_Mock/HookedCallback.php + + - + message: '#^Method WP_Mock\\HookedCallback\:\:new_responder\(\) has no return type specified\.$#' + identifier: missingType.return + count: 1 + path: php/WP_Mock/HookedCallback.php + + - + message: '#^Method WP_Mock\\HookedCallback\:\:react\(\) has no return type specified\.$#' + identifier: missingType.return + count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Cannot call method react\\(\\) on mixed\\.$#" + message: '#^Method WP_Mock\\HookedCallback\:\:react\(\) has parameter \$argument_count with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallback\\:\\:new_responder\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\HookedCallback\:\:react\(\) has parameter \$callback with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallback\\:\\:react\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\HookedCallback\:\:react\(\) has parameter \$priority with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallback\\:\\:react\\(\\) has parameter \\$argument_count with no type specified\\.$#" + message: '#^Method WP_Mock\\HookedCallback\:\:react\(\) throws checked exception Mockery\\Exception but it''s missing from the PHPDoc @throws tag\.$#' + identifier: missingType.checkedException count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallback\\:\\:react\\(\\) has parameter \\$callback with no type specified\\.$#" + message: '#^Method WP_Mock\\HookedCallback\:\:react\(\) throws checked exception PHPUnit\\Framework\\ExpectationFailedException but it''s missing from the PHPDoc @throws tag\.$#' + identifier: missingType.checkedException count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallback\\:\\:react\\(\\) has parameter \\$priority with no type specified\\.$#" + message: '#^Method WP_Mock\\HookedCallback\:\:react\(\) throws checked exception ReflectionException but it''s missing from the PHPDoc @throws tag\.$#' + identifier: missingType.checkedException count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallback\\:\\:react\\(\\) throws checked exception Mockery\\\\Exception but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\\HookedCallback\:\:setType\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallback\\:\\:react\\(\\) throws checked exception PHPUnit\\\\Framework\\\\ExpectationFailedException but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\\HookedCallbackResponder\:\:perform\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallback\\:\\:react\\(\\) throws checked exception ReflectionException but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method WP_Mock\\HookedCallbackResponder\:\:perform\(\) has parameter \$callable with no type specified\.$#' + identifier: missingType.parameter count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallback\\:\\:setType\\(\\) has no return type specified\\.$#" + message: '#^Method WP_Mock\\HookedCallbackResponder\:\:react\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallbackResponder\\:\\:perform\\(\\) has no return type specified\\.$#" + message: '#^Parameter \#1 \$callback of method WP_Mock\\HookedCallback\:\:callback_to_string\(\) expects callable\(\)\: mixed, mixed given\.$#' + identifier: argument.type count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallbackResponder\\:\\:perform\\(\\) has parameter \\$callable with no type specified\\.$#" + message: '#^Parameter \#1 \$expected of class WP_Mock\\Matcher\\AnyInstance constructor expects object\|string\|null, mixed given\.$#' + identifier: argument.type count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\HookedCallbackResponder\\:\\:react\\(\\) has no return type specified\\.$#" + message: '#^Parameter \#1 \$object of function get_class expects object, mixed given\.$#' + identifier: argument.type count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Property WP_Mock\\\\HookedCallback\\:\\:\\$callback has no type specified\\.$#" + message: '#^Parameter \#2 \.\.\.\$values of function sprintf expects bool\|float\|int\|string\|null, mixed given\.$#' + identifier: argument.type count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Property WP_Mock\\\\HookedCallback\\:\\:\\$type has no type specified\\.$#" + message: '#^Part \$method \(mixed\) of encapsed string cannot be cast to string\.$#' + identifier: encapsedStringPart.nonString count: 1 path: php/WP_Mock/HookedCallback.php - - message: "#^Method WP_Mock\\\\InvokedFilterValue\\:\\:__invoke\\(\\) has no return type specified\\.$#" + message: '#^Property WP_Mock\\HookedCallback\:\:\$callback has no type specified\.$#' + identifier: missingType.property + count: 1 + path: php/WP_Mock/HookedCallback.php + + - + message: '#^Property WP_Mock\\HookedCallback\:\:\$type has no type specified\.$#' + identifier: missingType.property + count: 1 + path: php/WP_Mock/HookedCallback.php + + - + message: '#^Property WP_Mock\\HookedCallbackResponder\:\:\$callable \(callable\(\)\: mixed\) does not accept mixed\.$#' + identifier: assign.propertyType + count: 1 + path: php/WP_Mock/HookedCallback.php + + - + message: '#^Method WP_Mock\\InvokedFilterValue\:\:__invoke\(\) has no return type specified\.$#' + identifier: missingType.return + count: 1 + path: php/WP_Mock/InvokedFilterValue.php + + - + message: '#^Binary operation "\." between mixed and string results in an error\.$#' + identifier: binaryOp.invalid + count: 2 + path: php/WP_Mock/Tools/TestCase.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertIsArray\(\) with array\{\} will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 1 + path: tests/Unit/WP_Mock/FunctionsTest.php + + - + message: '#^Call to an undefined method Mockery\\ExpectationInterface\|Mockery\\HigherOrderMessage\:\:with\(\)\.$#' + identifier: method.notFound + count: 1 + path: tests/Unit/WP_Mock/Matcher/FuzzyObjectTest.php + + - + message: '#^Cannot call method andReturnTrue\(\) on mixed\.$#' + identifier: method.nonObject + count: 1 + path: tests/Unit/WP_Mock/Matcher/FuzzyObjectTest.php + + - + message: '#^Cannot call method getInaccessibleMethod\(\) on mixed\.$#' + identifier: method.nonObject count: 1 - path: php/WP_Mock/InvokedFilterValue.php \ No newline at end of file + path: tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php + + - + message: '#^Cannot call method getInaccessibleProperty\(\) on mixed\.$#' + identifier: method.nonObject + count: 1 + path: tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php + + - + message: '#^Cannot call method getInaccessiblePropertyValue\(\) on mixed\.$#' + identifier: method.nonObject + count: 1 + path: tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php + + - + message: '#^Cannot call method getName\(\) on mixed\.$#' + identifier: method.nonObject + count: 2 + path: tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php + + - + message: '#^Cannot call method getValue\(\) on mixed\.$#' + identifier: method.nonObject + count: 3 + path: tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php + + - + message: '#^Cannot call method invoke\(\) on mixed\.$#' + identifier: method.nonObject + count: 1 + path: tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php + + - + message: '#^Cannot call method invokeInaccessibleMethod\(\) on mixed\.$#' + identifier: method.nonObject + count: 1 + path: tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php + + - + message: '#^Cannot call method setInaccessibleProperty\(\) on mixed\.$#' + identifier: method.nonObject + count: 1 + path: tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php + + - + message: '#^Cannot call method setInaccessiblePropertyValue\(\) on mixed\.$#' + identifier: method.nonObject + count: 1 + path: tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php + + - + message: '#^Parameter \#1 \$object of function get_class expects object, mixed given\.$#' + identifier: argument.type + count: 1 + path: tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php + + - + message: '#^Call to an undefined method WP_Mock\\Action_Responder\|WP_Mock\\Filter_Responder\|WP_Mock\\HookedCallbackResponder\:\:reply\(\)\.$#' + identifier: method.notFound + count: 5 + path: tests/Unit/WP_MockTest.php + + - + message: '#^PHPDoc tag @throws with type InvalidArgumentException\|PHPUnit\\Framework\\Exception\|SebastianBergmann\\RecursionContext\\InvalidArgumentException is not subtype of Throwable$#' + identifier: throws.notThrowable + count: 2 + path: tests/Unit/WP_MockTest.php + + - + message: '#^PHPDoc tag @throws with type Mockery\\Exception\|PHPUnit\\Framework\\Exception\|SebastianBergmann\\RecursionContext\\InvalidArgumentException is not subtype of Throwable$#' + identifier: throws.notThrowable + count: 1 + path: tests/Unit/WP_MockTest.php + + - + message: '#^PHPDoc tag @throws with type PHPUnit\\Framework\\Exception\|SebastianBergmann\\RecursionContext\\InvalidArgumentException is not subtype of Throwable$#' + identifier: throws.notThrowable + count: 4 + path: tests/Unit/WP_MockTest.php + + - + message: '#^PHPDoc tag @throws with type PHPUnit\\Framework\\ExpectationFailedException\|SebastianBergmann\\RecursionContext\\InvalidArgumentException is not subtype of Throwable$#' + identifier: throws.notThrowable + count: 3 + path: tests/Unit/WP_MockTest.php \ No newline at end of file diff --git a/phpstan.neon b/phpstan.neon index 7700f11..41e0036 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -5,6 +5,11 @@ parameters: reportUnmatchedIgnoredErrors: false treatPhpDocTypesAsCertain: false exceptions: + # PHPUnit's mock-creation infrastructure throws these; they are test-runner concerns, + # not exceptions a test documents/handles, so don't require them in @throws tags. + uncheckedExceptionClasses: + - 'PHPUnit\Framework\MockObject\Exception' + - 'PHPUnit\Framework\InvalidArgumentException' check: missingCheckedExceptionInThrows: true tooWideThrowType: true diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index 937ae22..0000000 --- a/phpunit.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - ./tests/Unit - - - ./tests/Integration - - - - - - ./php - - - - diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..1dcca93 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,30 @@ + + + + + + ./tests/Unit + + + ./tests/Integration + + + + + + ./php + + + + diff --git a/tests/Integration/WP_MockTest.php b/tests/Integration/WP_MockTest.php index 3af7bb3..f5c28b9 100644 --- a/tests/Integration/WP_MockTest.php +++ b/tests/Integration/WP_MockTest.php @@ -4,17 +4,23 @@ use Exception; use Generator; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\PreserveGlobalState; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use PHPUnit\Framework\ExpectationFailedException; use WP_Mock; +use WP_Mock\Functions; +use WP_Mock\Functions\Handler; use WP_Mock\Tests\WP_MockTestCase; -/** - * @covers \WP_Mock - */ +#[CoversClass(WP_Mock::class)] +#[CoversClass(Functions::class)] +#[CoversClass(Handler::class)] class WP_MockTest extends WP_MockTestCase { /** @var string[] */ - private array $defaultMockedFunctions = [ + private const DEFAULT_MOCKED_FUNCTIONS = [ '__', '_e', '_n', @@ -44,7 +50,7 @@ class WP_MockTest extends WP_MockTestCase */ protected function setUp(): void { - if (! $this->isInIsolation()) { + if (! $this->isRunningInIsolation()) { WP_Mock::setUp(); } @@ -52,41 +58,31 @@ protected function setUp(): void } /** - * @covers \WP_Mock::bootstrap() - * @covers \WP_Mock\Functions::__construct() - * @covers \WP_Mock\Functions::flush() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void * @throws Exception */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCommonFunctionsAreDefined(): void { // First we assert that all common functions get removed from the returned array. // If any one of these functions doesn't get removed, that means it already exists. - $this->assertEmpty(array_filter($this->defaultMockedFunctions, 'function_exists')); + $this->assertEmpty(array_filter(self::DEFAULT_MOCKED_FUNCTIONS, 'function_exists')); WP_Mock::bootstrap(); // Now we assert that the array doesn't lose any items after bootstrap, // meaning all expected functions got defined correctly. - $this->assertEquals($this->defaultMockedFunctions, array_filter($this->defaultMockedFunctions, 'function_exists')); + $this->assertEquals(self::DEFAULT_MOCKED_FUNCTIONS, array_filter(self::DEFAULT_MOCKED_FUNCTIONS, 'function_exists')); } /** - * @covers \WP_Mock::userFunction() - * @covers \WP_Mock\Functions::__construct() - * @covers \WP_Mock\Functions::flush() - * - * @dataProvider providerCommonFunctionsDefaultFunctionality - * * @param callable&string $function * @param string $action echo or return * @return void * @throws Exception */ + #[DataProvider('providerCommonFunctionsDefaultFunctionality')] public function testCommonFunctionsDefaultFunctionality($function, string $action) { $input = $expected = 'Something Random '.rand(0, 99); @@ -110,9 +106,9 @@ public function testCommonFunctionsDefaultFunctionality($function, string $actio * * @return array */ - public function providerCommonFunctionsDefaultFunctionality(): array + public static function providerCommonFunctionsDefaultFunctionality(): array { - $functions = $this->defaultMockedFunctions; + $functions = self::DEFAULT_MOCKED_FUNCTIONS; return array_filter(array_map(function ($function) { // skip hook functions - only gettext functions under test @@ -123,14 +119,10 @@ public function providerCommonFunctionsDefaultFunctionality(): array } /** - * @covers \WP_Mock::activateStrictMode() - * @covers \WP_Mock::bootstrap() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testDefaultFailsInStrictMode(): void { $this->expectExceptionMessageMatches('/No handler found for \w+/'); @@ -144,11 +136,6 @@ public function testDefaultFailsInStrictMode(): void } /** - * @covers \WP_Mock::userFunction() - * @covers \WP_Mock\Functions::register() - * @covers \WP_Mock\Functions::generateFunction() - * @covers \WP_Mock\Functions::setUpMock() - * * @return void * @throws Exception */ @@ -164,11 +151,6 @@ public function testMockingOverridesDefaults(): void } /** - * @covers \WP_Mock::userFunction() - * @covers \WP_Mock\Functions::register() - * @covers \WP_Mock\Functions::generateFunction() - * @covers \WP_Mock\Functions::setUpMock() - * * @return void * @throws Exception */ @@ -181,23 +163,12 @@ public function testBotchedMocksStillOverridesDefault(): void } /** - * @covers \WP_Mock::userFunction() - * @covers \WP_Mock\Functions::register() - * @covers \WP_Mock\Functions::generateFunction() - * @covers \WP_Mock\Functions::setUpMock() - * @covers \WP_Mock\Functions::setExpectedTimes() - * @covers \WP_Mock\Functions::setExpectedArgs() - * @covers \WP_Mock\Functions::setExpectedReturn() - * @covers \WP_Mock\Functions::parseExpectedReturn() - * @covers \WP_Mock\Functions\Handler::registerHandler() - * - * @dataProvider providerUserFunctionExpectationArgs - * * @param array $expectationArgs * @param array $expectedResults * @return void * @throws Exception */ + #[DataProvider('providerUserFunctionExpectationArgs')] public function testCanSetUserFunctionExpectationArgs(array $expectationArgs, array $expectedResults): void { WP_Mock::userFunction('wpMockTestReturnFunction', $expectationArgs); @@ -215,7 +186,7 @@ public function testCanSetUserFunctionExpectationArgs(array $expectationArgs, ar } /** @see testCanSetUserFunctionExpectationArgs */ - public function providerUserFunctionExpectationArgs(): Generator + public static function providerUserFunctionExpectationArgs(): Generator { yield 'Function never called' => [ 'expectationArgs' => [ @@ -265,9 +236,6 @@ public function providerUserFunctionExpectationArgs(): Generator } /** - * @covers \WP_Mock::passthruFunction() - * @covers \WP_Mock\Functions::register() - * * @return void * @throws Exception */ @@ -281,9 +249,6 @@ public function testCanMockPassthruFunction(): void } /** - * @covers \WP_Mock::echoFunction() - * @covers \WP_Mock\Functions::register() - * * @return void * @throws Exception */ @@ -299,11 +264,6 @@ public function testCanMockEchoFunction(): void } /** - * @covers \WP_Mock::expectActionAdded() - * @covers \WP_Mock::expectFilterAdded() - * @covers \WP_Mock::expectHookAdded() - * @covers \WP_Mock::assertHooksAdded() - * * @return void */ public function testCanExpectHooksAdded() : void @@ -318,10 +278,6 @@ public function testCanExpectHooksAdded() : void } /** - * @covers \WP_Mock::expectActionNotAdded() - * @covers \WP_Mock::expectFilterNotAdded() - * @covers \WP_Mock::expectHookNotAdded() - * * @return void * @throws Exception */ diff --git a/tests/Unit/WP_Mock/API/FunctionMocksTest.php b/tests/Unit/WP_Mock/API/FunctionMocksTest.php index 2ba4ce1..6bb3896 100644 --- a/tests/Unit/WP_Mock/API/FunctionMocksTest.php +++ b/tests/Unit/WP_Mock/API/FunctionMocksTest.php @@ -3,35 +3,20 @@ namespace Unit\WP_Mock\API; use Exception; +use PHPUnit\Framework\Attributes\PreserveGlobalState; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use WP_Mock; use WP_Mock\Tests\WP_MockTestCase; -/** - * @covers \WP_Mock - * @covers \WP_Mock\Functions\Handler - */ +// No coverage metadata: this exercises globally-defined function mocks (esc_url(), __(), …), +// not a single class, so it contributes whole-suite coverage rather than per-class attribution. final class FunctionMocksTest extends WP_MockTestCase { /** - * @covers \__() - * @covers \_n() - * @covers \_x() - * @covers \esc_attr() - * @covers \esc_attr__() - * @covers \esc_attr_x() - * @covers \esc_html() - * @covers \esc_html__() - * @covers \esc_js() - * @covers \esc_textarea() - * @covers \esc_url() - * @covers \esc_url_raw() - * @covers \WP_Mock\Functions\Handler::handlePredefinedReturnFunction() - * - * @preserveGlobalState disabled - * @runInSeparateProcess - * * @return void */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testPredefinedReturnFunctions(): void { WP_Mock::bootstrap(); @@ -64,17 +49,11 @@ public function testPredefinedReturnFunctions(): void } /** - * @covers \_e() - * @covers \esc_attr_e() - * @covers \esc_html_e() - * @covers \WP_Mock\Functions\Handler::handlePredefinedEchoFunction() - * - * @preserveGlobalState disabled - * @runInSeparateProcess - * * @return void * @throws Exception */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testPredefinedEchoFunctions(): void { WP_Mock::bootstrap(); diff --git a/tests/Unit/WP_Mock/DeprecatedMethodListenerTest.php b/tests/Unit/WP_Mock/DeprecatedMethodListenerTest.php index 98f76af..8f30b95 100644 --- a/tests/Unit/WP_Mock/DeprecatedMethodListenerTest.php +++ b/tests/Unit/WP_Mock/DeprecatedMethodListenerTest.php @@ -4,11 +4,8 @@ use Exception; use Generator; -use Mockery; -use PHPUnit\Framework\Assert; -use PHPUnit\Framework\RiskyTestError; -use PHPUnit\Framework\TestCase; -use PHPUnit\Framework\TestResult; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use ReflectionException; use ReflectionMethod; use ReflectionProperty; @@ -17,9 +14,8 @@ use WP_Mock\DeprecatedMethodListener; use WP_Mock\Tests\WP_MockTestCase; -/** - * @covers \WP_Mock\DeprecatedMethodListener - */ +#[CoversClass(WP_Mock::class)] +#[CoversClass(DeprecatedMethodListener::class)] final class DeprecatedMethodListenerTest extends WP_MockTestCase { /** @var DeprecatedMethodListener */ @@ -32,6 +28,8 @@ final class DeprecatedMethodListenerTest extends WP_MockTestCase */ protected function setUp(): void { + parent::setUp(); + $this->object = new DeprecatedMethodListener(); } @@ -40,293 +38,116 @@ protected function setUp(): void * * @return void */ - public function tearDown(): void + protected function tearDown(): void { $this->object->reset(); - } - - /** - * @covers \WP_Mock\DeprecatedMethodListener::setTestName() - * - * @return void - * @throws ReflectionException|Exception - */ - public function testCanSetTestName(): void - { - $property = new ReflectionProperty($this->object, 'testName'); - $property->setAccessible(true); - - $this->assertSame('test', $property->getValue($this->object)); - - $this->assertSame($this->object, $this->object->setTestName('FooBar')); - $this->assertSame('FooBar', $property->getValue($this->object)); + parent::tearDown(); } /** - * @covers \WP_Mock\DeprecatedMethodListener::setTestCase() + * Captures the {@see E_USER_DEPRECATED} messages emitted while running $callback. * - * @return void - * @throws ReflectionException|Exception + * A local error handler intercepts the notices so that PHPUnit's + * `failOnDeprecation` does not interfere with the assertions. + * + * @param callable $callback + * @return string[] the captured deprecation messages, in order */ - public function testCanSetTestCase(): void + protected function captureDeprecations(callable $callback): array { - /** @var TestCase&Mockery\MockInterface $testCase */ - $testCase = Mockery::mock(TestCase::class); + $messages = []; - $this->assertSame($this->object, $this->object->setTestCase($testCase)); + set_error_handler(static function (int $errno, string $errstr) use (&$messages): bool { + $messages[] = $errstr; - $property = new ReflectionProperty($this->object, 'testCase'); - $property->setAccessible(true); + return true; + }, E_USER_DEPRECATED); - $this->assertSame($testCase, $property->getValue($this->object)); + try { + $callback(); + } finally { + restore_error_handler(); + } + + return $messages; } /** - * @covers \WP_Mock\DeprecatedMethodListener::setTestResult() - * * @return void * @throws ReflectionException|Exception */ - public function testCanSetTestResult(): void + public function testCanSetTestName(): void { - $concreteTestResult = new TestResult(); - /** @var TestResult&Mockery\MockInterface $mockTestResult @phpstan-ignore-line */ - $mockTestResult = Mockery::mock($concreteTestResult); + $property = new ReflectionProperty($this->object, 'testName'); + $property->setAccessible(true); - $this->assertSame($this->object, $this->object->setTestResult($mockTestResult)); + $this->assertSame('test', $property->getValue($this->object)); - $property = new ReflectionProperty($this->object, 'testResult'); - $property->setAccessible(true); + $this->assertSame($this->object, $this->object->setTestName('FooBar')); - $this->assertSame($mockTestResult, $property->getValue($this->object)); + $this->assertSame('FooBar', $property->getValue($this->object)); } /** - * @covers \WP_Mock\DeprecatedMethodListener::logDeprecatedCall() - * * @return void * @throws ReflectionException|Exception */ - public function testCanLogDeprecatedCall(): void + public function testLogDeprecatedCallRecordsAndTriggersDeprecation(): void { - $method = 'Foo::bar'.rand(0, 9); - $args = [rand(10, 99)]; + $method = 'Foo::bar'; + $args = [42]; - $this->assertSame($this->object, $this->object->logDeprecatedCall($method, $args)); + $messages = $this->captureDeprecations(function () use ($method, $args) { + $this->assertSame($this->object, $this->object->logDeprecatedCall($method, $args)); + }); - $this->assertEquals([[$method, $args]], $this->getDeprecatedMethodCalls($this->object)); - } + // the call is recorded for inspection + $this->assertSame([[$method, $args]], $this->getDeprecatedMethodCalls($this->object)); - /** - * @covers \WP_Mock\DeprecatedMethodListener::reset() - * - * @return void - * @throws Exception - */ - public function testCanResetDeprecatedCallsLog(): void - { - $this->assertSame($this->object, $this->object->logDeprecatedCall('Foo::bar', ['baz'])); - $this->assertSame($this->object, $this->object->reset()); - $this->assertSame([], $this->getDeprecatedMethodCalls($this->object)); + // exactly one E_USER_DEPRECATED was emitted, mentioning the method and its args + $this->assertCount(1, $messages); + $this->assertStringContainsString('Foo::bar', $messages[0]); + $this->assertStringContainsString('[42]', $messages[0]); } /** - * @covers \WP_Mock\DeprecatedMethodListener::checkCalls() - * * @return void * @throws Exception */ - public function testCheckDeprecatedMethodCallsWithNoCallsMade(): void + public function testDeprecationMessageIncludesTestNameAndArgs(): void { - $concreteTestResult = new TestResult(); - /** @var TestResult&Mockery\MockInterface $mockTestResult @phpstan-ignore-line */ - $mockTestResult = Mockery::mock($concreteTestResult); - $mockTestResult->expects('addFailure')->never(); + $this->object->setTestName('MyTest'); - $this->object->setTestResult($mockTestResult); - $this->object->checkCalls(); + $messages = $this->captureDeprecations(function () { + $this->object->logDeprecatedCall('Foo::bar', ['baz']); + }); - $this->assertConditionsMet(); + $this->assertCount(1, $messages); + $this->assertSame('Deprecated WP_Mock call inside MyTest: Foo::bar ["baz"]', $messages[0]); } /** - * @covers \WP_Mock\DeprecatedMethodListener::checkCalls() - * - * @return void - */ - public function testCanCheckDeprecatedMethodCallsWithScalarArgs(): void - { - $this->object->logDeprecatedCall('FooBar::bazBat', ['string', true, 42]); - $this->object->setTestName('TestName'); - - /** @var TestCase&Mockery\MockInterface $mockTestCase */ - $mockTestCase = Mockery::mock(TestCase::class); - - $this->object->setTestCase($mockTestCase); - - $concreteTestResult = new TestResult(); - /** @var TestResult&Mockery\MockInterface $mockTestResult @phpstan-ignore-line */ - $mockTestResult = Mockery::mock($concreteTestResult)->makePartial(); - - $mockTestResult->expects('addFailure') - ->once() - ->andReturnUsing(function ($concreteCase, $exception, $int) use ($mockTestCase) { - $int = (int) $int; // It's coming as 0.0 - Assert::assertSame($mockTestCase, $concreteCase); - Assert::assertTrue($exception instanceof RiskyTestError); - $message = <<getMessage()); - Assert::assertTrue(0 === $int); - }); - - $this->object->setTestResult($mockTestResult); - $this->object->checkCalls(); - } - - /** - * @covers \WP_Mock\DeprecatedMethodListener::checkCalls() - * * @return void * @throws Exception */ - public function testCanCheckDeprecatedMethodCallsWithNonScalarArgs(): void - { - $object1 = Mockery::mock('WP_Query'); - $range = rand(5, 10); - $resource = fopen('php://temp', 'r'); - $callback1 = function () { - }; - - $this->object->logDeprecatedCall('BazBat::fooBar', [$callback1]); - $this->object->logDeprecatedCall('BazBat::fooBar', [$object1]); - $this->object->logDeprecatedCall('BazBat::fooBar', [$object1]); - $this->object->logDeprecatedCall('LongerClassName::callback', [[$object1, 'shouldReceive']]); - $this->object->logDeprecatedCall('BazBat::fooBar', [range(1, $range), $resource]); - $this->object->setTestName('OtherTest'); - - /** @var TestCase&Mockery\MockInterface $mockTestCase @phpstan-ignore-line */ - $mockTestCase = Mockery::mock(TestCase::class); - - $this->object->setTestCase($mockTestCase); - - $concreteTestResult = new TestResult(); - /** @var TestResult&Mockery\MockInterface $mockTestResult @phpstan-ignore-line */ - $mockTestResult = Mockery::mock($concreteTestResult); - - $testClosure = function ($case, $exception, $int) use ($mockTestCase, $callback1, $object1, $range) { - $int = (int) $int; // It's coming as 0.0 - $callback1 = get_class($callback1) . ':' . spl_object_hash($callback1); - $object1 = get_class($object1) . ':' . spl_object_hash($object1); - - Assert::assertSame($mockTestCase, $case); - Assert::assertTrue($exception instanceof RiskyTestError); - - $message = <<"] - ["<$object1>"] - ["Array([$range] ...)","Resource"] - LongerClassName::callback ["[<$object1>,shouldReceive]"] -EOT; - Assert::assertEquals($message, $exception->getMessage()); - Assert::assertTrue(0 === $int); - }; - - $mockTestResult->expects('addFailure') - ->once() - ->andReturnUsing($testClosure); - - $this->object->setTestResult($mockTestResult); - - try { - $this->object->checkCalls(); - } catch (Exception $exception) { - fclose($resource); // @phpstan-ignore-line - - throw $exception; - } - - fclose($resource); // @phpstan-ignore-line - } - - /** - * @covers \WP_Mock\DeprecatedMethodListener::buildErrorMessage() - * - * @return void - * @throws ReflectionException|Exception - */ - public function testCanBuildErrorMessage(): void - { - $instance = new DeprecatedMethodListener(); - $instance->setTestName('MyTest'); - $instance->logDeprecatedCall('Foo::bar', ['baz']); - - $method = new ReflectionMethod($instance, 'buildErrorMessage'); - $method->setAccessible(true); - - $expectedMessage = 'Deprecated WP Mock calls inside MyTest:'."\n ".'Foo::bar ["baz"]'; - - $this->assertSame($expectedMessage, $method->invoke($instance)); - } - - /** - * @covers \WP_Mock\DeprecatedMethodListener::getDeprecatedMethods() - * - * @return void - * @throws ReflectionException|Exception - */ - public function testCanGetDeprecatedMethods(): void - { - $instance = new DeprecatedMethodListener(); - $instance->logDeprecatedCall('Foo::bar', ['baz']); - $instance->logDeprecatedCall('Boz::qux'); - - $method = new ReflectionMethod($instance, 'getDeprecatedMethods'); - $method->setAccessible(true); - - $this->assertSame(['Foo::bar', 'Boz::qux'], $method->invoke($instance)); - } - - /** - * @covers \WP_Mock\DeprecatedMethodListener::getDeprecatedMethodsWithArgs() - * - * @return void - * @throws ReflectionException|Exception - */ - public function testCanGetDeprecatedMethodsWithArgs(): void + public function testCanResetDeprecatedCallsLog(): void { - $instance = new DeprecatedMethodListener(); - $instance->logDeprecatedCall('Foo::bar', ['baz']); - $instance->logDeprecatedCall('Boz::qux'); + $this->captureDeprecations(function () { + $this->object->logDeprecatedCall('Foo::bar', ['baz']); + }); - $method = new ReflectionMethod($instance, 'getDeprecatedMethodsWithArgs'); - $method->setAccessible(true); - - $expected = [ - 'Foo::bar' => [ - '["baz"]' - ], - 'Boz::qux' => [ - '[]' - ], - ]; - - $this->assertSame($expected, $method->invoke($instance)); + $this->assertSame($this->object, $this->object->reset()); + $this->assertSame([], $this->getDeprecatedMethodCalls($this->object)); } /** - * @covers \WP_Mock\DeprecatedMethodListener::toScalar() - * @dataProvider providerConvertsArgumentsToScalarValue - * * @param mixed $arg * @param string|bool|null|float|int $expected * @return void * @throws ReflectionException|Exception */ + #[DataProvider('providerConvertsArgumentsToScalarValue')] public function testCanConvertArgumentsToScalarValue($arg, $expected): void { $instance = new DeprecatedMethodListener(); @@ -335,7 +156,7 @@ public function testCanConvertArgumentsToScalarValue($arg, $expected): void $result = $method->invokeArgs($instance, [$arg]); - if (is_object($arg) && is_string($expected) && is_string($result)) { + if (is_object($arg) && is_string($expected) && '' !== $expected && is_string($result)) { $this->assertStringStartsWith($expected, $result); } else { $this->assertSame($expected, $result); @@ -343,7 +164,7 @@ public function testCanConvertArgumentsToScalarValue($arg, $expected): void } /** @see testCanConvertArgumentsToScalarValue */ - public function providerConvertsArgumentsToScalarValue(): Generator + public static function providerConvertsArgumentsToScalarValue(): Generator { yield 'null' => [null, null]; yield 'true' => [true, true]; @@ -359,55 +180,28 @@ public function providerConvertsArgumentsToScalarValue(): Generator } /** - * @covers \WP_Mock\DeprecatedMethodListener::logDeprecatedCall() - * @covers \WP_Mock::getDeprecatedMethodListener() - * * @return void * @throws Exception */ - public function testCanHandleDeprecatedMethodCall(): void + public function testCanHandleDeprecatedMethodCallThroughWpMock(): void { $deprecatedMethodListener = new DeprecatedMethodListener(); - $concreteTestResult = new TestResult(); - /** @var TestResult&Mockery\MockInterface $mockTestResult @phpstan-ignore-line */ - $mockTestResult = Mockery::mock($concreteTestResult); - /** @var TestCase&Mockery\MockInterface $mockTestCase */ - $mockTestCase = Mockery::mock(TestCase::class); - - $instance = new class ($deprecatedMethodListener) extends WP_Mock { - /** - * @param DeprecatedMethodListener $deprecatedMethodListener - */ - public function __construct(DeprecatedMethodListener $deprecatedMethodListener) - { - static::$deprecatedMethodListener = $deprecatedMethodListener; - } - - /** - * @param array $args - * @return string - */ - public function deprecatedMethod(array $args = []): string - { - static::getDeprecatedMethodListener()->logDeprecatedCall(__METHOD__, $args); - - return 'test'; - } - }; - - $mockTestResult->expects('addFailure') - ->once() - ->with($mockTestCase, Mockery::type(RiskyTestError::class), 0); - - $deprecatedMethodListener->setTestCase($mockTestCase); - $deprecatedMethodListener->setTestResult($mockTestResult); - - $instance->deprecatedMethod(['foo' => 'bar']); - - $deprecatedMethodListener->checkCalls(); - - $this->assertConditionsMet(); + // Use a named fixture (defined below) rather than an anonymous class: anonymous class + // names embed a null byte that trigger_error() truncates on PHP <= 8.1, which would drop + // the method name from the deprecation message. + $instance = new WpMockWithDeprecatedMethod($deprecatedMethodListener); + + $result = null; + + $messages = $this->captureDeprecations(function () use ($instance, &$result) { + $result = $instance->deprecatedMethod(['foo' => 'bar']); + }); + + // the deprecated method still returns normally (a deprecation is a notice, not a hard stop) + $this->assertSame('test', $result); + $this->assertCount(1, $messages); + $this->assertStringContainsString('deprecatedMethod', $messages[0]); } /** @@ -416,7 +210,7 @@ public function deprecatedMethod(array $args = []): string * @see DeprecatedMethodListener::$deprecatedCalls * * @param DeprecatedMethodListener $listener - * @return array}> + * @return array}> the logged [$method, $args] pairs * @throws ReflectionException */ protected function getDeprecatedMethodCalls(DeprecatedMethodListener $listener): array @@ -426,6 +220,38 @@ protected function getDeprecatedMethodCalls(DeprecatedMethodListener $listener): $value = $property->getValue($listener); - return is_array($value) ? $value : []; + if (! is_array($value)) { + return []; + } + + /** @var array}> $value */ + return $value; + } +} + +/** + * Named WP_Mock subclass with a deprecated method, used by + * {@see DeprecatedMethodListenerTest::testCanHandleDeprecatedMethodCallThroughWpMock()}. + * + * Intentionally a named (not anonymous) class so `__METHOD__` is stable and free of the null byte + * that anonymous class names embed — which `trigger_error()` truncates on PHP <= 8.1, dropping the + * method name from the captured deprecation message. + */ +final class WpMockWithDeprecatedMethod extends WP_Mock +{ + public function __construct(DeprecatedMethodListener $deprecatedMethodListener) + { + static::$deprecatedMethodListener = $deprecatedMethodListener; + } + + /** + * @param array $args + * @return string + */ + public function deprecatedMethod(array $args = []): string + { + static::getDeprecatedMethodListener()->logDeprecatedCall(__METHOD__, $args); + + return 'test'; } } diff --git a/tests/Unit/WP_Mock/Functions/HandlerTest.php b/tests/Unit/WP_Mock/Functions/HandlerTest.php index 4d8eec6..41009cc 100644 --- a/tests/Unit/WP_Mock/Functions/HandlerTest.php +++ b/tests/Unit/WP_Mock/Functions/HandlerTest.php @@ -3,19 +3,18 @@ namespace Unit\WP_Mock\Functions; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\PreserveGlobalState; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use ReflectionProperty; use WP_Mock; use WP_Mock\Functions\Handler; use WP_Mock\Tests\WP_MockTestCase; -/** - * @covers \WP_Mock\Functions\Handler - */ +#[CoversClass(Handler::class)] final class HandlerTest extends WP_MockTestCase { /** - * @covers \WP_Mock\Functions\Handler::registerHandler() - * * @return void * @throws Exception */ @@ -43,14 +42,11 @@ public function testCanRegisterHandler(): void } /** - * @covers \WP_Mock\Functions\Handler::handleFunction() - * - * @preserveGlobalState disabled - * @runInSeparateProcess - * * @return void * @throws Exception */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanHandleFunction(): void { $this->assertNull(Handler::handleFunction('invalid')); @@ -66,14 +62,11 @@ public function testCanHandleFunction(): void } /** - * @covers \WP_Mock\Functions\Handler::handlerExists() - * - * @preserveGlobalState disabled - * @runInSeparateProcess - * * @return void * @throws Exception */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanDetermineHandlerExists(): void { $functionName = 'test_function'; @@ -89,14 +82,11 @@ public function testCanDetermineHandlerExists(): void } /** - * @covers \WP_Mock\Functions\Handler::cleanup() - * - * @preserveGlobalState disabled - * @runInSeparateProcess - * * @return void * @throws Exception */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanCleanup(): void { $property = new ReflectionProperty(Handler::class, 'handlers'); @@ -114,14 +104,11 @@ public function testCanCleanup(): void } /** - * @covers \WP_Mock\Functions\Handler::handlePredefinedReturnFunction() - * - * @preserveGlobalState disabled - * @runInSeparateProcess - * * @return void * @throws Exception */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanHandlePredefinedReturnFunction(): void { WP_Mock::bootstrap(); @@ -135,14 +122,11 @@ public function testCanHandlePredefinedReturnFunction(): void } /** - * @covers \WP_Mock\Functions\Handler::handlePredefinedEchoFunction() - * - * @preserveGlobalState disabled - * @runInSeparateProcess - * * @return void * @throws Exception */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanHandlePredefinedEchoFunction(): void { WP_Mock::bootstrap(); diff --git a/tests/Unit/WP_Mock/Functions/ReturnSequenceTest.php b/tests/Unit/WP_Mock/Functions/ReturnSequenceTest.php index 5172a9a..169304c 100644 --- a/tests/Unit/WP_Mock/Functions/ReturnSequenceTest.php +++ b/tests/Unit/WP_Mock/Functions/ReturnSequenceTest.php @@ -3,18 +3,15 @@ namespace WP_Mock\Tests\Unit\WP_Mock\Functions; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; use ReflectionProperty; use WP_Mock\Functions\ReturnSequence; use WP_Mock\Tests\WP_MockTestCase; -/** - * @covers \WP_Mock\Functions\ReturnSequence - */ +#[CoversClass(ReturnSequence::class)] final class ReturnSequenceTest extends WP_MockTestCase { /** - * @covers \WP_Mock\Functions\ReturnSequence::__construct() - * * @return void * @throws Exception */ @@ -28,9 +25,6 @@ public function testConstructor(): void } /** - * @covers \WP_Mock\Functions\ReturnSequence::getReturnValues() - * @covers \WP_Mock\Functions\ReturnSequence::setReturnValues() - * * @return void * @throws Exception */ diff --git a/tests/Unit/WP_Mock/FunctionsTest.php b/tests/Unit/WP_Mock/FunctionsTest.php index f82e980..670bfa2 100644 --- a/tests/Unit/WP_Mock/FunctionsTest.php +++ b/tests/Unit/WP_Mock/FunctionsTest.php @@ -9,6 +9,10 @@ use Mockery\CountValidator\Exact; use Mockery\Expectation; use Mockery\Mock; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\PreserveGlobalState; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use ReflectionException; use ReflectionMethod; use ReflectionProperty; @@ -16,20 +20,15 @@ use WP_Mock\Functions\Handler; use WP_Mock\Tests\WP_MockTestCase; -/** - * @covers \WP_Mock\Functions - */ +#[CoversClass(Functions::class)] final class FunctionsTest extends WP_MockTestCase { /** - * @covers \WP_Mock\Functions::__construct() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void * @throws ReflectionException|Exception */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanInitialize(): void { $functions = new Functions(); @@ -80,14 +79,11 @@ public function testCanInitialize(): void } /** - * @covers \WP_Mock\Functions::register() - * - * @preserveGlobalState disabled - * @runInSeparateProcess - * * @return void * @throws Exception */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanRegister(): void { $handler = new ReflectionProperty(Handler::class, 'handlers'); @@ -118,13 +114,11 @@ public function testCanRegister(): void } /** - * @covers \WP_Mock\Functions::setUpMock() - * @dataProvider providerCanSetUpMock - * * @param array $expectationArgs * @return void * @throws Exception */ + #[DataProvider('providerCanSetUpMock')] public function testCanSetupMock(array $expectationArgs): void { $functions = new Functions(); @@ -172,7 +166,7 @@ public function testCanSetupMock(array $expectationArgs): void } /** @see testCanSetupMock */ - public function providerCanSetUpMock(): Generator + public static function providerCanSetUpMock(): Generator { yield 'With args' => [['args' => ['foo', 'bar']]]; yield 'With return value' => [['return' => 'foo']]; @@ -180,14 +174,12 @@ public function providerCanSetUpMock(): Generator } /** - * @covers \WP_Mock\Functions::generateFunction() - * @dataProvider providerCanGenerateFunction - * * @param bool $willCreate * @param bool $willReplace * @return void * @throws ReflectionException|Exception */ + #[DataProvider('providerCanGenerateFunction')] public function testCanGenerateFunction(bool $willCreate, bool $willReplace): void { $functionName = 'myFunction'; @@ -221,7 +213,7 @@ public function testCanGenerateFunction(bool $willCreate, bool $willReplace): vo } /** @see testCanGenerateFunction */ - public function providerCanGenerateFunction(): Generator + public static function providerCanGenerateFunction(): Generator { yield 'Function is created' => [true, false]; yield 'Function is replaced' => [false, true]; @@ -229,12 +221,6 @@ public function providerCanGenerateFunction(): Generator } /** - * @covers \WP_Mock\Functions::createFunction() - * @dataProvider providerCanCreateFunction - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @param string $functionName * @param string[] $functionsList * @param bool $functionWillExist @@ -243,6 +229,9 @@ public function providerCanGenerateFunction(): Generator * @return void * @throws ReflectionException|Exception */ + #[DataProvider('providerCanCreateFunction')] + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanCreateFunction(string $functionName, array $functionsList, bool $functionWillExist, bool $functionWillBeRegistered, bool $expectedReturnValue): void { $functions = new Functions(); @@ -266,7 +255,7 @@ public function testCanCreateFunction(string $functionName, array $functionsList } /** @see testCanCreateFunction */ - public function providerCanCreateFunction(): Generator + public static function providerCanCreateFunction(): Generator { yield 'Function is already registered' => ['myWpMockFunction', ['myWpMockFunction'], false, true, true]; yield 'Function already exists' => ['str_replace', [], true, false, false]; @@ -274,8 +263,6 @@ public function providerCanCreateFunction(): Generator } /** - * @covers \WP_Mock\Functions::replaceFunction() - * * @return void * @throws ReflectionException|Exception */ @@ -295,8 +282,6 @@ public function testCanReplaceFunction(): void } /** - * @covers \WP_Mock\Functions::sanitizeFunctionName() - * * @return void * @throws ReflectionException|Exception */ @@ -312,14 +297,12 @@ public function testCanSanitizeFunctionName(): void } /** - * @covers \WP_Mock\Functions::validateFunctionName() - * @dataProvider providerCanValidateFunction - * * @param string $functionName * @param bool $validates * @return void * @throws ReflectionException|Exception */ + #[DataProvider('providerCanValidateFunction')] public function testCanValidateFunction(string $functionName, bool $validates): void { if (! $validates) { @@ -335,7 +318,7 @@ public function testCanValidateFunction(string $functionName, bool $validates): } /** @see testCanValidateFunction */ - public function providerCanValidateFunction(): Generator + public static function providerCanValidateFunction(): Generator { yield 'Invalid function name' => ['#!?', false]; yield 'Internal PHP function' => ['str_replace', false]; @@ -344,15 +327,13 @@ public function providerCanValidateFunction(): Generator } /** - * @covers \WP_Mock\Functions::anyOf() - * @dataProvider providerMatchAnyTypes - * * @param bool $expected * @param mixed $matchedValue * @param mixed...$typesToMatch * @return void * @throws Exception */ + #[DataProvider('providerMatchAnyTypes')] public function testCanSetUpArgumentPlaceholderOfAnyType(bool $expected, $matchedValue, $typesToMatch): void { $anyType = Functions::anyOf($typesToMatch); @@ -361,7 +342,7 @@ public function testCanSetUpArgumentPlaceholderOfAnyType(bool $expected, $matche } /** @see testCanSetUpArgumentPlaceholderOfAnyType */ - public function providerMatchAnyTypes(): Generator + public static function providerMatchAnyTypes(): Generator { yield 'Match expected string' => [true, 'string', 'string']; yield 'Does not match expected string' => [false, 'string', 123]; @@ -372,14 +353,12 @@ public function providerMatchAnyTypes(): Generator } /** - * @covers \WP_Mock\Functions::type() - * @dataProvider providerMatchTypes - * * @param string $typeToMatch * @param mixed $matchedValue * @return void * @throws Exception */ + #[DataProvider('providerMatchTypes')] public function testCanSetUpArgumentPlaceholderOfStrictType(string $typeToMatch, $matchedValue): void { $type = Functions::type($typeToMatch); @@ -388,7 +367,7 @@ public function testCanSetUpArgumentPlaceholderOfStrictType(string $typeToMatch, } /** @see testCanSetUpArgumentPlaceholderOfType */ - public function providerMatchTypes(): Generator + public static function providerMatchTypes(): Generator { yield ['string', 'string']; yield ['integer', 1]; diff --git a/tests/Unit/WP_Mock/HookTest.php b/tests/Unit/WP_Mock/HookTest.php index fcfecf3..8a78e14 100644 --- a/tests/Unit/WP_Mock/HookTest.php +++ b/tests/Unit/WP_Mock/HookTest.php @@ -6,38 +6,38 @@ use Generator; use Exception; use Mockery; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use ReflectionException; use stdClass; use WP_Mock\Hook; use WP_Mock\Traits\AccessInaccessibleClassMembersTrait; -/** - * @covers \WP_Mock\Hook - */ +#[CoversClass(Hook::class)] +#[AllowMockObjectsWithoutExpectations] final class HookTest extends TestCase { use AccessInaccessibleClassMembersTrait; /** - * @covers \WP_Mock\Hook::safe_offset() - * @dataProvider providerSafeOffset - * * @param mixed $value * @param string $expected * @return void * @throws ReflectionException|Exception */ + #[DataProvider('providerSafeOffset')] public function testCanParseSafeOffSet($value, string $expected): void { - $instance = $this->getMockForAbstractClass(Hook::class, [], '', false); + $instance = $this->createPartialMock(Hook::class, ['new_responder', 'get_strict_mode_message']); $method = $this->getInaccessibleMethod($instance, 'safe_offset'); $this->assertSame($expected, $method->invokeArgs($instance, [$value])); } /** @see testCanParseSafeOffset */ - public function providerSafeOffset(): Generator + public static function providerSafeOffset(): Generator { $callbackInstance = new class () { public function callback(): bool diff --git a/tests/Unit/WP_Mock/Matcher/AnyInstanceTest.php b/tests/Unit/WP_Mock/Matcher/AnyInstanceTest.php index 049a99a..aa7edf6 100644 --- a/tests/Unit/WP_Mock/Matcher/AnyInstanceTest.php +++ b/tests/Unit/WP_Mock/Matcher/AnyInstanceTest.php @@ -3,20 +3,17 @@ namespace WP_Mock\Tests\Unit\WP_Mock\Matcher; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; use ReflectionException; use WP_Mock\Matcher\AnyInstance; use WP_Mock\Tests\Mocks\SampleClass; use WP_Mock\Tests\Mocks\SampleSubClass; use WP_Mock\Tests\WP_MockTestCase; -/** - * @covers \WP_Mock\Matcher\AnyInstance - */ +#[CoversClass(AnyInstance::class)] class AnyInstanceTest extends WP_MockTestCase { /** - * @covers \WP_Mock\Matcher\AnyInstance::match() - * * @return void * @throws ReflectionException|Exception */ @@ -32,8 +29,6 @@ public function testExactClassInstanceMatchesTrue(): void } /** - * @covers \WP_Mock\Matcher\AnyInstance::match() - * * @return void * @throws ReflectionException|Exception */ @@ -49,8 +44,6 @@ public function testExactClassStringMatchesTrue(): void } /** - * @covers \WP_Mock\Matcher\AnyInstance::match() - * * @return void * @throws ReflectionException|Exception */ @@ -66,8 +59,6 @@ public function testSubClassMatchesTrue(): void } /** - * @covers \WP_Mock\Matcher\AnyInstance::match() - * * @return void * @throws ReflectionException|Exception */ @@ -83,8 +74,6 @@ public function testWrongClassMatchesFalse(): void } /** - * @covers \WP_Mock\Matcher\AnyInstance::match() - * * @return void * @throws ReflectionException|Exception */ @@ -101,8 +90,6 @@ public function testClosureMatchesFalse(): void } /** - * @covers \WP_Mock\Matcher\AnyInstance::match() - * * @return void * @throws ReflectionException|Exception */ @@ -118,8 +105,6 @@ public function testStringFunctionMatchesFalse(): void } /** - * @covers \WP_Mock\Matcher\AnyInstance::__toString() - * * @return void * @throws Exception */ @@ -133,8 +118,6 @@ public function testToString(): void } /** - * @covers \WP_Mock\Matcher\AnyInstance::__construct() - * * @return void * @throws Exception */ diff --git a/tests/Unit/WP_Mock/Matcher/FuzzyObjectTest.php b/tests/Unit/WP_Mock/Matcher/FuzzyObjectTest.php index 679e501..094536c 100644 --- a/tests/Unit/WP_Mock/Matcher/FuzzyObjectTest.php +++ b/tests/Unit/WP_Mock/Matcher/FuzzyObjectTest.php @@ -6,6 +6,8 @@ use Generator; use Mockery; use Mockery\Exception as MockeryException; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use ReflectionException; use ReflectionMethod; @@ -14,20 +16,16 @@ use WP_Mock\Tests\Mocks\SampleClassTwo; use WP_Mock\Tests\Mocks\SampleSubClass; -/** - * @covers \WP_Mock\Matcher\FuzzyObject - */ +#[CoversClass(FuzzyObject::class)] final class FuzzyObjectTest extends TestCase { /** - * @covers \WP_Mock\Matcher\FuzzyObject::__construct() - * @dataProvider providerCanConstruct - * * @param object|array|mixed $expected * @param bool $shouldThrowException * @return void * @throws Exception */ + #[DataProvider('providerCanConstruct')] public function testCanConstruct($expected, bool $shouldThrowException): void { if ($shouldThrowException) { @@ -40,7 +38,7 @@ public function testCanConstruct($expected, bool $shouldThrowException): void } /** @see testCanConstruct */ - public function providerCanConstruct(): Generator + public static function providerCanConstruct(): Generator { yield 'Can construct when $expected is object' => [ 'expected' => new SampleClass(), @@ -79,15 +77,13 @@ public function providerCanConstruct(): Generator } /** - * @covers \WP_Mock\Matcher\FuzzyObject::match() - * @dataProvider providerCanMatch - * * @param mixed $testClass * @param object $expectedClass * @param bool $expectedResult * @return void * @throws Exception */ + #[DataProvider('providerCanMatch')] public function testCanMatch($testClass, object $expectedClass, bool $expectedResult): void { /** @var FuzzyObject&Mockery\LegacyMockInterface&Mockery\MockInterface $partialMock */ @@ -107,7 +103,7 @@ public function testCanMatch($testClass, object $expectedClass, bool $expectedRe } /** @see testCanMatch */ - public function providerCanMatch(): Generator + public static function providerCanMatch(): Generator { yield 'False when test class is not a class.' => [ 'testClass' => 'not a class', @@ -178,15 +174,13 @@ public function providerCanMatch(): Generator } /** - * @covers \WP_Mock\Matcher\FuzzyObject::haveCommonAncestor() - * @dataProvider providerCanDetermineHaveCommonAncestor - * * @param object|mixed $object1 * @param object|mixed $object2 * @param bool $expectedResult * @return void * @throws ReflectionException|Exception */ + #[DataProvider('providerCanDetermineHaveCommonAncestor')] public function testCanDetermineIfTwoObjectsHaveCommonAncestor($object1, $object2, bool $expectedResult): void { $instance = new FuzzyObject(new SampleClass()); @@ -198,7 +192,7 @@ public function testCanDetermineIfTwoObjectsHaveCommonAncestor($object1, $object } /** @see testCanDetermineIfTwoObjectsHaveCommonAncestor */ - public function providerCanDetermineHaveCommonAncestor(): Generator + public static function providerCanDetermineHaveCommonAncestor(): Generator { yield 'False when object1 is not an object' => [ 'object1' => 'not an object', @@ -232,14 +226,12 @@ public function providerCanDetermineHaveCommonAncestor(): Generator } /** - * @covers \WP_Mock\Matcher\FuzzyObject::__toString() - * @dataProvider providerToString - * * @param object|mixed $object * @param string $expectedResult * @return void * @throws Exception */ + #[DataProvider('providerToString')] public function testCanConvertToString($object, string $expectedResult): void { $instance = new FuzzyObject($object); @@ -248,10 +240,10 @@ public function testCanConvertToString($object, string $expectedResult): void } /** @see testCanConvertToString */ - public function providerToString(): Generator + public static function providerToString(): Generator { yield 'With expected object with all types of properties' => [ - 'expected' => new class() { + 'object' => new class() { /** @var string[] */ public $testPropertyIsArray = ['foo','bar']; @@ -271,17 +263,17 @@ public function __construct() $this->testPropertyIsResource = stream_context_create(); } }, - 'expectedString' => '', + 'expectedResult' => '', ]; yield 'With expected object with no properties' => [ - 'expected' => new class() {}, - 'expectedString' => '', + 'object' => new class() {}, + 'expectedResult' => '', ]; yield 'With array' => [ - 'expected' => ['foo','bar'], - 'expectedString' => '', + 'object' => ['foo','bar'], + 'expectedResult' => '', ]; } } diff --git a/tests/Unit/WP_Mock/Tools/Constraints/ExpectationsMetTest.php b/tests/Unit/WP_Mock/Tools/Constraints/ExpectationsMetTest.php index 00d4c10..071f856 100644 --- a/tests/Unit/WP_Mock/Tools/Constraints/ExpectationsMetTest.php +++ b/tests/Unit/WP_Mock/Tools/Constraints/ExpectationsMetTest.php @@ -3,20 +3,17 @@ namespace WP_Mock\Tests\Unit\WP_Mock\Tools\Constraints; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; use ReflectionException; use ReflectionMethod; use ReflectionProperty; use WP_Mock\Tests\WP_MockTestCase; use WP_Mock\Tools\Constraints\ExpectationsMet; -/** - * @covers \WP_Mock\Tools\Constraints\ExpectationsMet - */ +#[CoversClass(ExpectationsMet::class)] final class ExpectationsMetTest extends WP_MockTestCase { /** - * @covers \WP_Mock\Tools\Constraints\ExpectationsMet::matches() - * * @return void * @throws Exception */ @@ -28,8 +25,6 @@ public function testMatches(): void } /** - * @covers \WP_Mock\Tools\Constraints\ExpectationsMet::toString() - * * @return void * @throws Exception */ @@ -39,8 +34,6 @@ public function testCanConvertToString(): void } /** - * @covers \WP_Mock\Tools\Constraints\ExpectationsMet::failureDescription() - * * @return void * @throws ReflectionException|Exception */ @@ -54,8 +47,6 @@ public function testCanGetFailureDescription(): void } /** - * @covers \WP_Mock\Tools\Constraints\ExpectationsMet::additionalFailureDescription() - * * @return void * @throws ReflectionException|Exception */ diff --git a/tests/Unit/WP_Mock/Tools/Constraints/IsEqualHtmlTest.php b/tests/Unit/WP_Mock/Tools/Constraints/IsEqualHtmlTest.php index 444650f..0edb731 100644 --- a/tests/Unit/WP_Mock/Tools/Constraints/IsEqualHtmlTest.php +++ b/tests/Unit/WP_Mock/Tools/Constraints/IsEqualHtmlTest.php @@ -4,46 +4,32 @@ use Exception; use Generator; -use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use ReflectionException; use ReflectionMethod; use ReflectionProperty; use WP_Mock\Tests\WP_MockTestCase; use WP_Mock\Tools\Constraints\IsEqualHtml; -/** - * @covers \WP_Mock\Tools\Constraints\IsEqualHtml - */ +#[CoversClass(IsEqualHtml::class)] final class IsEqualHtmlTest extends WP_MockTestCase { /** - * @covers \WP_Mock\Tools\Constraints\IsEqualHtml::__construct() - * * @return void * @throws ReflectionException|Exception */ public function testConstructor(): void { - $props = [ - 'value' => 'Test', - 'delta' => 1.2, - 'canonicalize' => true, - 'ignoreCase' => true, - ]; - - $constraint = new IsEqualHtml($props['value'], $props['delta'], $props['canonicalize'], $props['ignoreCase']); + $constraint = new IsEqualHtml('Test'); - foreach ($props as $key => $value) { - $property = new ReflectionProperty($constraint, $key); - $property->setAccessible(true); + $property = new ReflectionProperty($constraint, 'value'); + $property->setAccessible(true); - $this->assertSame($value, $property->getValue($constraint)); - } + $this->assertSame('Test', $property->getValue($constraint)); } /** - * @covers \WP_Mock\Tools\Constraints\IsEqualHtml::clean() - * * @return void * @throws ReflectionException|Exception */ @@ -58,70 +44,43 @@ public function testCanClean(): void } /** - * @covers \WP_Mock\Tools\Constraints\IsEqualHtml::evaluate() - * @dataProvider providerEvaluate - * * @param string $value * @param string $otherValue - * @param bool $returnResult - * @param bool|null $expected - * @param bool|null $throwsException + * @param bool $expected * @return void * @throws Exception */ - public function testCanEvaluate( - string $value, - string $otherValue, - bool $returnResult, - ?bool $expected, - ?bool $throwsException = null - ): void { + #[DataProvider('providerMatches')] + public function testCanMatch(string $value, string $otherValue, bool $expected): void + { $constraint = new IsEqualHtml($value); - if ($throwsException) { - $this->expectException(ExpectationFailedException::class); - } - - $this->assertSame($expected, $constraint->evaluate($otherValue, 'Test error message', $returnResult)); + $this->assertSame($expected, $constraint->matches($otherValue)); } - /** @see testCanEvaluate */ - public function providerEvaluate(): Generator + /** @see testCanMatch */ + public static function providerMatches(): Generator { - yield 'The two HTML strings are the same (return bool)' => [ + yield 'identical HTML' => [ 'value' => 'Test', 'otherValue' => 'Test', - 'returnResult' => true, 'expected' => true, ]; - yield 'The two HTML strings are the same (throw exception)' => [ - 'value' => 'Test', + yield 'whitespace-insensitive match' => [ + 'value' => "\n\t Test", 'otherValue' => 'Test', - 'returnResult' => false, - 'expected' => null, - 'throwsException' => false, + 'expected' => true, ]; - yield 'The two HTML strings are not the same (return bool)' => [ + yield 'different HTML' => [ 'value' => 'Test', 'otherValue' => 'Test', - 'returnResult' => true, 'expected' => false, ]; - - yield 'The two HTML strings are not the same (throw exception)' => [ - 'value' => 'Test', - 'otherValue' => 'Test', - 'returnResult' => false, - 'expected' => null, - 'throwsException' => true, - ]; } /** - * @covers \WP_Mock\Tools\Constraints\IsEqualHtml::toString() - * * @return void * @throws Exception */ diff --git a/tests/Unit/WP_Mock/Tools/TestCaseTest.php b/tests/Unit/WP_Mock/Tools/TestCaseTest.php index f9e6e84..3a867c0 100644 --- a/tests/Unit/WP_Mock/Tools/TestCaseTest.php +++ b/tests/Unit/WP_Mock/Tools/TestCaseTest.php @@ -4,25 +4,25 @@ use Exception; use Generator; -use InvalidArgumentException; use Mockery; +use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\PreserveGlobalState; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use PHPUnit\Framework\ExpectationFailedException; use ReflectionException; use ReflectionMethod; use ReflectionProperty; use WP_Mock; -use WP_Mock\DeprecatedMethodListener; use WP_Mock\Tests\WP_MockTestCase; use WP_Mock\Tools\TestCase; -/** - * @covers \WP_Mock\Tools\TestCase - */ +#[CoversClass(TestCase::class)] +#[AllowMockObjectsWithoutExpectations] final class TestCaseTest extends WP_MockTestCase { /** - * @covers \WP_Mock\Tools\TestCase::setUp() - * * @return void * @throws Exception */ @@ -32,12 +32,10 @@ public function testCanSetUpTests(): void $_GET = 'test_get'; $_REQUEST = 'test_request'; - $methods = ['requireFileDependencies', 'setUpContentFiltering', 'cleanGlobals']; - $instance = $this->getMockForAbstractClass(TestCase::class, [], '', false, false, true, $methods); + $instance = $this->createPartialMock(TestCase::class, ['requireFileDependencies', 'cleanGlobals']); - foreach ($methods as $method) { - $instance->expects($this->once())->method($method); - } + $instance->expects($this->once())->method('requireFileDependencies'); + $instance->expects($this->once())->method('cleanGlobals'); $instance->setUp(); @@ -47,22 +45,17 @@ public function testCanSetUpTests(): void } /** - * @covers \WP_Mock\Tools\TestCase::tearDown() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void * @throws Exception|ReflectionException */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanTearDownTests(): void { $wpMock = Mockery::mock('overload:WP_Mock'); $wpMock->shouldReceive('tearDown'); - $instance = $this->getMockForAbstractClass(TestCase::class, [], '', false, false, true, [ - 'cleanGlobals', - ]); + $instance = $this->createPartialMock(TestCase::class, ['cleanGlobals']); $instance->expects($this->once()) ->method('cleanGlobals'); @@ -77,73 +70,6 @@ public function testCanTearDownTests(): void } /** - * @covers \WP_Mock\Tools\TestCase::run() - * - * @doesNotPerformAssertions - * - * @return void - * @throws Exception - */ - public function testCanRunTests(): void - { - $this->markTestSkipped('Cannot create test doubles for final classes from PHPUnit.'); - } - - /** - * @covers \WP_Mock\Tools\TestCase::after() - * - * @return void - * @throws Exception - */ - public function testCanPerformLogicAfterTests(): void - { - $instance = $this->getMockForAbstractClass(TestCase::class, [], '', false, false, true, [ - 'checkDeprecatedCalls', - ]); - - $instance->expects($this->once()) - ->method('checkDeprecatedCalls'); - - $instance->after(); - } - - /** - * @covers \WP_Mock\Tools\TestCase::checkDeprecatedCalls() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * - * @return void - * @throws Exception - */ - public function testCanCheckDeprecatedCalls(): void - { - $deprecatedMethodListener = $this->getMockBuilder(DeprecatedMethodListener::class) - ->disableOriginalConstructor() - ->onlyMethods(['checkCalls', 'reset']) - ->getMock(); - - $deprecatedMethodListener->expects($this->atMost(1)) - ->method('checkCalls'); - - $deprecatedMethodListener->expects($this->atMost(1)) - ->method('reset'); - - /** @var Mockery\Mock $wpMock */ - $wpMock = Mockery::mock('overload:WP_Mock'); - /** @phpstan-ignore-next-line */ - $wpMock->shouldReceive('getDeprecatedMethodListener') - ->andReturn($deprecatedMethodListener); - - $instance = $this->getMockForAbstractClass(TestCase::class); - $method = new ReflectionMethod($instance, 'checkDeprecatedCalls'); - $method->setAccessible(true); - $method->invoke($instance); - } - - /** - * @covers \WP_Mock\Tools\TestCase::cleanGlobals() - * * @return void * @throws ReflectionException|Exception */ @@ -154,7 +80,7 @@ public function testCanCleanGlobals(): void $post = 'foo'; $wp_query = 'bar'; - $instance = $this->getMockForAbstractClass(TestCase::class); + $instance = $this->createPartialMock(TestCase::class, []); $method = new ReflectionMethod($instance, 'cleanGlobals'); $method->setAccessible(true); $method->invoke($instance); @@ -164,53 +90,16 @@ public function testCanCleanGlobals(): void } /** - * @covers \WP_Mock\Tools\TestCase::setUpContentFiltering() - * - * @return void - * @throws ReflectionException|Exception - */ - public function testCanSetUpContentFiltering(): void - { - $instance = $this->getMockForAbstractClass(TestCase::class); - - $property = new ReflectionProperty($instance, '__contentFilterCallback'); - $property->setAccessible(true); - - $this->assertFalse($property->getValue($instance)); - - $method = new ReflectionMethod($instance, 'setUpContentFiltering'); - $method->setAccessible(true); - $method->invoke($instance); - - $this->assertSame([$instance, 'stripTabsAndNewlines'], $property->getValue($instance)); - } - - /** - * @covers \WP_Mock\Tools\TestCase::stripTabsAndNewlines() - * - * @return void - * @throws Exception - */ - public function testCanStripTabsAndNewlinesForContentFiltering(): void - { - $instance = $this->getMockForAbstractClass(TestCase::class); - - $this->assertSame('Test', $instance->stripTabsAndNewlines("\n\n\tTest\r\t")); - } - - /** - * @covers \WP_Mock\Tools\TestCase::assertActionsCalled() - * @dataProvider providerAssertActionsCalled - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @param bool $throwsException * @return void * @throws Exception - */public function testCanAssertExpectedActionsWereCalled(bool $throwsException): void + */ + #[DataProvider('providerAssertActionsCalled')] + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] + public function testCanAssertExpectedActionsWereCalled(bool $throwsException): void { - $instance = $this->getMockForAbstractClass(TestCase::class); + $instance = $this->createPartialMock(TestCase::class, []); /** @var Mockery\Mock $wpMock */ $wpMock = Mockery::mock('overload:WP_Mock'); @@ -227,26 +116,23 @@ public function testCanStripTabsAndNewlinesForContentFiltering(): void } /** @see testCanAssertExpectedActionsWereCalled */ - public function providerAssertActionsCalled(): Generator + public static function providerAssertActionsCalled(): Generator { yield 'Actions were not called' => [true]; yield 'Actions were called' => [false]; } /** - * @covers \WP_Mock\Tools\TestCase::assertHooksAdded() - * @dataProvider providerAssertHooksAdded - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @param bool $throwsException * @return void * @throws Exception */ + #[DataProvider('providerAssertHooksAdded')] + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanAssertExpectedHooksWereAdded(bool $throwsException): void { - $instance = $this->getMockForAbstractClass(TestCase::class); + $instance = $this->createPartialMock(TestCase::class, []); /** @var Mockery\Mock $wpMock */ $wpMock = Mockery::mock('overload:WP_Mock'); @@ -263,23 +149,19 @@ public function testCanAssertExpectedHooksWereAdded(bool $throwsException): void } /** @see testCanAssertExpectedHooksWereAdded */ - public function providerAssertHooksAdded(): Generator + public static function providerAssertHooksAdded(): Generator { yield 'Hooks were not added' => [true]; yield 'Hooks were added' => [false]; } /** - * @covers \WP_Mock\Tools\TestCase::assertCurrentConditionsMet() - * * @return void * @throws Exception */ public function testCanAssertCurrentTestConditionsWereMet(): void { - $instance = $this->getMockForAbstractClass(TestCase::class, [], '', true, true, true, [ - 'assertConditionsMet' - ]); + $instance = $this->createPartialMock(TestCase::class, ['assertConditionsMet']); $instance->expects($this->once()) ->method('assertConditionsMet') @@ -289,82 +171,61 @@ public function testCanAssertCurrentTestConditionsWereMet(): void } /** - * @covers \WP_Mock\Tools\TestCase::assertConditionsMet() - * * @return void */ public function testCanAssertTestConditionsWereMet(): void { - $instance = $this->getMockForAbstractClass(TestCase::class); + $instance = $this->createPartialMock(TestCase::class, []); - // this will intentionally always pass and there are no assertions to be made + // this will intentionally always pass $instance->assertConditionsMet('test'); } /** - * @covers \WP_Mock\Tools\TestCase::expectOutputString() - * @dataProvider providerExpectOutputString - * - * @param bool $expectException * @return void - * @throws ReflectionException|Exception + * @throws Exception */ - public function testCanExpectOutputString(bool $expectException): void + public function testCanAssertEqualsHtml(): void { - $instance = $this->getMockForAbstractClass(TestCase::class); - - if ($expectException) { - $property = new ReflectionProperty($instance, '__contentFilterCallback'); - $property->setAccessible(true); - $property->setValue($instance, function () { - return false; - }); - - $this->expectException(InvalidArgumentException::class); - } + $instance = $this->createPartialMock(TestCase::class, []); - $instance->expectOutputString('test'); + $instance->assertEqualsHtml('

test

', "

test

"); - // parent method will not run in the context of this test, this will prevent method flagging no assertions performed - $instance->assertConditionsMet(); - } + $this->expectException(ExpectationFailedException::class); - /** @see testCanExpectOutputString */ - public function providerExpectOutputString(): Generator - { - yield 'Should not throw an exception' => [false]; - yield 'Should throw an exception' => [true]; + $instance->assertEqualsHtml('

foo

', '

bar

'); } /** - * @covers \WP_Mock\Tools\TestCase::assertEqualsHtml() - * * @return void * @throws Exception */ - public function testCanAssertEqualsHtml(): void + public function testCanAssertOutputEqualsHtml(): void { - $instance = $this->getMockForAbstractClass(TestCase::class); + $instance = $this->createPartialMock(TestCase::class, []); - $instance->assertEqualsHtml('

test

', "

test

"); + // whitespace-insensitive match passes + $instance->assertOutputEqualsHtml('

test

', static function () { + echo "

\n\t test

"; + }); + // a mismatch throws $this->expectException(ExpectationFailedException::class); - $instance->assertEqualsHtml('

foo

', '

bar

'); + $instance->assertOutputEqualsHtml('

foo

', static function () { + echo '

bar

'; + }); } /** - * @covers \WP_Mock\Tools\TestCase::mockStaticMethod() - * @dataProvider providerMockStaticMethod - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @param bool $usingPatchwork * @param bool $invalidMethod * @return void * @throws ReflectionException|Exception */ + #[DataProvider('providerMockStaticMethod')] + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testCanMockStaticMethod(bool $usingPatchwork, bool $invalidMethod): void { $wpMock = Mockery::mock('overload:WP_Mock'); @@ -380,7 +241,7 @@ public static function testMethod(): bool $this->assertTrue($class::testMethod()); - $instance = $this->getMockForAbstractClass(TestCase::class); + $instance = $this->createPartialMock(TestCase::class, []); $method = new ReflectionMethod($instance, 'mockStaticMethod'); $method->setAccessible(true); @@ -396,7 +257,7 @@ public static function testMethod(): bool } /** @see testCanMockStaticMethod */ - public function providerMockStaticMethod(): Generator + public static function providerMockStaticMethod(): Generator { yield 'Patchwork is disabled' => [false, false]; yield 'Referencing invalid method' => [true, true]; diff --git a/tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php b/tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php index 0a9d6b2..08265ee 100644 --- a/tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php +++ b/tests/Unit/WP_Mock/Traits/AccessInaccessibleClassMembersTraitTest.php @@ -7,14 +7,10 @@ use ReflectionException; use WP_Mock\Traits\AccessInaccessibleClassMembersTrait; -/** - * @covers \WP_Mock\Traits\AccessInaccessibleClassMembersTrait - */ +// No coverage metadata: #[CoversTrait] requires PHPUnit 11+, but the supported floor is PHPUnit 10. final class AccessInaccessibleClassMembersTraitTest extends TestCase { /** - * @covers \WP_Mock\Traits\AccessInaccessibleClassMembersTrait::getInaccessibleProperty() - * * @return void * @throws ReflectionException|Exception */ @@ -28,8 +24,6 @@ public function testCanGetInaccessibleProperty(): void } /** - * @covers \WP_Mock\Traits\AccessInaccessibleClassMembersTrait::setInaccessibleProperty() - * * @return void * @throws ReflectionException|Exception */ @@ -42,8 +36,6 @@ public function testCanSetInaccessibleProperty(): void } /** - * @covers \WP_Mock\Traits\AccessInaccessibleClassMembersTrait::setInaccessiblePropertyValue() - * * @return void * @throws ReflectionException|Exception */ @@ -56,8 +48,6 @@ public function testCanSetInaccessiblePropertyValue() : void } /** - * @covers \WP_Mock\Traits\AccessInaccessibleClassMembersTrait::getInaccessiblePropertyValue() - * * @return void * @throws ReflectionException|Exception */ @@ -69,8 +59,6 @@ public function testCanGetInaccessiblePropertyValue(): void } /** - * @covers \WP_Mock\Traits\AccessInaccessibleClassMembersTrait::getInaccessibleMethod() - * * @return void * @throws ReflectionException|Exception */ @@ -84,8 +72,6 @@ public function testCanGetInaccessibleMethod(): void } /** - * @covers \WP_Mock\Traits\AccessInaccessibleClassMembersTrait::invokeInaccessibleMethod() - * * @return void * @throws ReflectionException|Exception */ diff --git a/tests/Unit/WP_Mock/Traits/MockWordPressObjectsTraitTest.php b/tests/Unit/WP_Mock/Traits/MockWordPressObjectsTraitTest.php index b0284a1..a72467d 100644 --- a/tests/Unit/WP_Mock/Traits/MockWordPressObjectsTraitTest.php +++ b/tests/Unit/WP_Mock/Traits/MockWordPressObjectsTraitTest.php @@ -10,20 +10,18 @@ use WP_Mock\Traits\MockWordPressObjectsTrait; use WP_Post; -/** - * @covers \WP_Mock\Traits\MockWordPressObjectsTrait - */ +// No coverage metadata: #[CoversTrait] requires PHPUnit 11+, but the supported floor is PHPUnit 10. final class MockWordPressObjectsTraitTest extends WP_MockTestCase { /** - * @covers \WP_Mock\Traits\MockWordPressObjectsTrait::mockPost() - * * @return void * @throws ReflectionException|Exception */ public function testCanMockWordPressPost(): void { - $trait = $this->getMockForTrait(MockWordPressObjectsTrait::class); + $trait = new class () { + use MockWordPressObjectsTrait; + }; $postData = [ 'ID' => 123, 'post_author' => 'johndoe', @@ -58,14 +56,14 @@ public function testCanMockWordPressPost(): void } /** - * @covers \WP_Mock\Traits\MockWordPressObjectsTrait::mockWp() - * * @return void * @throws ReflectionException|Exception */ public function testCanMockWordPressInstance(): void { - $trait = $this->getMockForTrait(MockWordPressObjectsTrait::class); + $trait = new class () { + use MockWordPressObjectsTrait; + }; $method = new ReflectionMethod($trait, 'mockWp'); $method->setAccessible(true); diff --git a/tests/Unit/WP_MockTest.php b/tests/Unit/WP_MockTest.php index 82f34c0..0c8543a 100644 --- a/tests/Unit/WP_MockTest.php +++ b/tests/Unit/WP_MockTest.php @@ -7,6 +7,10 @@ use stdClass; use Generator; use PHPUnit\Framework\Exception; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\PreserveGlobalState; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use Mockery\ExpectationInterface; use WP_Mock\Tests\WP_MockTestCase; use WP_Mock\Tests\Mocks\SampleClass; @@ -16,34 +20,26 @@ use PHPUnit\Framework\ExpectationFailedException; use SebastianBergmann\RecursionContext\InvalidArgumentException; -/** - * @covers \WP_Mock - */ +#[CoversClass(WP_Mock::class)] class WP_MockTest extends WP_MockTestCase { /** - * @covers \WP_Mock::strictMode() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void * @throws ExpectationFailedException|InvalidArgumentException */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testStrictModeOffByDefault(): void { $this->assertFalse(WP_Mock::strictMode()); } /** - * @covers \WP_Mock::activateStrictMode() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void * @throws ExpectationFailedException|InvalidArgumentException */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testActivateStrictModeTurnsStrictModeOn(): void { WP_Mock::activateStrictMode(); @@ -52,14 +48,11 @@ public function testActivateStrictModeTurnsStrictModeOn(): void } /** - * @covers \WP_Mock::strictMode() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void * @throws ExpectationFailedException|InvalidArgumentException */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testActivateStrictModeDoesNotWorkAfterBootstrap(): void { WP_Mock::bootstrap(); @@ -69,14 +62,11 @@ public function testActivateStrictModeDoesNotWorkAfterBootstrap(): void } /** - * @covers \WP_Mock::userFunction() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void * @throws Exception|InvalidArgumentException|\InvalidArgumentException */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testUserFunctionReturnsExpectationContract(): void { WP_Mock::bootstrap(); @@ -88,13 +78,10 @@ public function testUserFunctionReturnsExpectationContract(): void } /** - * @covers \WP_Mock::assertHooksAdded() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testAssertHooksAddedForFiltersAndActionsPasses(): void { WP_Mock::bootstrap(); @@ -114,13 +101,10 @@ public function testAssertHooksAddedForFiltersAndActionsPasses(): void } /** - * @covers \WP_Mock::assertHooksAdded() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testAssertHooksAddedForFiltersAndActionsFails(): void { try { @@ -141,13 +125,10 @@ public function testAssertHooksAddedForFiltersAndActionsFails(): void } /** - * @covers \WP_Mock::assertActionsCalled() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testAssertActionsCalledPasses(): void { WP_Mock::bootstrap(); @@ -161,13 +142,10 @@ public function testAssertActionsCalledPasses(): void } /** - * @covers \WP_Mock::assertActionsCalled() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testAssertActionsCalledFails(): void { try { @@ -185,13 +163,10 @@ public function testAssertActionsCalledFails(): void } /** - * @covers \WP_Mock::assertFiltersCalled() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testAssertFiltersCalledPasses(): void { WP_Mock::bootstrap(); @@ -206,13 +181,10 @@ public function testAssertFiltersCalledPasses(): void } /** - * @covers \WP_Mock::assertFiltersCalled() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testAssertFiltersCalledFails(): void { WP_Mock::bootstrap(); @@ -225,13 +197,10 @@ public function testAssertFiltersCalledFails(): void } /** - * @covers \WP_Mock::assertFiltersCalled() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testAssertFiltersPassesWithTypes(): void { WP_Mock::bootstrap(); @@ -246,8 +215,6 @@ public function testAssertFiltersPassesWithTypes(): void } /** - * @covers \WP_Mock::alias() - * * @return void * @throws Exception|InvalidArgumentException|\InvalidArgumentException */ @@ -267,14 +234,12 @@ public function testCanAliasFunction(): void } /** - * @covers \WP_Mock::fuzzyObject() - * @dataProvider providerFuzzyObject - * * @param array|object|mixed $object * @param string $expected * @return void * @throws Exception|Mockery\Exception|InvalidArgumentException */ + #[DataProvider('providerFuzzyObject')] public function testCanInstantiateFuzzyObject($object, string $expected): void { if (! is_object($object) && ! is_array($object)) { @@ -288,7 +253,7 @@ public function testCanInstantiateFuzzyObject($object, string $expected): void } /** @see testCanInstantiateFuzzyObject */ - public function providerFuzzyObject(): Generator + public static function providerFuzzyObject(): Generator { $stdClass = new stdClass(); $stdClass->baz = 'boz'; @@ -299,8 +264,6 @@ public function providerFuzzyObject(): Generator } /** - * @covers \WP_Mock::getDeprecatedMethodListener() - * * @return void * @throws Exception|InvalidArgumentException */ @@ -314,14 +277,11 @@ public function testCanGetDeprecatedMethodListener(): void } /** - * @covers \WP_Mock::onFilter() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void * @throws Exception|InvalidArgumentException */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testOnFilterPasses(): void { WP_Mock::bootstrap(); @@ -339,14 +299,11 @@ public function testOnFilterPasses(): void } /** - * @covers \WP_Mock::onFilter() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void * @throws Exception|InvalidArgumentException */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testOnFilterPassesWithAnyArgs(): void { WP_Mock::bootstrap(); @@ -364,14 +321,11 @@ public function testOnFilterPassesWithAnyArgs(): void } /** - * @covers \WP_Mock::onFilter() - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * * @return void * @throws Exception|InvalidArgumentException */ + #[RunInSeparateProcess] + #[PreserveGlobalState(false)] public function testMultipleOnFilterPassesWithAnyArgs(): void { WP_Mock::bootstrap(); diff --git a/tests/WP_MockTestCase.php b/tests/WP_MockTestCase.php index 0d1ea61..9baa6d3 100644 --- a/tests/WP_MockTestCase.php +++ b/tests/WP_MockTestCase.php @@ -49,4 +49,24 @@ protected function assertConditionsMet(): void { $this->assertThat(null, new ExpectationsMet()); } + + /** + * Determines whether the current test is running in process isolation. + * + * PHPUnit 10+ removed the public `isInIsolation()` method; the state now lives in a private + * `$inIsolation` property on {@see \PHPUnit\Framework\TestCase}, which we read by reflection. + * + * @return bool + */ + protected function isRunningInIsolation(): bool + { + try { + $property = new \ReflectionProperty(TestCase::class, 'inIsolation'); + $property->setAccessible(true); + + return (bool) $property->getValue($this); + } catch (\ReflectionException $exception) { + return false; + } + } }