Upgraded drupal core with security updates
[yaffs-website] / web / core / lib / Drupal / Component / FileCache / FileCache.php
1 <?php
2
3 namespace Drupal\Component\FileCache;
4
5 /**
6  * Allows to cache data based on file modification dates.
7  */
8 class FileCache implements FileCacheInterface {
9
10   /**
11    * Prefix that is used for cache entries.
12    *
13    * @var string
14    */
15   protected $prefix;
16
17   /**
18    * Static cache that contains already loaded cache entries.
19    *
20    * @var array
21    */
22   protected static $cached = [];
23
24   /**
25    * The collection identifier of this cache.
26    *
27    * @var string
28    */
29   protected $collection;
30
31   /**
32    * The cache backend backing this FileCache object.
33    *
34    * @var \Drupal\Component\FileCache\FileCacheBackendInterface
35    */
36   protected $cache;
37
38   /**
39    * Constructs a FileCache object.
40    *
41    * @param string $prefix
42    *   The cache 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.
50    */
51   public function __construct($prefix, $collection, $cache_backend_class = NULL, array $cache_backend_configuration = []) {
52
53     if (empty($prefix)) {
54       throw new \InvalidArgumentException('Required prefix configuration is missing');
55     }
56
57     $this->prefix = $prefix;
58     $this->collection = $collection;
59
60     if (isset($cache_backend_class)) {
61       $this->cache = new $cache_backend_class($cache_backend_configuration);
62     }
63   }
64
65   /**
66    * {@inheritdoc}
67    */
68   public function get($filepath) {
69     $filepaths = [$filepath];
70     $cached = $this->getMultiple($filepaths);
71     return isset($cached[$filepath]) ? $cached[$filepath] : NULL;
72   }
73
74   /**
75    * {@inheritdoc}
76    */
77   public function getMultiple(array $filepaths) {
78     $file_data = [];
79     $remaining_cids = [];
80
81     // First load from the static cache what we can.
82     foreach ($filepaths as $filepath) {
83       if (!file_exists($filepath)) {
84         continue;
85       }
86
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)) {
91         continue;
92       }
93
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'];
97       }
98       else {
99         // Collect a list of cache IDs that we still need to fetch from cache
100         // backend.
101         $remaining_cids[$cid] = $filepath;
102       }
103     }
104
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;
113         }
114       }
115     }
116
117     return $file_data;
118   }
119
120   /**
121    * {@inheritdoc}
122    */
123   public function set($filepath, $data) {
124     $realpath = realpath($filepath);
125     $cached = [
126       'mtime' => filemtime($filepath),
127       'filepath' => $filepath,
128       'data' => $data,
129     ];
130
131     $cid = $this->prefix . ':' . $this->collection . ':' . $realpath;
132     static::$cached[$cid] = $cached;
133     if ($this->cache) {
134       $this->cache->store($cid, $cached);
135     }
136   }
137
138   /**
139    * {@inheritdoc}
140    */
141   public function delete($filepath) {
142     $realpath = realpath($filepath);
143     $cid = $this->prefix . ':' . $this->collection . ':' . $realpath;
144
145     unset(static::$cached[$cid]);
146     if ($this->cache) {
147       $this->cache->delete($cid);
148     }
149   }
150
151   /**
152    * Resets the static cache.
153    *
154    * @todo Replace this once https://www.drupal.org/node/2260187 is in.
155    */
156   public static function reset() {
157     static::$cached = [];
158   }
159
160 }