From daa2221cf0f5ec0ffcd34d353154b6ec7d4556d6 Mon Sep 17 00:00:00 2001 From: Tamara Date: Mon, 12 Oct 2026 13:11:52 -0500 Subject: [PATCH 01/10] [FSSDK-13266] Update dependency constraints for json-schema and murmurhash Allow justinrainbow/json-schema v6.x and lastguest/murmurhash v2.x to support newer versions of these dependencies. Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 6 ++++++ composer.json | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4377558c..87fbb0a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Optimizely PHP SDK Changelog +## 4.0.4 +October 12, 2026 + +* Update: Allow `justinrainbow/json-schema` v6.x +* Update: Allow `lastguest/murmurhash` v2.x + ## 4.0.3 May 20, 2026 diff --git a/composer.json b/composer.json index 2a28d4cd..76df92f3 100644 --- a/composer.json +++ b/composer.json @@ -17,8 +17,8 @@ "require": { "php": ">=8.1", "guzzlehttp/guzzle": ">=6.2", - "justinrainbow/json-schema": "^1.6 || ^2.0 || ^4.0 || ^5.0", - "lastguest/murmurhash": "^1.3.0", + "justinrainbow/json-schema": "^1.6 || ^2.0 || ^4.0 || ^5.0 || ^6.0", + "lastguest/murmurhash": "^1.3.0 || ^2.0", "monolog/monolog": ">=1.21" }, "require-dev": { From 99beacc45328a3e58636c3572364816efaab19d2 Mon Sep 17 00:00:00 2001 From: Tamara Date: Mon, 12 Oct 2026 13:23:01 -0500 Subject: [PATCH 02/10] [FSSDK-13266] Fix compatibility with murmurhash v2 and json-schema v6 murmurhash v2 removed the global murmurhash3_int() function in favor of a static class method. Add a function_exists() check to support both APIs. json-schema v6 deprecated check() in favor of validate(). Switch to the new method for forward compatibility. Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 2 ++ src/Optimizely/Bucketer.php | 6 +++++- src/Optimizely/Utils/Validator.php | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87fbb0a4..b72f098b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ October 12, 2026 * Update: Allow `justinrainbow/json-schema` v6.x * Update: Allow `lastguest/murmurhash` v2.x +* Fix: Add compatibility for murmurhash v2 API (global function replaced with static class method) +* Fix: Use `validate()` instead of deprecated `check()` for json-schema forward compatibility ## 4.0.3 May 20, 2026 diff --git a/src/Optimizely/Bucketer.php b/src/Optimizely/Bucketer.php index 5891649a..a77c847c 100644 --- a/src/Optimizely/Bucketer.php +++ b/src/Optimizely/Bucketer.php @@ -72,7 +72,11 @@ public function __construct(LoggerInterface $logger) */ private function generateHashCode($bucketingKey) { - return murmurhash3_int($bucketingKey, Bucketer::$HASH_SEED) & Bucketer::$UNSIGNED_MAX_32_BIT_VALUE; + // murmurhash v2 replaced the global function with a static class method + if (function_exists('murmurhash3_int')) { + return murmurhash3_int($bucketingKey, Bucketer::$HASH_SEED) & Bucketer::$UNSIGNED_MAX_32_BIT_VALUE; + } + return \lastguest\Murmur::hash3_int($bucketingKey, Bucketer::$HASH_SEED) & Bucketer::$UNSIGNED_MAX_32_BIT_VALUE; } /** diff --git a/src/Optimizely/Utils/Validator.php b/src/Optimizely/Utils/Validator.php index 803bc25b..f656e184 100644 --- a/src/Optimizely/Utils/Validator.php +++ b/src/Optimizely/Utils/Validator.php @@ -37,7 +37,8 @@ public static function validateJsonSchema($datafile, ?LoggerInterface $logger = // Validate $validator = new JsonSchema\Validator; - $validator->check($data, (object)['$ref' => 'file://' . __DIR__.'/schema.json']); + // validate() replaces check(), which was deprecated in json-schema v6 + $validator->validate($data, (object)['$ref' => 'file://' . __DIR__.'/schema.json']); if ($validator->isValid()) { return true; From 9f7997d8faf344dc76ee783009ce2cc600f25361 Mon Sep 17 00:00:00 2001 From: Tamara Date: Mon, 12 Oct 2026 13:35:25 -0500 Subject: [PATCH 03/10] [FSSDK-13266] Fix: Add check() fallback for older json-schema versions validate() does not exist in json-schema v1.6 and v2.x. Use method_exists() to call validate() when available and fall back to check() for older versions. Co-Authored-By: Claude Opus 4.6 --- src/Optimizely/Utils/Validator.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Optimizely/Utils/Validator.php b/src/Optimizely/Utils/Validator.php index f656e184..419ca695 100644 --- a/src/Optimizely/Utils/Validator.php +++ b/src/Optimizely/Utils/Validator.php @@ -37,8 +37,12 @@ public static function validateJsonSchema($datafile, ?LoggerInterface $logger = // Validate $validator = new JsonSchema\Validator; - // validate() replaces check(), which was deprecated in json-schema v6 - $validator->validate($data, (object)['$ref' => 'file://' . __DIR__.'/schema.json']); + // validate() replaces check() in newer json-schema versions + if (method_exists($validator, 'validate')) { + $validator->validate($data, (object)['$ref' => 'file://' . __DIR__.'/schema.json']); + } else { + $validator->check($data, (object)['$ref' => 'file://' . __DIR__.'/schema.json']); + } if ($validator->isValid()) { return true; From df6fdc008f0846456c5fc8026d4e2577d9357470 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Oct 2026 18:36:43 +0000 Subject: [PATCH 04/10] Add latest dependency CI coverage Co-authored-by: Tamara-Barum <88795935+Tamara-Barum@users.noreply.github.com> --- .github/workflows/php.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 21ea2503..bb6bd5a7 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -64,6 +64,22 @@ jobs: composer global require php-coveralls/php-coveralls php-coveralls --coverage_clover=./build/logs/clover.xml -v + latest_dependency_tests: + name: Latest Dependency Tests + needs: [ linting ] + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + - name: Install latest supported dependencies + run: composer update justinrainbow/json-schema lastguest/murmurhash --with-dependencies + - name: Run tests + run: ./vendor/bin/phpunit + integration_tests: name: Integration Tests needs: [ unit_tests ] From aa88f6b6061310917717a5e708ce8fa6507b2524 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Oct 2026 18:37:38 +0000 Subject: [PATCH 05/10] Limit permissions for dependency CI job Co-authored-by: Tamara-Barum <88795935+Tamara-Barum@users.noreply.github.com> --- .github/workflows/php.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index bb6bd5a7..fd083fb6 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -68,6 +68,8 @@ jobs: name: Latest Dependency Tests needs: [ linting ] runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout code uses: actions/checkout@v3 From f24ac218b4f412e9b56834cca5fb09bea76442e7 Mon Sep 17 00:00:00 2001 From: Tamara Date: Mon, 12 Oct 2026 14:18:40 -0500 Subject: [PATCH 06/10] [FSSDK-13266] Address PR review feedback - Fix Validator.php comment to accurately describe json-schema version history (validate() added in v5, check() deprecated in v6) - De-duplicate bitmask operation in Bucketer.php - Change murmurhash constraint from ^2.0 to ^2.1 (2.0.0 requires PHP 7) - Regenerate composer.lock to match updated constraints - Remove premature CHANGELOG 4.0.4 entry (belongs in release-prep PR) - Add CI job to test with latest dependency versions (PHP 8.1 + 8.2) with version assertion to verify v6/v2 actually resolved - Add edge-case bucketing test keys (empty string, UTF-8) Co-Authored-By: Claude Opus 4.6 --- .github/workflows/php.yml | 28 ++++++++++++++++++++++------ CHANGELOG.md | 8 -------- composer.json | 2 +- composer.lock | 16 ++++++++-------- src/Optimizely/Bucketer.php | 8 ++++---- src/Optimizely/Utils/Validator.php | 3 ++- tests/BucketerTest.php | 9 +++++++++ 7 files changed, 46 insertions(+), 28 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index fd083fb6..2e56915e 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -65,22 +65,38 @@ jobs: php-coveralls --coverage_clover=./build/logs/clover.xml -v latest_dependency_tests: - name: Latest Dependency Tests + name: Latest Deps (PHP ${{ matrix.php-versions }}) needs: [ linting ] runs-on: ubuntu-latest - permissions: - contents: read + strategy: + fail-fast: false + matrix: + php-versions: [ '8.1', '8.2' ] steps: - name: Checkout code uses: actions/checkout@v3 - - name: Set up PHP + - name: Set up PHP v${{ matrix.php-versions }} uses: shivammathur/setup-php@v2 with: - php-version: '8.2' + php-version: ${{ matrix.php-versions }} + - name: Install dependencies + run: composer install - name: Install latest supported dependencies run: composer update justinrainbow/json-schema lastguest/murmurhash --with-dependencies + - name: Verify latest majors resolved + run: | + composer show justinrainbow/json-schema lastguest/murmurhash + php -r ' + require "vendor/autoload.php"; + $jsonSchema = Composer\InstalledVersions::getVersion("justinrainbow/json-schema"); + $murmur = Composer\InstalledVersions::getVersion("lastguest/murmurhash"); + echo "json-schema: $jsonSchema\nmurmurhash: $murmur\n"; + exit((version_compare($jsonSchema, "6.0.0", ">=") && version_compare($murmur, "2.0.0", ">=")) ? 0 : 1); + ' - name: Run tests - run: ./vendor/bin/phpunit + run: | + mkdir -p ./build/logs + ./vendor/bin/phpunit integration_tests: name: Integration Tests diff --git a/CHANGELOG.md b/CHANGELOG.md index b72f098b..4377558c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,5 @@ # Optimizely PHP SDK Changelog -## 4.0.4 -October 12, 2026 - -* Update: Allow `justinrainbow/json-schema` v6.x -* Update: Allow `lastguest/murmurhash` v2.x -* Fix: Add compatibility for murmurhash v2 API (global function replaced with static class method) -* Fix: Use `validate()` instead of deprecated `check()` for json-schema forward compatibility - ## 4.0.3 May 20, 2026 diff --git a/composer.json b/composer.json index 76df92f3..7789d037 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "php": ">=8.1", "guzzlehttp/guzzle": ">=6.2", "justinrainbow/json-schema": "^1.6 || ^2.0 || ^4.0 || ^5.0 || ^6.0", - "lastguest/murmurhash": "^1.3.0 || ^2.0", + "lastguest/murmurhash": "^1.3.0 || ^2.1", "monolog/monolog": ">=1.21" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 50ece972..1b2c5812 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": "82b1237943c87584a7fd69a882570e14", + "content-hash": "99b7de4d0fca1025e6148d0d08fd66fc", "packages": [ { "name": "guzzlehttp/guzzle", @@ -336,12 +336,12 @@ "version": "5.2.12", "source": { "type": "git", - "url": "https://github.com/justinrainbow/json-schema.git", + "url": "https://github.com/jsonrainbow/json-schema.git", "reference": "ad87d5a5ca981228e0e205c2bc7dfb8e24559b60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/ad87d5a5ca981228e0e205c2bc7dfb8e24559b60", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/ad87d5a5ca981228e0e205c2bc7dfb8e24559b60", "reference": "ad87d5a5ca981228e0e205c2bc7dfb8e24559b60", "shasum": "" }, @@ -2808,12 +2808,12 @@ "version": "3.7.0", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", "reference": "a2cd51b45bcaef9c1f2a4bda48f2dd2fa2b95563" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/a2cd51b45bcaef9c1f2a4bda48f2dd2fa2b95563", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/a2cd51b45bcaef9c1f2a4bda48f2dd2fa2b95563", "reference": "a2cd51b45bcaef9c1f2a4bda48f2dd2fa2b95563", "shasum": "" }, @@ -3785,12 +3785,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=8.1" }, - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform-dev": {}, + "plugin-api-version": "2.9.0" } diff --git a/src/Optimizely/Bucketer.php b/src/Optimizely/Bucketer.php index a77c847c..908b083c 100644 --- a/src/Optimizely/Bucketer.php +++ b/src/Optimizely/Bucketer.php @@ -73,10 +73,10 @@ public function __construct(LoggerInterface $logger) private function generateHashCode($bucketingKey) { // murmurhash v2 replaced the global function with a static class method - if (function_exists('murmurhash3_int')) { - return murmurhash3_int($bucketingKey, Bucketer::$HASH_SEED) & Bucketer::$UNSIGNED_MAX_32_BIT_VALUE; - } - return \lastguest\Murmur::hash3_int($bucketingKey, Bucketer::$HASH_SEED) & Bucketer::$UNSIGNED_MAX_32_BIT_VALUE; + $hash = function_exists('murmurhash3_int') + ? murmurhash3_int($bucketingKey, Bucketer::$HASH_SEED) + : \lastguest\Murmur::hash3_int($bucketingKey, Bucketer::$HASH_SEED); + return $hash & Bucketer::$UNSIGNED_MAX_32_BIT_VALUE; } /** diff --git a/src/Optimizely/Utils/Validator.php b/src/Optimizely/Utils/Validator.php index 419ca695..7c3d65db 100644 --- a/src/Optimizely/Utils/Validator.php +++ b/src/Optimizely/Utils/Validator.php @@ -37,7 +37,8 @@ public static function validateJsonSchema($datafile, ?LoggerInterface $logger = // Validate $validator = new JsonSchema\Validator; - // validate() replaces check() in newer json-schema versions + // json-schema added validate() in v5; before that only check() exists, + // and check() is a deprecated alias in v6+. Prefer validate() when available. if (method_exists($validator, 'validate')) { $validator->validate($data, (object)['$ref' => 'file://' . __DIR__.'/schema.json']); } else { diff --git a/tests/BucketerTest.php b/tests/BucketerTest.php index 4cbcf8a4..6125d5aa 100644 --- a/tests/BucketerTest.php +++ b/tests/BucketerTest.php @@ -88,6 +88,15 @@ public function testGenerateBucketValue() ) ) ); + // Edge cases: empty string and multibyte UTF-8 + $this->assertSame( + 3175, + $generateBucketValueMethod->invoke(new Bucketer($this->loggerMock), '') + ); + $this->assertSame( + 8308, + $generateBucketValueMethod->invoke(new Bucketer($this->loggerMock), '日本語テスト1886780721') + ); } public function testBucketValidExperimentNotInGroup() From 8cf9279f4d38a18323a00d7ca353420a7a46ab14 Mon Sep 17 00:00:00 2001 From: Tamara Date: Tue, 13 Oct 2026 09:11:24 -0500 Subject: [PATCH 07/10] [FSSDK-13266] Fix: Split composer show into separate commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit composer show does not accept multiple package names as positional arguments — the second name was parsed as a version constraint. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/php.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 2e56915e..d96b478a 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -85,7 +85,8 @@ jobs: run: composer update justinrainbow/json-schema lastguest/murmurhash --with-dependencies - name: Verify latest majors resolved run: | - composer show justinrainbow/json-schema lastguest/murmurhash + composer show justinrainbow/json-schema + composer show lastguest/murmurhash php -r ' require "vendor/autoload.php"; $jsonSchema = Composer\InstalledVersions::getVersion("justinrainbow/json-schema"); From 5e69a1ad48a917dcd86f7b743bec236ce47514f4 Mon Sep 17 00:00:00 2001 From: Tamara Date: Tue, 13 Oct 2026 09:31:46 -0500 Subject: [PATCH 08/10] [FSSDK-13266] Address alexjoeyyong review: simplify Validator and CI job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Revert Validator.php to use check() directly — it works in all allowed versions (1.6 through 6.x) and the v6 deprecation is docblock-only - Remove redundant composer install step from latest-deps CI job - Remove redundant composer show lines — the php -r gate already echoes and asserts the resolved versions Co-Authored-By: Claude Opus 4.6 --- .github/workflows/php.yml | 4 ---- src/Optimizely/Utils/Validator.php | 8 +------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index d96b478a..3d4bd29e 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -79,14 +79,10 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} - - name: Install dependencies - run: composer install - name: Install latest supported dependencies run: composer update justinrainbow/json-schema lastguest/murmurhash --with-dependencies - name: Verify latest majors resolved run: | - composer show justinrainbow/json-schema - composer show lastguest/murmurhash php -r ' require "vendor/autoload.php"; $jsonSchema = Composer\InstalledVersions::getVersion("justinrainbow/json-schema"); diff --git a/src/Optimizely/Utils/Validator.php b/src/Optimizely/Utils/Validator.php index 7c3d65db..803bc25b 100644 --- a/src/Optimizely/Utils/Validator.php +++ b/src/Optimizely/Utils/Validator.php @@ -37,13 +37,7 @@ public static function validateJsonSchema($datafile, ?LoggerInterface $logger = // Validate $validator = new JsonSchema\Validator; - // json-schema added validate() in v5; before that only check() exists, - // and check() is a deprecated alias in v6+. Prefer validate() when available. - if (method_exists($validator, 'validate')) { - $validator->validate($data, (object)['$ref' => 'file://' . __DIR__.'/schema.json']); - } else { - $validator->check($data, (object)['$ref' => 'file://' . __DIR__.'/schema.json']); - } + $validator->check($data, (object)['$ref' => 'file://' . __DIR__.'/schema.json']); if ($validator->isValid()) { return true; From 91f3eea3b90aa8d86009eccf7fa2abe9ececfe20 Mon Sep 17 00:00:00 2001 From: Tamara Date: Wed, 14 Oct 2026 15:49:30 -0500 Subject: [PATCH 09/10] [FSSDK-13266] Add 4.0.4 CHANGELOG entry and tighten CI murmurhash gate Re-add the user-facing CHANGELOG entry and align the CI version check with the ^2.1 murmurhash constraint. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/php.yml | 2 +- CHANGELOG.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 3d4bd29e..a2bcd4fe 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -88,7 +88,7 @@ jobs: $jsonSchema = Composer\InstalledVersions::getVersion("justinrainbow/json-schema"); $murmur = Composer\InstalledVersions::getVersion("lastguest/murmurhash"); echo "json-schema: $jsonSchema\nmurmurhash: $murmur\n"; - exit((version_compare($jsonSchema, "6.0.0", ">=") && version_compare($murmur, "2.0.0", ">=")) ? 0 : 1); + exit((version_compare($jsonSchema, "6.0.0", ">=") && version_compare($murmur, "2.1.0", ">=")) ? 0 : 1); ' - name: Run tests run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 4377558c..3b986241 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Optimizely PHP SDK Changelog +## 4.0.4 +October 14, 2026 + +* Update: Allow `justinrainbow/json-schema` v6.x and `lastguest/murmurhash` v2.x #298 + ## 4.0.3 May 20, 2026 From edda32b2a5ccc50ff4b297888561575bb6f8d787 Mon Sep 17 00:00:00 2001 From: Tamara Date: Thu, 15 Oct 2026 08:27:11 -0500 Subject: [PATCH 10/10] [FSSDK-13266] Remove 4.0.4 CHANGELOG entry The release entry belongs in the separate release-prep PR alongside the SDK_VERSION bump. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b986241..4377558c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,5 @@ # Optimizely PHP SDK Changelog -## 4.0.4 -October 14, 2026 - -* Update: Allow `justinrainbow/json-schema` v6.x and `lastguest/murmurhash` v2.x #298 - ## 4.0.3 May 20, 2026