3 namespace Drupal\Component\FileCache;
6 * Allows to cache data based on file modification dates.
8 class FileCache implements FileCacheInterface {
11 * Prefix that is used for cache entries.
18 * Static cache that contains already loaded cache entries.
22 protected static $cached = [];
25 * The collection identifier of this cache.
29 protected $collection;
32 * The cache backend backing this FileCache object.
34 * @var \Drupal\Component\FileCache\FileCacheBackendInterface
39 * Constructs a FileCache object.
41 * @param string $prefix
43 * @param string $collection
44 * A collection identifier to ensure that the same files could be cached for
45 * different purposes without clashing.
46 * @param string|null $cache_backend_class
47 * (optional) The class that should be used as cache backend.
48 * @param array $cache_backend_configuration
49 * (optional) The configuration for the backend class.
51 public function __construct($prefix, $collection, $cache_backend_class = NULL, array $cache_backend_configuration = []) {
54 throw new \InvalidArgumentException('Required prefix configuration is missing');
57 $this->prefix = $prefix;
58 $this->collection = $collection;
60 if (isset($cache_backend_class)) {
61 $this->cache = new $cache_backend_class($cache_backend_configuration);
68 public function get($filepath) {
69 $filepaths = [$filepath];
70 $cached = $this->getMultiple($filepaths);
71 return isset($cached[$filepath]) ? $cached[$filepath] : NULL;
77 public function getMultiple(array $filepaths) {
81 // First load from the static cache what we can.
82 foreach ($filepaths as $filepath) {
83 if (!file_exists($filepath)) {
87 $realpath = realpath($filepath);
88 // If the file exists but realpath returns nothing, it is using a stream
89 // wrapper, those are not supported.
90 if (empty($realpath)) {
94 $cid = $this->prefix . ':' . $this->collection . ':' . $realpath;
95 if (isset(static::$cached[$cid]) && static::$cached[$cid]['mtime'] == filemtime($filepath)) {
96 $file_data[$filepath] = static::$cached[$cid]['data'];
99 // Collect a list of cache IDs that we still need to fetch from cache
101 $remaining_cids[$cid] = $filepath;
105 // If there are any cache IDs left to fetch from the cache backend.
106 if ($remaining_cids && $this->cache) {
107 $cache_results = $this->cache->fetch(array_keys($remaining_cids)) ?: [];
108 foreach ($cache_results as $cid => $cached) {
109 $filepath = $remaining_cids[$cid];
110 if ($cached['mtime'] == filemtime($filepath)) {
111 $file_data[$cached['filepath']] = $cached['data'];
112 static::$cached[$cid] = $cached;
123 public function set($filepath, $data) {
124 $realpath = realpath($filepath);
126 'mtime' => filemtime($filepath),
127 'filepath' => $filepath,
131 $cid = $this->prefix . ':' . $this->collection . ':' . $realpath;
132 static::$cached[$cid] = $cached;
134 $this->cache->store($cid, $cached);
141 public function delete($filepath) {
142 $realpath = realpath($filepath);
143 $cid = $this->prefix . ':' . $this->collection . ':' . $realpath;
145 unset(static::$cached[$cid]);
147 $this->cache->delete($cid);
152 * Resets the static cache.
154 * @todo Replace this once https://www.drupal.org/node/2260187 is in.
156 public static function reset() {
157 static::$cached = [];