setUserAgent($ua); } /** * Set how DeviceDetector should return versions * @param int|null $type Any of the VERSION_TRUNCATION_* constants */ public static function setVersionTruncation($type) { if (in_array($type, array(self::VERSION_TRUNCATION_BUILD, self::VERSION_TRUNCATION_NONE, self::VERSION_TRUNCATION_MAJOR, self::VERSION_TRUNCATION_MINOR, self::VERSION_TRUNCATION_PATCH))) { self::$maxMinorParts = $type; } } /** * Sets the user agent to parse * * @param string $ua user agent */ public function setUserAgent($ua) { $this->userAgent = $ua; } /** * Returns the internal name of the parser * * @return string */ public function getName() { return $this->parserName; } /** * Returns the result of the parsed yml file defined in $fixtureFile * * @return array */ protected function getRegexes() { if (empty($this->regexList)) { $cacheKey = 'DeviceDetector-'.DeviceDetector::VERSION.'regexes-'.$this->getName(); $cacheKey = preg_replace('/([^a-z0-9_-]+)/i', '', $cacheKey); $this->regexList = $this->getCache()->fetch($cacheKey); if (empty($this->regexList)) { $this->regexList = Spyc::YAMLLoad(dirname(__DIR__).DIRECTORY_SEPARATOR.$this->fixtureFile); $this->getCache()->save($cacheKey, $this->regexList); } } return $this->regexList; } /** * Matches the useragent against the given regex * * @param $regex * @return array|bool */ protected function matchUserAgent($regex) { // only match if useragent begins with given regex or there is no letter before it $regex = '/(?:^|[^A-Z0-9\_\-]|sprd-)(?:' . str_replace('/', '\/', $regex) . ')/i'; if (preg_match($regex, $this->userAgent, $matches)) { return $matches; } return false; } /** * @param string $item * @param array $matches * @return string type */ protected function buildByMatch($item, $matches) { for ($nb=1;$nb<=3;$nb++) { if (strpos($item, '$' . $nb) === false) { continue; } $replace = isset($matches[$nb]) ? $matches[$nb] : ''; $item = trim(str_replace('$' . $nb, $replace, $item)); } return $item; } /** * Builds the version with the given $versionString and $matches * * Example: * $versionString = 'v$2' * $matches = array('version_1_0_1', '1_0_1') * return value would be v1.0.1 * * @param $versionString * @param $matches * @return mixed|string */ protected function buildVersion($versionString, $matches) { $versionString = $this->buildByMatch($versionString, $matches); $versionString = str_replace('_', '.', $versionString); if (null !== self::$maxMinorParts && substr_count($versionString, '.') > self::$maxMinorParts) { $versionParts = explode('.', $versionString); $versionParts = array_slice($versionParts, 0, 1+self::$maxMinorParts); $versionString = implode('.', $versionParts); } return trim($versionString, ' .'); } /** * Tests the useragent against a combination of all regexes * * All regexes returned by getRegexes() will be reversed and concated with '|' * Afterwards the big regex will be tested against the user agent * * Method can be used to speed up detections by making a big check before doing checks for every single regex * * @return bool */ protected function preMatchOverall() { $regexes = $this->getRegexes(); static $overAllMatch; $cacheKey = $this->parserName.DeviceDetector::VERSION.'-all'; $cacheKey = preg_replace('/([^a-z0-9_-]+)/i', '', $cacheKey); if (empty($overAllMatch)) { $overAllMatch = $this->getCache()->fetch($cacheKey); } if (empty($overAllMatch)) { // reverse all regexes, so we have the generic one first, which already matches most patterns $overAllMatch = array_reduce(array_reverse($regexes), function ($val1, $val2) { if (!empty($val1)) { return $val1.'|'.$val2['regex']; } else { return $val2['regex']; } }); $this->getCache()->save($cacheKey, $overAllMatch); } return $this->matchUserAgent($overAllMatch); } /** * Sets the Cache class * * @param Cache|\Doctrine\Common\Cache\CacheProvider $cache * @throws \Exception */ public function setCache($cache) { if ($cache instanceof Cache || (class_exists('\Doctrine\Common\Cache\CacheProvider') && $cache instanceof \Doctrine\Common\Cache\CacheProvider)) { $this->cache = $cache; return; } throw new \Exception('Cache not supported'); } /** * Returns Cache object * * @return Cache|\Doctrine\Common\Cache\CacheProvider */ public function getCache() { if (!empty($this->cache)) { return $this->cache; } return new StaticCache(); } }