diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bca73ce..bc13c7a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,7 +18,7 @@ jobs: - name: Install Composer uses: php-actions/composer@v6 with: - php_version: 8.2 + php_version: 8.4 php_extensions: mbstring xdebug - name: PHPUnit Tests diff --git a/composer.lock b/composer.lock index 9cde051..e195565 100644 --- a/composer.lock +++ b/composer.lock @@ -298,16 +298,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "12.5.5", + "version": "12.5.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "a25bde1f8f83849f441ef5713c6466e470872a71" + "reference": "876099a072646c7745f673d7aeab5382c4439691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/a25bde1f8f83849f441ef5713c6466e470872a71", - "reference": "a25bde1f8f83849f441ef5713c6466e470872a71", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/876099a072646c7745f673d7aeab5382c4439691", + "reference": "876099a072646c7745f673d7aeab5382c4439691", "shasum": "" }, "require": { @@ -362,7 +362,7 @@ "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/12.5.5" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.6" }, "funding": [ { @@ -382,7 +382,7 @@ "type": "tidelift" } ], - "time": "2026-04-13T04:53:32+00:00" + "time": "2026-04-15T08:23:17+00:00" }, { "name": "phpunit/php-file-iterator", @@ -643,16 +643,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.5.19", + "version": "12.5.23", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "92f7744ca5f5701c9e4b4a60d9e143f2d84956da" + "reference": "c54fcf3d6bcb6e96ac2f7e40097dc37b5f139969" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/92f7744ca5f5701c9e4b4a60d9e143f2d84956da", - "reference": "92f7744ca5f5701c9e4b4a60d9e143f2d84956da", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c54fcf3d6bcb6e96ac2f7e40097dc37b5f139969", + "reference": "c54fcf3d6bcb6e96ac2f7e40097dc37b5f139969", "shasum": "" }, "require": { @@ -666,15 +666,15 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.3", - "phpunit/php-code-coverage": "^12.5.5", + "phpunit/php-code-coverage": "^12.5.6", "phpunit/php-file-iterator": "^6.0.1", "phpunit/php-invoker": "^6.0.0", "phpunit/php-text-template": "^5.0.0", "phpunit/php-timer": "^8.0.0", "sebastian/cli-parser": "^4.2.0", - "sebastian/comparator": "^7.1.5", + "sebastian/comparator": "^7.1.6", "sebastian/diff": "^7.0.0", - "sebastian/environment": "^8.0.4", + "sebastian/environment": "^8.1.0", "sebastian/exporter": "^7.0.2", "sebastian/global-state": "^8.0.2", "sebastian/object-enumerator": "^7.0.0", @@ -721,7 +721,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.19" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.23" }, "funding": [ { @@ -729,7 +729,7 @@ "type": "other" } ], - "time": "2026-04-13T05:38:19+00:00" + "time": "2026-04-18T06:12:49+00:00" }, { "name": "sebastian/cli-parser", @@ -1019,16 +1019,16 @@ }, { "name": "sebastian/environment", - "version": "8.0.4", + "version": "8.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "7b8842c2d8e85d0c3a5831236bf5869af6ab2a11" + "reference": "b121608b28a13f721e76ffbbd386d08eff58f3f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/7b8842c2d8e85d0c3a5831236bf5869af6ab2a11", - "reference": "7b8842c2d8e85d0c3a5831236bf5869af6ab2a11", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/b121608b28a13f721e76ffbbd386d08eff58f3f6", + "reference": "b121608b28a13f721e76ffbbd386d08eff58f3f6", "shasum": "" }, "require": { @@ -1043,7 +1043,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-main": "8.1-dev" } }, "autoload": { @@ -1071,7 +1071,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/8.0.4" + "source": "https://github.com/sebastianbergmann/environment/tree/8.1.0" }, "funding": [ { @@ -1091,7 +1091,7 @@ "type": "tidelift" } ], - "time": "2026-03-15T07:05:40+00:00" + "time": "2026-04-15T12:13:01+00:00" }, { "name": "sebastian/exporter", diff --git a/src/agentzero.php b/src/agentzero.php index 9b04fc0..320f5a5 100644 --- a/src/agentzero.php +++ b/src/agentzero.php @@ -89,13 +89,13 @@ private function __construct(string $ua, \stdClass $data) { // platform $this->kernel = $data->kernel ?? null; $this->platform = $data->platform ?? null; - $this->platformversion = $data->platformversion ?? null; + $this->platformversion = !empty($data->platformversion) ? \strval($data->platformversion) : null; // browser $this->engine = $data->engine ?? null; - $this->engineversion = $data->engineversion ?? null; + $this->engineversion = !empty($data->engineversion) ? \strval($data->engineversion) : null; $this->browser = $data->browser ?? null; - $this->browserversion = $data->browserversion ?? null; + $this->browserversion = !empty($data->browserversion) ? \strval($data->browserversion) : null; $this->browserstatus = $data->browserstatus ?? null; $this->browserreleased = !empty($data->browserreleased) ? $data->browserreleased : null; $this->browserlatest = $data->browserlatest ?? null; @@ -104,9 +104,9 @@ private function __construct(string $ua, \stdClass $data) { // app $this->app = $data->app ?? null; $this->appname = $data->appname ?? null; - $this->appversion = $data->appversion ?? null; + $this->appversion = !empty($data->appversion) ? \strval($data->appversion) : null; $this->framework = $data->framework ?? null; - $this->frameworkversion = $data->frameworkversion ?? null; + $this->frameworkversion = !empty($data->frameworkversion) ? \strval($data->frameworkversion) : null; $this->url = $data->url ?? null; // network @@ -251,7 +251,7 @@ public static function parse(string $ua, array $hints = [], array $config = []) // lowercase the tokens $tokenslower = []; foreach ($tokens AS $key => $item) { - $tokenslower[$key] = $item; + $tokenslower[$key] = \mb_strtolower($item); } // extract UA info diff --git a/src/helpers/versions.php b/src/helpers/versions.php index 8ec4b62..f9c1bad 100644 --- a/src/helpers/versions.php +++ b/src/helpers/versions.php @@ -97,6 +97,27 @@ protected static function released(array $data, string $version) : ?string { return !empty($released) ? (new \DateTime(\strval($released)))->format('Y-m-d') : null; } + protected static function legacy(array $browsers, string $version) : bool { + $earliest = \strval(\array_key_last($browsers)); + + // check if we have a version in range + $parts = \explode('.', $version); + foreach (\explode('.', $earliest) AS $key => $item) { + if (isset($parts[$key])) { + + // older than earlier version we have a date for + if ($item > $parts[$key]) { + return true; + + // newer than the earlier version we have a date for + } elseif ($item < $parts[$key]) { + return false; + } + } + } + return false; + } + public static function get(string $browser, string $version, array $config) : array { $source = $config['versionssource']; $cache = $config['versionscache']; @@ -110,10 +131,13 @@ public static function get(string $browser, string $version, array $config) : ar // check if version is greater than latest version $major = \intval($version); $latest = \intval($data['browserlatest']); - $first = \intval(\array_key_last($versions[$browser])); + + // check if we have a version in range + if (self::legacy($versions[$browser], $version)) { + $data['browserstatus'] = 'legacy'; // version is way out of bounds (This happens sometimes, for example if the safari engine version is reported instead of the browser version) - if ($latest + 3 < $major) { + } elseif ($latest + 3 < $major) { return []; // nightly build? @@ -128,10 +152,6 @@ public static function get(string $browser, string $version, array $config) : ar } elseif ($latest + 1 === $major) { $data['browserstatus'] = 'beta'; - // so old we don't have data for it - } elseif ($major < $first) { - $data['browserstatus'] = 'legacy'; - // find closes match for version } else { diff --git a/tests/browsersTest.php b/tests/browsersTest.php index 3090ca6..14ed003 100644 --- a/tests/browsersTest.php +++ b/tests/browsersTest.php @@ -499,8 +499,7 @@ public function testBrave() : void { 'engine' => 'WebKit', 'engineversion' => '601.1.46', 'browser' => 'Brave', - 'browserversion' => '1.2.11', - 'browserreleased' => '2026-04-08' + 'browserversion' => '1.2.11' ], 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Brave/115.0.0.0 Safari/605.1.15' => [ 'string' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Brave/115.0.0.0 Safari/605.1.15', @@ -660,8 +659,7 @@ public function testKonqueror() : void { 'platform' => 'Kubuntu', 'browser' => 'Konqueror', 'browserversion' => '3.5', - 'language' => 'en-US', - 'browserreleased' => '2007-12-04' + 'language' => 'en-US' ], 'Mozilla/5.0 (compatible; Konqueror/3.1; i686 Linux; 20021102)' => [ 'string' => 'Mozilla/5.0 (compatible; Konqueror/3.1; i686 Linux; 20021102)', @@ -672,8 +670,7 @@ public function testKonqueror() : void { 'architecture' => 'x86', 'bits' => 32, 'browser' => 'Konqueror', - 'browserversion' => '3.1', - 'browserreleased' => '2007-12-04' + 'browserversion' => '3.1' ] ]; foreach ($strings AS $ua => $item) { @@ -1573,6 +1570,7 @@ public function testSilk() : void { 'bits' => 64, 'browser' => 'Silk', 'browserversion' => '148.0.5259.39', + 'browserreleased' => '2026-04-23', 'engine' => 'Blink', 'engineversion' => '148.0.5259.39' ] diff --git a/tests/clientHintsTest.php b/tests/clientHintsTest.php index fc992d7..276e299 100644 --- a/tests/clientHintsTest.php +++ b/tests/clientHintsTest.php @@ -24,7 +24,7 @@ public function testClientHints() : void { 'bits' => 64, 'kernel' => 'Windows NT', 'platform' => 'Windows', - 'platformversion' => '19.0.0', + 'platformversion' => '11', 'engine' => 'Blink', 'engineversion' => '133.0.6943.142', 'browser' => 'Chrome',