Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed the situation where the current local ini is newer than the distributed one + performance increase #71

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 99 additions & 95 deletions src/phpbrowscap/Browscap.php
Original file line number Diff line number Diff line change
Expand Up @@ -273,19 +273,21 @@ public function getBrowser($user_agent = null, $return_array = false)
$interval = 0;
}

$update_cache = true;

if (file_exists($cache_file) && file_exists($ini_file) && ($interval <= $this->updateInterval))
$update_ini = true;
$need_new_cache = !file_exists($cache_file); //< preformance reasons: only update cache on new ini file downloads or when not existing

if (!$need_new_cache && file_exists($ini_file) && ($interval <= $this->updateInterval))
{
if ($this->_loadCache($cache_file))
{
$update_cache = false;
$update_ini = false;
}
else $need_new_cache = true; //< if cache file couldn't load, force rewrite cache file
}

if ($update_cache) {
if ($update_ini || $need_new_cache) {
try {
$this->updateCache();
$this->updateCache($need_new_cache);
} catch (Exception $e) {
if (file_exists($ini_file)) {
// Adjust the filemtime to the $errorInterval
Expand Down Expand Up @@ -486,7 +488,7 @@ public function getStreamContextOptions()
*
* @return bool whether the file was correctly written to the disk
*/
public function updateCache()
public function updateCache($need_new_cache = false)
{
$ini_path = $this->cacheDir . $this->iniFilename;
$cache_path = $this->cacheDir . $this->cacheFilename;
Expand All @@ -498,107 +500,111 @@ public function updateCache()
$url = $this->remoteIniUrl;
}

$this->_getRemoteIniFile($url, $ini_path);
$downloadednewini = $this->_getRemoteIniFile($url, $ini_path);

if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
$browsers = parse_ini_file($ini_path, true, INI_SCANNER_RAW);
} else {
$browsers = parse_ini_file($ini_path, true);
}

$this->_source_version = $browsers[self::BROWSCAP_VERSION_KEY]['Version'];
unset($browsers[self::BROWSCAP_VERSION_KEY]);

unset($browsers['DefaultProperties']['RenderingEngine_Description']);
// if downloaded new remote ini file, or has need_new_cache flag or cache doesn't exist: rewrite cache
if ($downloadednewini || $need_new_cache || !file_exists($cache_path)) {
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
$browsers = parse_ini_file($ini_path, true, INI_SCANNER_RAW);
} else {
$browsers = parse_ini_file($ini_path, true);
}

$this->_source_version = $browsers[self::BROWSCAP_VERSION_KEY]['Version'];
unset($browsers[self::BROWSCAP_VERSION_KEY]);

unset($browsers['DefaultProperties']['RenderingEngine_Description']);

$this->_properties = array_keys($browsers['DefaultProperties']);

array_unshift(
$this->_properties,
'browser_name',
'browser_name_regex',
'browser_name_pattern',
'Parent'
);

$tmp_user_agents = array_keys($browsers);

$this->_properties = array_keys($browsers['DefaultProperties']);
array_unshift(
$this->_properties,
'browser_name',
'browser_name_regex',
'browser_name_pattern',
'Parent'
);
$tmp_user_agents = array_keys($browsers);

usort($tmp_user_agents, array($this, 'compareBcStrings'));
usort($tmp_user_agents, array($this, 'compareBcStrings'));

$user_agents_keys = array_flip($tmp_user_agents);
$properties_keys = array_flip($this->_properties);
$user_agents_keys = array_flip($tmp_user_agents);
$properties_keys = array_flip($this->_properties);

$tmp_patterns = array();
$tmp_patterns = array();

foreach ($tmp_user_agents as $i => $user_agent) {

if (empty($browsers[$user_agent]['Comment']) || strpos($user_agent, '*') !== false || strpos($user_agent, '?') !== false)
{
$pattern = $this->_pregQuote($user_agent);

$matches_count = preg_match_all('@\d@', $pattern, $matches);

if (!$matches_count) {
$tmp_patterns[$pattern] = $i;
} else {
$compressed_pattern = preg_replace('@\d@', '(\d)', $pattern);

if (!isset($tmp_patterns[$compressed_pattern])) {
$tmp_patterns[$compressed_pattern] = array('first' => $pattern);
foreach ($tmp_user_agents as $i => $user_agent) {

if (empty($browsers[$user_agent]['Comment']) || strpos($user_agent, '*') !== false || strpos($user_agent, '?') !== false)
{
$pattern = $this->_pregQuote($user_agent);

$matches_count = preg_match_all('@\d@', $pattern, $matches);

if (!$matches_count) {
$tmp_patterns[$pattern] = $i;
} else {
$compressed_pattern = preg_replace('@\d@', '(\d)', $pattern);

if (!isset($tmp_patterns[$compressed_pattern])) {
$tmp_patterns[$compressed_pattern] = array('first' => $pattern);
}

$tmp_patterns[$compressed_pattern][$i] = $matches[0];
}
}

$tmp_patterns[$compressed_pattern][$i] = $matches[0];
}
}

if (!empty($browsers[$user_agent]['Parent'])) {
$parent = $browsers[$user_agent]['Parent'];
$parent_key = $user_agents_keys[$parent];
$browsers[$user_agent]['Parent'] = $parent_key;
$this->_userAgents[$parent_key . '.0'] = $tmp_user_agents[$parent_key];
};

$browser = array();
foreach ($browsers[$user_agent] as $key => $value) {
if (!isset($properties_keys[$key]))
{
continue;
if (!empty($browsers[$user_agent]['Parent'])) {
$parent = $browsers[$user_agent]['Parent'];
$parent_key = $user_agents_keys[$parent];
$browsers[$user_agent]['Parent'] = $parent_key;
$this->_userAgents[$parent_key . '.0'] = $tmp_user_agents[$parent_key];
};

$browser = array();
foreach ($browsers[$user_agent] as $key => $value) {
if (!isset($properties_keys[$key]))
{
continue;
}

$key = $properties_keys[$key];
$browser[$key] = $value;
}

$key = $properties_keys[$key];
$browser[$key] = $value;
}


$this->_browsers[] = $browser;
}
$this->_browsers[] = $browser;
}

foreach ($tmp_patterns as $pattern => $pattern_data) {
if (is_int($pattern_data)) {
$this->_patterns[$pattern] = $pattern_data;
} elseif (2 == count($pattern_data)) {
end($pattern_data);
$this->_patterns[$pattern_data['first']] = key($pattern_data);
} else {
unset($pattern_data['first']);
foreach ($tmp_patterns as $pattern => $pattern_data) {
if (is_int($pattern_data)) {
$this->_patterns[$pattern] = $pattern_data;
} elseif (2 == count($pattern_data)) {
end($pattern_data);
$this->_patterns[$pattern_data['first']] = key($pattern_data);
} else {
unset($pattern_data['first']);

$pattern_data = $this->deduplicateCompressionPattern($pattern_data, $pattern);
$pattern_data = $this->deduplicateCompressionPattern($pattern_data, $pattern);

$this->_patterns[$pattern] = $pattern_data;
}
}

// Save the keys lowercased if needed
if ($this->lowercase) {
$this->_properties = array_map('strtolower', $this->_properties);
}
$this->_patterns[$pattern] = $pattern_data;
}
}
// Save the keys lowercased if needed
if ($this->lowercase) {
$this->_properties = array_map('strtolower', $this->_properties);
}

// Get the whole PHP code
$cache = $this->_buildCache();
// Get the whole PHP code
$cache = $this->_buildCache();

// Save and return
return (bool) file_put_contents($cache_path, $cache, LOCK_EX);
// Save and return
return (bool) file_put_contents($cache_path, $cache, LOCK_EX);
}
return false;
}

protected function compareBcStrings($a, $b)
Expand Down Expand Up @@ -805,8 +811,6 @@ protected function _getRemoteIniFile($url, $path)

if ($remote_tmstp < $local_tmstp) {
// No update needed, return
touch($path);

return false;
}
}
Expand Down Expand Up @@ -1047,4 +1051,4 @@ protected function _getUserAgent()
* @license http://www.opensource.org/licenses/MIT MIT License
* @link https://github.com/GaretJax/phpbrowscap/*/
class Exception extends BaseException
{}
{}