| <?php |
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Plugins\DeviceDetectorCache; |
|
|
| use DeviceDetector\ClientHints; |
| use DeviceDetector\DeviceDetector; |
| use Piwik\Container\StaticContainer; |
| use Piwik\DeviceDetector\DeviceDetectorFactory; |
| use Piwik\Filesystem; |
| use Piwik\Plugins\DeviceDetectorCache\DeviceDetector\CachedBrowserParser; |
| use Piwik\Plugins\DeviceDetectorCache\DeviceDetector\CachedOperatingSystemParser; |
|
|
| class CachedEntry extends DeviceDetector |
| { |
| private static $CACHE_DIR = ''; |
| private static $customCache = null; |
|
|
| public function __construct(string $userAgent, $clientHints, array $values) |
| { |
| $clientHints = $clientHints ? ClientHints::factory($clientHints) : null; |
| parent::__construct($userAgent, $clientHints); |
|
|
| $this->bot = $values['bot'] ?? null; |
| $this->brand = $values['brand'] ?? ''; |
| $this->client = $values['client'] ?? null; |
| $this->device = $values['device'] ?? null; |
| $this->model = $values['model'] ?? ''; |
| $this->os = $values['os'] ?? null; |
|
|
| |
| |
| if (!empty($clientHints) && !empty($values['client']['type']) && $values['client']['type'] === 'browser') { |
| $browserParser = new CachedBrowserParser($userAgent, $clientHints); |
| $browserParser->setCachedResult($this->client); |
| $this->client = $browserParser->parse(); |
| } |
|
|
| if (!empty($clientHints)) { |
| $osParser = new CachedOperatingSystemParser($userAgent, $clientHints); |
| $osParser->setCachedResult($this->os); |
| $this->os = $osParser->parse(); |
| } |
| } |
|
|
| public static function getCached(string $userAgent): ?array |
| { |
| |
| |
| |
| $path = self::getCachePath($userAgent); |
| $exists = file_exists($path); |
| if ($exists) { |
| $values = @include($path); |
| if (!empty($values) && is_array($values) && isset($values['os'])) { |
| return $values; |
| } |
| } |
|
|
| return null; |
| } |
|
|
| public static function writeToCache(string $userAgent): ?string |
| { |
| if (self::getCached($userAgent)) { |
| return null; |
| } |
|
|
| if (empty(self::$customCache)) { |
| self::$customCache = StaticContainer::get('DeviceDetector\Cache\Cache'); |
| } |
|
|
| |
| |
| $deviceDetector = new DeviceDetector($userAgent); |
| $deviceDetector->discardBotInformation(); |
| $deviceDetector->setCache(self::$customCache); |
| $deviceDetector->parse(); |
|
|
| $outputArray = [ |
| 'bot' => $deviceDetector->getBot(), |
| 'brand' => $deviceDetector->getBrandName(), |
| 'client' => $deviceDetector->getClient(), |
| 'device' => $deviceDetector->getDevice(), |
| 'model' => $deviceDetector->getModel(), |
| 'os' => $deviceDetector->getOs() |
| ]; |
| $outputPath = self::getCachePath($userAgent, true); |
| $content = "<?php return " . var_export($outputArray, true) . ";"; |
| file_put_contents($outputPath, $content, LOCK_EX); |
|
|
| return $outputPath; |
| } |
|
|
| public static function getCachePath(string $userAgent, bool $createDirs = false): string |
| { |
| $userAgent = DeviceDetectorFactory::getNormalizedUserAgent($userAgent); |
| $hashedUserAgent = md5($userAgent); |
|
|
| |
| $cacheDir = self::getCacheDir(); |
| $hashDir = $cacheDir . substr($hashedUserAgent, 0, 3); |
|
|
| if ($createDirs) { |
| if (!is_dir($cacheDir)) { |
| Filesystem::mkdir($cacheDir); |
| } |
| if (!is_dir($hashDir)) { |
| Filesystem::mkdir($hashDir); |
| } |
| } |
|
|
| return $hashDir . '/' . $hashedUserAgent . '.php'; |
| } |
|
|
| public static function setCacheDir(string $cacheDir): void |
| { |
| self::$CACHE_DIR = $cacheDir; |
| } |
|
|
| public static function getCacheDir(): string |
| { |
| if (empty(self::$CACHE_DIR)) { |
| self::$CACHE_DIR = rtrim(PIWIK_DOCUMENT_ROOT, '/') . '/tmp/devicecache/'; |
| } |
| return self::$CACHE_DIR; |
| } |
|
|
| |
| |
| |
| |
| public static function clearCacheDir(): void |
| { |
| $path = self::getCacheDir(); |
| if ( |
| !empty($path) |
| && is_dir($path) |
| && strpos($path, PIWIK_DOCUMENT_ROOT) === 0 |
| ) { |
| |
|
|
| Filesystem::unlinkRecursive(self::getCacheDir(), false); |
| } |
| } |
|
|
| public static function getNumEntriesInCacheDir(): int |
| { |
| $files = self::getCacheFilesInCacheDir(); |
| return count($files); |
| } |
|
|
| private static function getCacheFilesInCacheDir(): array |
| { |
| $path = rtrim(self::getCacheDir(), '/'); |
| return array_filter(Filesystem::globr($path, '*.php'), function ($file) { |
| return strpos($file, 'index.php') === false; |
| }); |
| } |
|
|
| public static function deleteLeastAccessedFiles(int $numFilesToDelete): void |
| { |
| if ($numFilesToDelete < 1) { |
| return; |
| } |
| $files = self::getCacheFilesInCacheDir(); |
| $accessed = []; |
| foreach ($files as $file) { |
| $accessed[$file] = fileatime($file); |
| } |
|
|
| |
| asort($accessed, SORT_NATURAL); |
|
|
| $numFilesDeleted = 1; |
| foreach ($accessed as $file => $time) { |
| if ($numFilesDeleted > $numFilesToDelete) { |
| break; |
| } else { |
| Filesystem::deleteFileIfExists($file); |
| $numFilesDeleted++; |
| } |
| } |
| } |
| } |
|
|