diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f525138..5446f12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - php: ['8.4', '8.5'] + php: ['8.3', '8.4', '8.5'] name: PHP ${{ matrix.php }} steps: - uses: actions/checkout@v7 diff --git a/CHANGELOG.md b/CHANGELOG.md index a765ea3..648ffd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ ## [Unreleased] +## [0.8.2] - 2026-11-09 + +### Changed + +- Support PHP 8.3 again. The only PHP 8.4 functions in use were two + `array_any()` calls, now `array_filter()` checks with the same result. + The lock file resolves against PHP 8.3.0 and CI runs the regular suite on + PHP 8.3, 8.4 and 8.5. +- Require `openstatspec/spss-sav` ^3.2, the first codec release that runs on + PHP 8.3 and writes very long string records that IBM SPSS recognises. + The engine capability declaration now lists 3.2.0 as the CI-tested codec. + ## [0.8.1] - 2026-11-09 ### Changed diff --git a/README.md b/README.md index 9c01f42..a54302c 100644 --- a/README.md +++ b/README.md @@ -54,12 +54,12 @@ Only unencrypted SAV and ZSAV are supported. Encrypted files, Portable (`.por`) ## Requirements -- PHP 8.4.1 or later +- PHP 8.3 or later - `ext-pdo` - Selected PDO driver: `pdo_sqlite`, `pdo_pgsql`, or `pdo_mysql` - `openstatspec/spss-sav` 3.x, installed by Composer. The php-spss V3 engine needs `ext-bcmath`, `ext-mbstring` and `ext-zlib`. -Composer resolves dependencies against PHP 8.4.1, the package minimum. +Composer resolves dependencies against PHP 8.3.0, the package minimum. ## API @@ -272,7 +272,7 @@ bash tools/install-git-hooks.sh `composer check` validates Composer configuration, lints PHP, checks style, runs PHPStan and runs PHPUnit. Use `composer fix` for safe style fixes, then rerun `composer check`. -GitHub Actions runs the regular suite on PHP 8.4 and 8.5. It also runs real +GitHub Actions runs the regular suite on PHP 8.3, 8.4 and 8.5. It also runs real SAV and ZSAV integration round trips against exact PostgreSQL 17.10/18.4, MySQL 8.4.11/9.7.2, MariaDB 11.4.12/11.8.8/12.3.2, and Dolt 2.2.2/2.2.3. diff --git a/composer.json b/composer.json index ade1396..5b94c8b 100644 --- a/composer.json +++ b/composer.json @@ -12,11 +12,11 @@ ] }, "require": { - "php": "^8.4.1", + "php": "^8.3", "ext-mbstring": "*", "ext-pdo": "*", "brick/math": "^0.19", - "openstatspec/spss-sav": "^3.0" + "openstatspec/spss-sav": "^3.2" }, "repositories": [ { @@ -56,7 +56,7 @@ "config": { "sort-packages": true, "platform": { - "php": "8.4.1" + "php": "8.3.0" } }, "minimum-stability": "stable", diff --git a/composer.lock b/composer.lock index 4e6374e..e45d2de 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "722b02e08bdd232bd5b51c6da138a90d", + "content-hash": "bf5a0e31daabf051cf31dcd0b0a0080d", "packages": [ { "name": "brick/math", @@ -67,23 +67,23 @@ }, { "name": "openstatspec/spss-sav", - "version": "3.1.1", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/OpenStatSpec/php-spss.git", - "reference": "249f8a0b3a46dc503cc24f42a5c8f629e421a60b" + "reference": "a8a6d744d424eb43182f5402ca669f1fd2c45ee9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/OpenStatSpec/php-spss/zipball/249f8a0b3a46dc503cc24f42a5c8f629e421a60b", - "reference": "249f8a0b3a46dc503cc24f42a5c8f629e421a60b", + "url": "https://api.github.com/repos/OpenStatSpec/php-spss/zipball/a8a6d744d424eb43182f5402ca669f1fd2c45ee9", + "reference": "a8a6d744d424eb43182f5402ca669f1fd2c45ee9", "shasum": "" }, "require": { "ext-bcmath": "*", "ext-mbstring": "*", "ext-zlib": "*", - "php": "^8.4.1" + "php": "^8.3" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.95", @@ -213,7 +213,7 @@ "issues": "https://github.com/OpenStatSpec/php-spss/issues", "source": "https://github.com/OpenStatSpec/php-spss" }, - "time": "2026-09-07T18:47:21+00:00" + "time": "2026-11-09T16:44:14+00:00" } ], "packages-dev": [ @@ -4727,13 +4727,13 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.4.1", + "php": "^8.3", "ext-mbstring": "*", "ext-pdo": "*" }, "platform-dev": {}, "platform-overrides": { - "php": "8.4.1" + "php": "8.3.0" }, "plugin-api-version": "2.9.0" } diff --git a/src/Frontend/Spss/Compiler.php b/src/Frontend/Spss/Compiler.php index a3905a2..6cbf9e3 100644 --- a/src/Frontend/Spss/Compiler.php +++ b/src/Frontend/Spss/Compiler.php @@ -76,10 +76,10 @@ public function compile(BoundProgram $program): TransformationPlan }; } - $contract = array_any( + $contract = array_filter( $operations, static fn(Operation $operation): bool => $operation->minimumContract() === PlanContract::V02, - ) ? PlanContract::V02 : PlanContract::V01; + ) !== [] ? PlanContract::V02 : PlanContract::V01; return new TransformationPlan($contract, $program->inputAlias, $operations); } diff --git a/src/Spss/PhpSpssEngine.php b/src/Spss/PhpSpssEngine.php index 3766e62..fcf860b 100644 --- a/src/Spss/PhpSpssEngine.php +++ b/src/Spss/PhpSpssEngine.php @@ -17,7 +17,7 @@ final class PhpSpssEngine implements SpssEngine public const READER_CLASS = 'SPSS\\Sav\\Reader'; public const WRITER_CLASS = 'SPSS\\Sav\\Writer'; public const CLAIMED_VERSION_RANGE = '>=3.0.0 <4.0.0'; - public const CI_TESTED_VERSIONS = ['3.1.1']; + public const CI_TESTED_VERSIONS = ['3.2.0']; public function isAvailable(): bool { diff --git a/src/Sql/OperationJournal.php b/src/Sql/OperationJournal.php index a935287..d70534b 100644 --- a/src/Sql/OperationJournal.php +++ b/src/Sql/OperationJournal.php @@ -74,7 +74,7 @@ public function fail( $this->updateNormativeOperation($operationId, 'failed'); } - if (!array_any($diagnostics, static fn(FidelityDiagnostic $diagnostic): bool => $diagnostic->code === $failureCode)) { + if (array_filter($diagnostics, static fn(FidelityDiagnostic $diagnostic): bool => $diagnostic->code === $failureCode) === []) { $diagnostics[] = new FidelityDiagnostic( $failureCode, $exception->getMessage(), diff --git a/tests/Core/CapabilityDeclarationTest.php b/tests/Core/CapabilityDeclarationTest.php index 20fb7b8..fe0c116 100644 --- a/tests/Core/CapabilityDeclarationTest.php +++ b/tests/Core/CapabilityDeclarationTest.php @@ -66,9 +66,9 @@ public function testDeclarationIsMachineReadableAndIncludesEveryProfileLimit(): ], $contracts['opt_in_frontend_contracts']); self::assertArrayNotHasKey('legacy_plan_contracts', $contracts); self::assertFalse(class_exists(\OpenStatSpec\Transformation\Model\TransformationPlan::class)); - self::assertSame('3.1.1', $declaration['engine']['active_version']); + self::assertSame('3.2.0', $declaration['engine']['active_version']); self::assertSame('>=3.0.0 <4.0.0', $declaration['engine']['claimed_version_range']); - self::assertSame(['3.1.1'], $declaration['engine']['ci_tested_versions']); + self::assertSame(['3.2.0'], $declaration['engine']['ci_tested_versions']); self::assertTrue($declaration['engine']['claimed_supported']); self::assertNotEmpty($declaration['required_capabilities']); foreach ($declaration['required_capabilities'] as $supported) { diff --git a/tests/Integration/OfficialSpssConformanceManifestTest.php b/tests/Integration/OfficialSpssConformanceManifestTest.php index 6e06ddf..ecfa5e2 100644 --- a/tests/Integration/OfficialSpssConformanceManifestTest.php +++ b/tests/Integration/OfficialSpssConformanceManifestTest.php @@ -134,7 +134,7 @@ private function assertRequiredCapabilities(array $manifest, SpssAdapter $adapte self::assertTrue($declaration['active_connection']['claimed_supported'], $profile . ': active server version is outside the claimed profile'); self::assertSame($declaration['sql_profiles'][$profile]['claimed_server_versions'], $declaration['active_connection']['matched_claim']); self::assertTrue($declaration['engine']['claimed_supported']); - self::assertSame(['3.1.1'], $declaration['engine']['ci_tested_versions']); + self::assertSame(['3.2.0'], $declaration['engine']['ci_tested_versions']); self::assertContains($profile, array_keys($declaration['sql_profiles'] ?? [])); self::assertContains('import', $declaration['directions'] ?? []); self::assertContains('export', $declaration['directions'] ?? []); diff --git a/tests/Spss/SpssAdapterTest.php b/tests/Spss/SpssAdapterTest.php index 1709664..b48aa55 100644 --- a/tests/Spss/SpssAdapterTest.php +++ b/tests/Spss/SpssAdapterTest.php @@ -56,10 +56,10 @@ public function testComposerInstallsTheOfficialPhpSpssV3Engine(): void self::assertTrue(class_exists(Dataset::class)); self::assertSame([ 'package' => 'openstatspec/spss-sav', - 'version' => '3.1.1', - 'active_version' => '3.1.1', + 'version' => '3.2.0', + 'active_version' => '3.2.0', 'claimed_version_range' => '>=3.0.0 <4.0.0', - 'ci_tested_versions' => ['3.1.1'], + 'ci_tested_versions' => ['3.2.0'], 'claimed_supported' => true, ], (new PhpSpssEngine())->identity()); }