vendor/jms/metadata/src/Cache/FileCache.php line 25

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Metadata\Cache;
  4. use Metadata\ClassMetadata;
  5. class FileCache implements CacheInterfaceClearableCacheInterface
  6. {
  7.     /**
  8.      * @var string
  9.      */
  10.     private $dir;
  11.     public function __construct(string $dir)
  12.     {
  13.         if (!is_dir($dir) && false === @mkdir($dir0777true)) {
  14.             throw new \InvalidArgumentException(sprintf('Can\'t create directory for cache at "%s"'$dir));
  15.         }
  16.         $this->dir rtrim($dir'\\/');
  17.     }
  18.     public function load(string $class): ?ClassMetadata
  19.     {
  20.         $path $this->getCachePath($class);
  21.         if (!is_readable($path)) {
  22.             return null;
  23.         }
  24.         try {
  25.             $metadata = include $path;
  26.             if ($metadata instanceof ClassMetadata) {
  27.                 return $metadata;
  28.             }
  29.             // if the file does not return anything, the return value is integer `1`.
  30.         } catch (\Error $e) {
  31.             // ignore corrupted cache
  32.         }
  33.         return null;
  34.     }
  35.     public function put(ClassMetadata $metadata): void
  36.     {
  37.         if (!is_writable($this->dir)) {
  38.             throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable.'$this->dir));
  39.         }
  40.         $path $this->getCachePath($metadata->name);
  41.         if (!is_writable(dirname($path))) {
  42.             throw new \RuntimeException(sprintf('Cache file "%s" is not writable.'$path));
  43.         }
  44.         $tmpFile tempnam($this->dir'metadata-cache');
  45.         if (false === $tmpFile) {
  46.             $this->evict($metadata->name);
  47.             return;
  48.         }
  49.         $data '<?php return unserialize(' var_export(serialize($metadata), true) . ');';
  50.         $bytesWritten file_put_contents($tmpFile$data);
  51.         // use strlen and not mb_strlen. if there is utf8 in the code, it also writes more bytes.
  52.         if ($bytesWritten !== strlen($data)) {
  53.             @unlink($tmpFile);
  54.             // also evict the cache to not use an outdated version.
  55.             $this->evict($metadata->name);
  56.             return;
  57.         }
  58.         // Let's not break filesystems which do not support chmod.
  59.         @chmod($tmpFile0666 & ~umask());
  60.         $this->renameFile($tmpFile$path);
  61.     }
  62.     /**
  63.      * Renames a file with fallback for windows
  64.      */
  65.     private function renameFile(string $sourcestring $target): void
  66.     {
  67.         if (false === @rename($source$target)) {
  68.             if (defined('PHP_WINDOWS_VERSION_BUILD')) {
  69.                 if (false === copy($source$target)) {
  70.                     throw new \RuntimeException(sprintf('(WIN) Could not write new cache file to %s.'$target));
  71.                 }
  72.                 if (false === unlink($source)) {
  73.                     throw new \RuntimeException(sprintf('(WIN) Could not delete temp cache file to %s.'$source));
  74.                 }
  75.             } else {
  76.                 throw new \RuntimeException(sprintf('Could not write new cache file to %s.'$target));
  77.             }
  78.         }
  79.     }
  80.     public function evict(string $class): void
  81.     {
  82.         $path $this->getCachePath($class);
  83.         if (file_exists($path)) {
  84.             @unlink($path);
  85.         }
  86.     }
  87.     public function clear(): bool
  88.     {
  89.         $result true;
  90.         $files glob($this->dir '/*.cache.php');
  91.         foreach ($files as $file) {
  92.             if (is_file($file)) {
  93.                 $result $result && @unlink($file);
  94.             }
  95.         }
  96.         return $result;
  97.     }
  98.     /**
  99.      * This function computes the cache file path.
  100.      *
  101.      * If anonymous class is to be cached, it contains invalid path characters that need to be removed/replaced
  102.      * Example of anonymous class name: class@anonymous\x00/app/src/Controller/DefaultController.php0x7f82a7e026ec
  103.      */
  104.     private function getCachePath(string $key): string
  105.     {
  106.         $fileName str_replace(['\\'"\0"'@''/''$''{''}'':'], '-'$key);
  107.         return $this->dir '/' $fileName '.cache.php';
  108.     }
  109. }