diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3f0673d..f511158 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,13 +16,11 @@ jobs: php_version: - '8.2' - '8.3' - dependencies: + - '8.4' + dependency-versions: + - 'lowest' - 'default' - include: - - php_version: '8.2' - dependencies: 'lowest' - - php_version: '8.3' - dependencies: 'lowest' + steps: - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -35,28 +33,10 @@ jobs: with: show-progress: false - - name: Get Composer Cache Directory - id: composer-cache - run: | - echo "::set-output name=dir::$(composer config cache-files-dir)" - - - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ matrix.dependencies }}-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer-${{ matrix.dependencies }} - - name: Install composer dependencies - env: - DEPENDENCIES: ${{ matrix.dependencies }} - run: | - if [ $DEPENDENCIES == 'lowest' ] - then - composer update --prefer-lowest --no-interaction --no-progress - else - composer install --no-interaction --no-progress - fi + uses: ramsey/composer-install@v3 + with: + dependency-versions: ${{ matrix.dependency-versions }} - name: Run unit tests run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index bc07d26..72fd167 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ### Unreleased +### v2.5.0 (2025-06-26) + +* Support PHP 8.4 + ### v2.4.0 (2025-06-05) * Fix `ObjectPropertyRipper` to handle `stdClass` objects diff --git a/composer.json b/composer.json index 873dc88..9cf80e3 100644 --- a/composer.json +++ b/composer.json @@ -16,15 +16,15 @@ ], "require": { "ext-json": "*", - "ext-mbstring": "~8.2.0 || ~8.3.0", - "ext-pdo": "~8.2.0 || ~8.3.0", - "ext-sodium": "~8.2.0 || ~8.3.0", - "php": "~8.2.0 || ~8.3.0", + "ext-mbstring": "~8.2.0 || ~8.3.0 || ~8.4.0", + "ext-pdo": "~8.2.0 || ~8.3.0 || ~8.4.0", + "ext-sodium": "~8.2.0 || ~8.3.0 || ~8.4.0", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "require-dev": { - "mikey179/vfsstream": "^1.6.11", - "phpunit/phpunit": "^11.0", + "mikey179/vfsstream": "^1.6.12", + "phpunit/phpunit": "^11.5", "ergebnis/phpunit-slow-test-detector": "^2.15" }, "support": { diff --git a/src/DateTime/DateString.php b/src/DateTime/DateString.php index 8fa4d46..059415e 100644 --- a/src/DateTime/DateString.php +++ b/src/DateTime/DateString.php @@ -22,7 +22,7 @@ class DateString * * @return string */ - public static function format(\DateTimeImmutable $date = NULL, $format, $empty_value = '') + public static function format(?\DateTimeImmutable $date, $format, $empty_value = '') { if ( ! $date) { return $empty_value; @@ -52,7 +52,7 @@ public static function isoMS(?\DateTimeImmutable $date, ?string $empty_value = ' * * @return string */ - public static function ymd(\DateTimeImmutable $date = NULL, $empty_value = '') + public static function ymd(?\DateTimeImmutable $date, $empty_value = '') { return static::format($date, 'Y-m-d', $empty_value); } @@ -65,7 +65,7 @@ public static function ymd(\DateTimeImmutable $date = NULL, $empty_value = '') * * @return string */ - public static function ymdhis(\DateTimeImmutable $date = NULL, $empty_value = '') + public static function ymdhis(?\DateTimeImmutable $date, $empty_value = '') { return static::format($date, 'Y-m-d H:i:s', $empty_value); } diff --git a/src/DeploymentConfig/DeploymentConfig.php b/src/DeploymentConfig/DeploymentConfig.php index 7d24655..cf57a67 100644 --- a/src/DeploymentConfig/DeploymentConfig.php +++ b/src/DeploymentConfig/DeploymentConfig.php @@ -58,7 +58,7 @@ public static function instance() * * @param array|NULL $env_vars - if missing will default to reading from $_SERVER */ - protected function __construct(array $env_vars = NULL) + protected function __construct(?array $env_vars = NULL) { if ($env_vars === NULL) { $env_vars = $_SERVER; diff --git a/src/Monitoring/OperationTimer.php b/src/Monitoring/OperationTimer.php index 3ed2b97..28547c5 100644 --- a/src/Monitoring/OperationTimer.php +++ b/src/Monitoring/OperationTimer.php @@ -17,7 +17,7 @@ class OperationTimer protected RealtimeClock $realtime_clock; - public function __construct(MetricsAgent $metrics_agent, RealtimeClock $realtime_clock = NULL) + public function __construct(MetricsAgent $metrics_agent, ?RealtimeClock $realtime_clock = NULL) { $this->metrics_agent = $metrics_agent; $this->realtime_clock = $realtime_clock ?? new RealtimeClock(); diff --git a/test/unit/CSV/CSVWriterTest.php b/test/unit/CSV/CSVWriterTest.php index 899f1ef..61dfb98 100644 --- a/test/unit/CSV/CSVWriterTest.php +++ b/test/unit/CSV/CSVWriterTest.php @@ -248,7 +248,7 @@ public function test_it_optionally_writes_byte_order_mark_at_start_of_file($writ if ($write_bom) { $this->assertSame(CSVWriter::UTF8_BOM, fread($file, strlen(CSVWriter::UTF8_BOM))); } - $this->assertSame(['first'], fgetcsv($file)); + $this->assertSame(['first'], fgetcsv($file, escape: '\\')); } #[TestWith([['is' => 'jumbled', 'our' => 'up']])] @@ -284,7 +284,7 @@ protected function assertCSVContent(array $expect, $file) { rewind($file); $actual = []; - while ($row = fgetcsv($file)) { + while ($row = fgetcsv($file, escape: '\\')) { $actual[] = $row; } diff --git a/test/unit/Logging/ExternalCallSiteFinderTest.php b/test/unit/Logging/ExternalCallSiteFinderTest.php index 4583f1f..22f46a4 100644 --- a/test/unit/Logging/ExternalCallSiteFinderTest.php +++ b/test/unit/Logging/ExternalCallSiteFinderTest.php @@ -129,8 +129,20 @@ function log_ab8123723123($asserter) { [ <<<'PHP' // Anonymous func + use test\unit\Ingenerator\PHPUtils\Logging\ExternalCallSiteFinderTest; return (function ($asserter) { - return $asserter->test(['file' => __FILE__, 'line' => __LINE__, 'function' => '{closure}']); + if (PHP_VERSION_ID < 80400) { + $expected_func_name = '{closure}'; + } else { + $expected_func_name = sprintf("%s->{closure:%s:%d}", + ExternalCallSiteFinderTest::class, + __FILE__, + // it's the line with the 'function' keyword + (__LINE__-8) + ); + } + return $asserter->test(['file' => __FILE__, 'line' => __LINE__, 'function' => $expected_func_name]); + })($asserter); PHP , diff --git a/test/unit/Mutex/BasicPDOStatementStub.php b/test/unit/Mutex/BasicPDOStatementStub.php index ad45199..9a05926 100644 --- a/test/unit/Mutex/BasicPDOStatementStub.php +++ b/test/unit/Mutex/BasicPDOStatementStub.php @@ -38,20 +38,8 @@ class BasicPDOStatementStub extends \PDOStatement public function __construct(array $result) { $this->result = $result; } - public function fetchAll(int $fetch_style = NULL, mixed ...$fetch_argument): array + public function fetchAll(?int $fetch_style = NULL, mixed ...$fetch_argument): array { - if (PHP_VERSION_ID < 80100) { - // Before 8.1, ints and floats were returned as strings - // https://www.php.net/manual/en/migration81.incompatible.php#migration81.incompatible.pdo.mysql - $this->result = array_map( - fn($row) => array_map( - fn($column) => (is_int($column) || \is_float($column)) ? (string) $column : $column, - $row - ), - $this->result - ); - } - if ($fetch_style === NULL) { return $this->result; } elseif ($fetch_style === PDO::FETCH_COLUMN) {