Skip to content

Commit 49ca643

Browse files
committed
fix Android tablet detection in VERSION_TRUNCATION_MAJOR mode
1 parent cc4eb16 commit 49ca643

File tree

6 files changed

+84
-14
lines changed

6 files changed

+84
-14
lines changed

DeviceDetector.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -980,10 +980,10 @@ protected function parseDevice(): void
980980
* Devices running Android 3.X are tablets. Device type of Android 2.X and 4.X+ are unknown
981981
*/
982982
if (null === $this->device && 'Android' === $osName && '' !== $osVersion) {
983-
if (-1 === \version_compare($osVersion, '2.0')) {
983+
if (-1 === \version_compare($osVersion, '2')) {
984984
$this->device = AbstractDeviceParser::DEVICE_TYPE_SMARTPHONE;
985-
} elseif (\version_compare($osVersion, '3.0') >= 0
986-
&& -1 === \version_compare($osVersion, '4.0')
985+
} elseif (\version_compare($osVersion, '3') >= 0
986+
&& -1 === \version_compare($osVersion, '4')
987987
) {
988988
$this->device = AbstractDeviceParser::DEVICE_TYPE_TABLET;
989989
}

Parser/AbstractParser.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,18 @@ protected function buildVersion(string $versionString, array $matches): string
356356
$versionString = $this->buildByMatch($versionString, $matches);
357357
$versionString = \str_replace('_', '.', $versionString);
358358

359+
return \trim($versionString, ' .');
360+
}
361+
362+
/**
363+
* Truncate the version based on the current truncation rule
364+
*
365+
* @param string $versionString
366+
*
367+
* @return string
368+
*/
369+
protected function truncateVersion(string $versionString): string
370+
{
359371
if (self::VERSION_TRUNCATION_NONE !== static::$maxMinorParts
360372
&& \substr_count($versionString, '.') > static::$maxMinorParts
361373
) {

Parser/Client/AbstractClientParser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public function parse(): ?array
5353
$result = [
5454
'type' => $this->parserName,
5555
'name' => $this->buildByMatch($regex['name'], $matches),
56-
'version' => $this->buildVersion((string) $regex['version'], $matches),
56+
'version' => $this->truncateVersion($this->buildVersion((string) $regex['version'], $matches)),
5757
];
5858

5959
break;

Parser/Client/Browser.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ protected function parseBrowserFromClientHints(): array
917917
return [
918918
'name' => $name,
919919
'short_name' => $short,
920-
'version' => $this->buildVersion($version, []),
920+
'version' => $this->truncateVersion($this->buildVersion($version, [])),
921921
];
922922
}
923923

@@ -952,8 +952,9 @@ protected function parseBrowserFromUserAgent(): array
952952
$browserShort = self::getBrowserShortName($name);
953953

954954
if (null !== $browserShort) {
955-
$version = $this->buildVersion((string) $regex['version'], $matches);
956-
$engine = $this->buildEngine($regex['engine'] ?? [], $version);
955+
$fullVersion = $this->buildVersion((string) $regex['version'], $matches);
956+
$version = $this->truncateVersion($fullVersion);
957+
$engine = $this->buildEngine($regex['engine'] ?? [], $fullVersion);
957958
$engineVersion = $this->buildEngineVersion($engine);
958959

959960
return [

Parser/OperatingSystem.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ protected function parseOsFromClientHints(): array
450450
return [
451451
'name' => $name,
452452
'short_name' => $short,
453-
'version' => $this->buildVersion($version, []),
453+
'version' => $this->truncateVersion($this->buildVersion($version, [])),
454454
];
455455
}
456456

@@ -479,7 +479,7 @@ protected function parseOsFromUserAgent(): array
479479
['name' => $name, 'short' => $short] = self::getShortOsData($name);
480480

481481
$version = \array_key_exists('version', $osRegex)
482-
? $this->buildVersion((string) $osRegex['version'], $matches)
482+
? $this->truncateVersion($this->buildVersion((string) $osRegex['version'], $matches))
483483
: '';
484484

485485
foreach ($osRegex['versions'] ?? [] as $regex) {
@@ -495,7 +495,7 @@ protected function parseOsFromUserAgent(): array
495495
}
496496

497497
if (\array_key_exists('version', $regex)) {
498-
$version = $this->buildVersion((string) $regex['version'], $matches);
498+
$version = $this->truncateVersion($this->buildVersion((string) $regex['version'], $matches));
499499
}
500500

501501
break;

Tests/DeviceDetectorTest.php

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ public function testParse(array $fixtureData): void
230230
}
231231

232232
$errorMessage = \sprintf(
233-
"UserAgent: %s\nHeaders: %s",
233+
"UserAgent: %s\nHeaders: %s\nVersion truncation: none",
234234
$ua,
235235
\print_r($fixtureData['headers'] ?? null, true)
236236
);
@@ -240,6 +240,48 @@ public function testParse(array $fixtureData): void
240240
$this->assertEquals($fixtureData, $uaInfo, $errorMessage);
241241
}
242242

243+
/**
244+
* @dataProvider getFixtures
245+
*/
246+
public function testParseWithVersionTruncationMajor(array $fixtureData): void
247+
{
248+
$ua = $fixtureData['user_agent'];
249+
$clientHints = !empty($fixtureData['headers']) ? ClientHints::factory($fixtureData['headers']) : null;
250+
251+
AbstractDeviceParser::setVersionTruncation(AbstractDeviceParser::VERSION_TRUNCATION_MAJOR);
252+
253+
try {
254+
$uaInfo = DeviceDetector::getInfoFromUserAgent($ua, $clientHints);
255+
} catch (\Exception $exception) {
256+
throw new \Exception(
257+
\sprintf('Error: %s from useragent %s', $exception->getMessage(), $ua),
258+
$exception->getCode(),
259+
$exception
260+
);
261+
}
262+
263+
$errorMessage = \sprintf(
264+
"UserAgent: %s\nHeaders: %s\nVersion truncation: major",
265+
$ua,
266+
\print_r($fixtureData['headers'] ?? null, true)
267+
);
268+
269+
unset($fixtureData['headers']); // ignore headers in result
270+
271+
// truncate versions
272+
if (\array_key_exists('version', $fixtureData['os'] ?? [])) {
273+
$fixtureData['os']['version'] = self::truncateVersion($fixtureData['os']['version']);
274+
}
275+
276+
if (\array_key_exists('version', $fixtureData['client'] ?? [])) {
277+
$fixtureData['client']['version'] = self::truncateVersion($fixtureData['client']['version']);
278+
}
279+
280+
$this->assertEquals($fixtureData, $uaInfo, $errorMessage);
281+
282+
AbstractDeviceParser::setVersionTruncation(AbstractDeviceParser::VERSION_TRUNCATION_NONE);
283+
}
284+
243285
public function getFixtures(): array
244286
{
245287
$fixtures = [];
@@ -613,7 +655,7 @@ public function testSetYamlParserInvalid(): void
613655
public function testSetYamlParser(): void
614656
{
615657
$reader = function & ($object, $property) {
616-
$value = & Closure::bind(function & () use ($property) {
658+
$value = &Closure::bind(function & () use ($property) {
617659
return $this->$property;
618660
}, $object, $object)->__invoke();
619661

@@ -630,15 +672,15 @@ public function testSetYamlParser(): void
630672

631673
foreach ($dd->getClientParsers() as $parser) {
632674
if ($parser instanceof MobileApp) {
633-
$appHints = & $reader($parser, 'appHints');
675+
$appHints = &$reader($parser, 'appHints');
634676
$this->assertInstanceOf(Symfony::class, $appHints->getYamlParser());
635677
}
636678

637679
if (!($parser instanceof Browser)) {
638680
continue;
639681
}
640682

641-
$browserHints = & $reader($parser, 'browserHints');
683+
$browserHints = &$reader($parser, 'browserHints');
642684
$this->assertInstanceOf(Symfony::class, $browserHints->getYamlParser());
643685
}
644686
}
@@ -741,4 +783,19 @@ private function getDeviceDetector(): DeviceDetector
741783

742784
return $dd;
743785
}
786+
787+
private static function truncateVersion(?string $versionString): ?string
788+
{
789+
if (null === $versionString) {
790+
return null;
791+
}
792+
793+
if (\substr_count($versionString, '.') > 0) {
794+
$versionParts = \explode('.', $versionString);
795+
$versionParts = \array_slice($versionParts, 0, 1);
796+
$versionString = \implode('.', $versionParts);
797+
}
798+
799+
return \trim($versionString, ' .');
800+
}
744801
}

0 commit comments

Comments
 (0)