diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3584e6c..1b1e2d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,4 +31,4 @@ jobs: os: >- ['ubuntu-latest', 'windows-latest'] php: >- - ['8.1', '8.2', '8.3', '8.4'] + ['8.1', '8.2', '8.3', '8.4', '8.5'] diff --git a/.github/workflows/composer-require-checker.yml b/.github/workflows/composer-require-checker.yml index a93390b..d2ef508 100644 --- a/.github/workflows/composer-require-checker.yml +++ b/.github/workflows/composer-require-checker.yml @@ -31,4 +31,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.1', '8.2', '8.3', '8.4'] + ['8.1', '8.2', '8.3', '8.4', '8.5'] diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml index a6873e2..cc40daa 100644 --- a/.github/workflows/mutation.yml +++ b/.github/workflows/mutation.yml @@ -22,11 +22,12 @@ name: mutation test jobs: mutation: - uses: yiisoft/actions/.github/workflows/roave-infection.yml@master + uses: yiisoft/actions/.github/workflows/infection.yml@master with: os: >- ['ubuntu-latest'] php: >- - ['8.3'] + ['8.5'] + infection-args: "--ignore-msi-with-no-mutations" secrets: STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml index 5d6931d..20f7d89 100644 --- a/.github/workflows/rector.yml +++ b/.github/workflows/rector.yml @@ -21,4 +21,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.4'] + ['8.5'] diff --git a/CHANGELOG.md b/CHANGELOG.md index b616dc9..fd3c740 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 1.1.1 under development - New #64: Add `PasswordHasher::needsRehash()` method (@Gerych1984) +- Enh #69: Add PHP 8.5 support (@vjik) ## 1.1.0 February 26, 2025 diff --git a/README.md b/README.md index 2d712a9..eb32a42 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Security package provides a set of classes to handle common security-related tas ## Requirements -- PHP 8.1 or higher. +- PHP 8.1 - 8.5. - `hash` PHP extension. - `openssl` PHP extension. diff --git a/composer.json b/composer.json index 28eeea5..dcd8410 100644 --- a/composer.json +++ b/composer.json @@ -34,18 +34,17 @@ } ], "require": { - "php": "8.1 - 8.4", + "php": "8.1 - 8.5", "ext-hash": "*", "ext-openssl": "*", "yiisoft/strings": "^2.0" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", "maglnet/composer-require-checker": "^4.7.1", "phpunit/phpunit": "^10.5.45", "rector/rector": "^2.0.9", - "roave/infection-static-analysis-plugin": "^1.35", - "spatie/phpunit-watcher": "^1.24", - "vimeo/psalm": "^5.26.1 || ^6.8.8" + "spatie/phpunit-watcher": "^1.24" }, "autoload": { "psr-4": { @@ -57,15 +56,21 @@ "Yiisoft\\Security\\Tests\\": "tests" } }, + "extra": { + "bamarni-bin": { + "bin-links": true, + "target-directory": "tools", + "forward-command": true + } + }, "scripts": { "test": "phpunit --testdox --no-interaction", "test-watch": "phpunit-watcher watch" }, "config": { "sort-packages": true, - "bump-after-update": "dev", "allow-plugins": { - "infection/extension-installer": true, + "bamarni/composer-bin-plugin": true, "composer/package-versions-deprecated": true } } diff --git a/tests/TestCase.php b/tests/TestCase.php index 872d16c..0aef408 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -4,108 +4,23 @@ namespace Yiisoft\Security\Tests; +use ReflectionClass; + abstract class TestCase extends \PHPUnit\Framework\TestCase { - /** - * Invokes a inaccessible method. - * - * @param $object - * @param $method - * @param bool $revoke whether to make method inaccessible after execution - * - * @throws \ReflectionException - * - * @return mixed - */ - protected function invokeMethod($object, $method, array $args = [], bool $revoke = true) - { - $reflection = new \ReflectionObject($object); - $method = $reflection->getMethod($method); - $method->setAccessible(true); - $result = $method->invokeArgs($object, $args); - if ($revoke) { - $method->setAccessible(false); - } - - return $result; - } - - /** - * Sets an inaccessible object property to a designated value. - * - * @param $object - * @param $propertyName - * @param $value - * @param bool $revoke whether to make property inaccessible after setting - * - * @throws \ReflectionException - */ - protected function setInaccessibleProperty($object, $propertyName, $value, bool $revoke = true): void - { - $class = new \ReflectionClass($object); - while (!$class->hasProperty($propertyName)) { - $class = $class->getParentClass(); - } - $property = $class->getProperty($propertyName); - $property->setAccessible(true); - $property->setValue($object, $value); - if ($revoke) { - $property->setAccessible(false); - } - } - /** * Gets an inaccessible object property. * - * @param $object * @param bool $revoke whether to make property inaccessible after getting - * - * @throws \ReflectionException - * - * @return mixed */ - protected function getInaccessibleProperty($object, string $propertyName, bool $revoke = true) + protected function getInaccessibleProperty(object $object, string $propertyName): mixed { - $class = new \ReflectionClass($object); + $class = new ReflectionClass($object); while (!$class->hasProperty($propertyName)) { $class = $class->getParentClass(); } - $property = $class->getProperty($propertyName); - $property->setAccessible(true); - - $result = $property->getValue($object); - if ($revoke) { - $property->setAccessible(false); - } - - return $result; - } - - public function assertSameExceptObject($expected, $actual): void - { - // assert for all types - $this->assertEquals($expected, $actual); - - // no more asserts for objects - if (is_object($expected)) { - return; - } - - // asserts same for all types except objects and arrays that can contain objects - if (!is_array($expected)) { - $this->assertSame($expected, $actual); - return; - } - - // assert same for each element of the array except objects - foreach ($expected as $key => $value) { - if (!is_object($value)) { - $this->assertSame($expected[$key], $actual[$key]); - } else { - $this->assertEquals($expected[$key], $actual[$key]); - } - } + return $class->getProperty($propertyName)->getValue($object); } } diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 0000000..cf452dc --- /dev/null +++ b/tools/.gitignore @@ -0,0 +1,2 @@ +/*/vendor +/*/composer.lock diff --git a/tools/infection/composer.json b/tools/infection/composer.json new file mode 100644 index 0000000..18be2ea --- /dev/null +++ b/tools/infection/composer.json @@ -0,0 +1,10 @@ +{ + "require-dev": { + "infection/infection": "^0.26 || ^0.31.9" + }, + "config": { + "allow-plugins": { + "infection/extension-installer": true + } + } +} diff --git a/tools/psalm/composer.json b/tools/psalm/composer.json new file mode 100644 index 0000000..44e11e3 --- /dev/null +++ b/tools/psalm/composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "vimeo/psalm": "^5.26.1 || ^6.8.8" + } +}