/** * Gets the browscap data of the used source type * * @return string */ public function getBrowscapSource() { $type = Browscap::getParser()->getSourceType(); $url = str_replace('%t', urlencode($type), $this->getBrowscapSourceUrl()); return $this->getRemoteData($url); }
/** * Gets the cache prefix, dependent of the used browscap dataset type. * * @return string */ protected static function getCachePrefix() { switch (Browscap::getDatasetType()) { case Browscap::DATASET_TYPE_SMALL: return 'smallbrowscap'; case Browscap::DATASET_TYPE_LARGE: return 'largebrowscap'; default: return 'browscap'; } }
/** * Checks if the source needs to be updated and processes the update * * @param boolean $forceUpdate * @throws \RuntimeException */ public function update($forceUpdate = false) { // get updater $updater = Browscap::getUpdater(); // check if an updater has been set - if not, nothing will be updated if ($updater !== null && $updater instanceof Updater\None === false) { // initialize variables $prefix = static::getCachePrefix(); /** @var Cache\File $cache */ $cache = static::getCache(); $path = $cache->getFileName("{$prefix}.ini", true); $readable = is_readable($path); $local_ts = 0; // do we have to check for a new update? if ($forceUpdate) { $update = true; } else { if ($readable) { $local_ts = filemtime($path); $update = time() - $local_ts >= $updater->getInterval(); } else { $local_ts = 0; $update = true; } } if ($update) { // check version/timestamp, to se if we need to do an update $do_update = false; if ($local_ts === 0) { $do_update = true; } else { $source_version = $updater->getBrowscapVersionNumber(); if ($source_version !== null && $source_version > $this->getVersion()) { $do_update = true; } else { $source_ts = $updater->getBrowscapVersion(); if ($source_ts > $local_ts) { $do_update = true; } } } if ($do_update) { // touch the file first so that the update is not triggered for some seconds, // to avoid that the update is triggered by multiple users at the same time if ($readable) { $update_lock_time = 300; touch($path, time() - $updater->getInterval() + $update_lock_time); } // get content try { $source_content = $updater->getBrowscapSource(); $source_exception = null; } catch (\Exception $e) { $source_content = null; $source_exception = $e; } if (!empty($source_content)) { // update internal version cache first, // to get the correct version for the next cache file if (isset($source_version)) { static::$version = (int) $source_version; } else { $key = $this->pregQuote(self::BROWSCAP_VERSION_KEY); if (preg_match("/\\.*[" . $key . "\\][^[]*Version=(\\d+)\\D.*/", $source_content, $matches)) { if (isset($matches[1])) { static::$version = (int) $matches[1]; } } else { // ignore the error if... // - we have old source data we can work with // - and the data are loaded from a remote source if ($readable && $updater instanceof Updater\AbstractUpdaterRemote) { touch($path); } else { throw new \RuntimeException("Problem parsing the INI file."); } } } // create cache file for the new version static::getCache()->set("{$prefix}.ini", $source_content, true); unset($source_content); // update cached version static::getCache()->set("{$prefix}.version", static::$version, false); // reset cached ini data $this->resetCachedData(); } else { // ignore the error if... // - we have old source data we can work with // - and the data are loaded from a remote source if ($readable && $updater instanceof Updater\AbstractUpdaterRemote) { touch($path); } else { throw new \RuntimeException("Error loading browscap source.", 0, $source_exception); } } } else { if ($readable) { touch($path); } } } } elseif ($forceUpdate === true) { throw new \RuntimeException("Required updater missing for forced update."); } }
/** * Gets the main/version cache directory * * @param boolean $with_version * @param bool $create_dir * @return string */ public static function getCacheDirectory($with_version = false, $create_dir = false) { // get sub directory name, depending on the data set type // (one sub directory for each data set type and version) switch (Browscap::getDatasetType()) { case Browscap::DATASET_TYPE_SMALL: $subDirName = 'smallbrowscap'; break; case Browscap::DATASET_TYPE_LARGE: $subDirName = 'largebrowscap'; break; default: $subDirName = 'browscap'; } if (static::$cache_dir === null) { static::setCacheDirectory(sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'browscap'); } $path = static::$cache_dir; if ($with_version === true) { $path .= DIRECTORY_SEPARATOR . $subDirName; $path .= '_v' . Browscap::getParser()->getVersion(); $path .= '_' . Browscap::VERSION; } if ($create_dir === true && !file_exists($path)) { mkdir($path, 0777, true); } return $path; }
/** * @expectedException \Crossjoin\Browscap\Exception\ParserRuntimeException * * @covers ::update * * @throws InvalidArgumentException * @throws ParserConfigurationException * @throws ParserRuntimeException * @throws SourceUnavailableException */ public function testUpdateLoop() { $reader = $this->getMockBuilder('\\Crossjoin\\Browscap\\Parser\\Sqlite\\Reader')->disableOriginalConstructor()->setMethods(['isUpdateRequired'])->getMock(); $reader->expects(static::any())->method('isUpdateRequired')->willReturn(true); $parser = $this->getMockBuilder('\\Crossjoin\\Browscap\\Parser\\Sqlite\\Parser')->disableOriginalConstructor()->setMethods(['getReader'])->getMock(); $parser->expects(static::any())->method('getReader')->willReturn($reader); $iniFile = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR . 'lite_php_browscap.ini'; $source = new File($iniFile); /** @var \Crossjoin\Browscap\Parser\Sqlite\Parser $parser */ $parser->setSource($source); $browscap = new Browscap(); $browscap->setParser($parser); $browscap->update(true); }
/** * @param InputInterface $input * @param OutputInterface $output * * @return int|null|void * @throws ParserConfigurationException * @throws ParserRuntimeException * @throws SourceConditionNotSatisfiedException * @throws SourceUnavailableException * @throws UnexpectedValueException */ protected function execute(InputInterface $input, OutputInterface $output) { $browscap = new Browscap(); // Set source $source = null; if ($input->getOption('ini-php')) { $source = new PhpSetting(); } elseif ($input->getOption('ini-load')) { $type = Type::STANDARD; switch ($input->getOption('ini-load')) { case 'lite': $type = Type::LITE; break; case 'full': $type = Type::FULL; break; } $source = new BrowscapOrg($type); } elseif ($input->getOption('ini-file')) { $file = (string) $input->getOption('ini-file'); $source = new File($file); } if ($source !== null) { $browscap->getParser()->setSource($source); } // Set filter $filter = null; if ($input->getOption('filter-allowed')) { $properties = (array) $input->getOption('filter-allowed'); $filter = new Allowed($properties); } elseif ($input->getOption('filter-disallowed')) { $properties = (array) $input->getOption('filter-disallowed'); $filter = new Disallowed($properties); } if ($filter !== null) { $browscap->getParser()->setPropertyFilter($filter); } // Set data directory if ($input->getOption('dir')) { /** @var Parser $parser */ $parser = $browscap->getParser(); $parser->setDataDirectory((string) $input->getOption('dir')); } // Force an update? $force = false; if ($input->getOption('force')) { $force = true; } // Process update $output->writeln('Processing update...'); $updated = $browscap->update($force); // Output result $version = $browscap->getParser()->getReader()->getVersion(); $type = $browscap->getParser()->getReader()->getType(); $name = Type::getName($type); if ($updated === true) { $output->writeln(sprintf('Browscap data successfully updated. New version: %s (%s)', $version, $name)); } else { $output->writeln(sprintf('Nothing to update. Current version: %s (%s)', $version, $name)); } }