/** * Gets the browser data formatr for the given user agent * (or null if no data avaailble, no even the default browser) * * @param string $userAgent * @return FormatterInterface|null */ public function getBrowser($userAgent) { $userAgent = strtolower($userAgent); $formatter = null; foreach ($this->patternHelper->getPatterns($userAgent) as $patterns) { $patternToMatch = '/^(?:' . str_replace("\t", ')|(?:', $patterns) . ')$/i'; if (!preg_match($patternToMatch, $userAgent)) { continue; } // strtok() requires less memory than explode() $pattern = strtok($patterns, "\t"); while ($pattern !== false) { $pattern = str_replace('[\\d]', '(\\d)', $pattern); $quotedPattern = '/^' . $pattern . '$/i'; $matches = []; if (preg_match($quotedPattern, $userAgent, $matches)) { // Insert the digits back into the pattern, so that we can search the settings for it if (count($matches) > 1) { array_shift($matches); foreach ($matches as $oneMatch) { $numPos = strpos($pattern, '(\\d)'); $pattern = substr_replace($pattern, $oneMatch, $numPos, 4); } } // Try to get settings - as digits have been replaced to speed up the pattern search (up to 90 faster), // we won't always find the data in the first step - so check if settings have been found and if not, // search for the next pattern. $settings = $this->dataHelper->getSettings($pattern); if (count($settings) > 0) { $formatter = $this->formatter; $formatter->setData($settings); break 2; } } $pattern = strtok("\t"); } } return $formatter; }