1<?php 2 3/** 4 * Device Detector - The Universal Device Detection library for parsing User Agents 5 * 6 * @link https://matomo.org 7 * 8 * @license http://www.gnu.org/licenses/lgpl.html LGPL v3 or later 9 */ 10 11declare(strict_types=1); 12 13namespace DeviceDetector\Parser\Client\Browser\Engine; 14 15use DeviceDetector\Parser\Client\AbstractClientParser; 16 17/** 18 * Class Version 19 * 20 * Client parser for browser engine version detection 21 */ 22class Version extends AbstractClientParser 23{ 24 /** 25 * @var string 26 */ 27 private $engine; 28 29 /** 30 * Version constructor. 31 * 32 * @param string $ua 33 * @param string $engine 34 */ 35 public function __construct(string $ua, string $engine) 36 { 37 parent::__construct($ua); 38 39 $this->engine = $engine; 40 } 41 42 /** 43 * @inheritdoc 44 */ 45 public function parse(): ?array 46 { 47 if (empty($this->engine)) { 48 return null; 49 } 50 51 if ('Gecko' === $this->engine || 'Clecko' === $this->engine) { 52 $pattern = '~[ ](?:rv[: ]([0-9.]+)).*(?:g|cl)ecko/[0-9]{8,10}~i'; 53 54 if (\preg_match($pattern, $this->userAgent, $matches)) { 55 return ['version' => \array_pop($matches)]; 56 } 57 } 58 59 $engineToken = $this->engine; 60 61 if ('Blink' === $this->engine) { 62 $engineToken = 'Chr[o0]me|Chromium|Cronet'; 63 } 64 65 if ('Arachne' === $this->engine) { 66 $engineToken = 'Arachne\/5\.'; 67 } 68 69 if ('LibWeb' === $this->engine) { 70 $engineToken = 'LibWeb\+LibJs'; 71 } 72 73 \preg_match( 74 "~(?:{$engineToken})\s*[/_]?\s*((?(?=\d+\.\d)\d+[.\d]*|\d{1,7}(?=(?:\D|$))))~i", 75 $this->userAgent, 76 $matches 77 ); 78 79 if (!$matches) { 80 return null; 81 } 82 83 return ['version' => \array_pop($matches)]; 84 } 85} 86