Upgraded drupal core with security updates
[yaffs-website] / web / core / lib / Drupal / Core / Cache / PhpBackend.php
1 <?php
2
3 namespace Drupal\Core\Cache;
4
5 use Drupal\Core\PhpStorage\PhpStorageFactory;
6 use Drupal\Component\Utility\Crypt;
7
8 /**
9  * Defines a PHP cache implementation.
10  *
11  * Stores cache items in a PHP file using a storage that implements
12  * Drupal\Component\PhpStorage\PhpStorageInterface.
13  *
14  * This is fast because of PHP's opcode caching mechanism. Once a file's
15  * content is stored in PHP's opcode cache, including it doesn't require
16  * reading the contents from a filesystem. Instead, PHP will use the already
17  * compiled opcodes stored in memory.
18  *
19  * @ingroup cache
20  */
21 class PhpBackend implements CacheBackendInterface {
22
23   /**
24    * @var string
25    */
26   protected $bin;
27
28   /**
29    * Array to store cache objects.
30    */
31   protected $cache = [];
32
33   /**
34    * The cache tags checksum provider.
35    *
36    * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
37    */
38   protected $checksumProvider;
39
40   /**
41    * Constructs a PhpBackend object.
42    *
43    * @param string $bin
44    *   The cache bin for which the object is created.
45    * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
46    *   The cache tags checksum provider.
47    */
48   public function __construct($bin, CacheTagsChecksumInterface $checksum_provider) {
49     $this->bin = 'cache_' . $bin;
50     $this->checksumProvider = $checksum_provider;
51   }
52
53   /**
54    * {@inheritdoc}
55    */
56   public function get($cid, $allow_invalid = FALSE) {
57     return $this->getByHash($this->normalizeCid($cid), $allow_invalid);
58   }
59
60   /**
61    * Fetch a cache item using a hashed cache ID.
62    *
63    * @param string $cidhash
64    *   The hashed version of the original cache ID after being normalized.
65    * @param bool $allow_invalid
66    *   (optional) If TRUE, a cache item may be returned even if it is expired or
67    *   has been invalidated.
68    *
69    * @return bool|mixed
70    */
71   protected function getByHash($cidhash, $allow_invalid = FALSE) {
72     if ($file = $this->storage()->getFullPath($cidhash)) {
73       $cache = @include $file;
74     }
75     if (isset($cache)) {
76       return $this->prepareItem($cache, $allow_invalid);
77     }
78     return FALSE;
79   }
80
81   /**
82    * {@inheritdoc}
83    */
84   public function setMultiple(array $items) {
85     foreach ($items as $cid => $item) {
86       $this->set($cid, $item['data'], isset($item['expire']) ? $item['expire'] : CacheBackendInterface::CACHE_PERMANENT, isset($item['tags']) ? $item['tags'] : []);
87     }
88   }
89
90   /**
91    * {@inheritdoc}
92    */
93   public function getMultiple(&$cids, $allow_invalid = FALSE) {
94     $ret = [];
95
96     foreach ($cids as $cid) {
97       if ($item = $this->get($cid, $allow_invalid)) {
98         $ret[$item->cid] = $item;
99       }
100     }
101
102     $cids = array_diff($cids, array_keys($ret));
103
104     return $ret;
105   }
106
107   /**
108    * Prepares a cached item.
109    *
110    * Checks that items are either permanent or did not expire, and returns data
111    * as appropriate.
112    *
113    * @param object $cache
114    *   An item loaded from cache_get() or cache_get_multiple().
115    * @param bool $allow_invalid
116    *   If FALSE, the method returns FALSE if the cache item is not valid.
117    *
118    * @return mixed
119    *   The item with data as appropriate or FALSE if there is no
120    *   valid item to load.
121    */
122   protected function prepareItem($cache, $allow_invalid) {
123     if (!isset($cache->data)) {
124       return FALSE;
125     }
126
127     // Check expire time.
128     $cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME;
129
130     // Check if invalidateTags() has been called with any of the item's tags.
131     if (!$this->checksumProvider->isValid($cache->checksum, $cache->tags)) {
132       $cache->valid = FALSE;
133     }
134
135     if (!$allow_invalid && !$cache->valid) {
136       return FALSE;
137     }
138
139     return $cache;
140   }
141
142   /**
143    * {@inheritdoc}
144    */
145   public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
146     assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($tags)', 'Cache Tags must be strings.');
147     $item = (object) [
148       'cid' => $cid,
149       'data' => $data,
150       'created' => round(microtime(TRUE), 3),
151       'expire' => $expire,
152       'tags' => array_unique($tags),
153       'checksum' => $this->checksumProvider->getCurrentChecksum($tags),
154     ];
155     $this->writeItem($this->normalizeCid($cid), $item);
156   }
157
158   /**
159    * {@inheritdoc}
160    */
161   public function delete($cid) {
162     $this->storage()->delete($this->normalizeCid($cid));
163   }
164
165   /**
166    * {@inheritdoc}
167    */
168   public function deleteMultiple(array $cids) {
169     foreach ($cids as $cid) {
170       $this->delete($cid);
171     }
172   }
173
174   /**
175    * {@inheritdoc}
176    */
177   public function deleteAll() {
178     $this->storage()->deleteAll();
179   }
180
181   /**
182    * {@inheritdoc}
183    */
184   public function invalidate($cid) {
185     $this->invalidatebyHash($this->normalizeCid($cid));
186   }
187
188   /**
189    * Invalidate one cache item.
190    *
191    * @param string $cidhash
192    *   The hashed version of the original cache ID after being normalized.
193    */
194   protected function invalidatebyHash($cidhash) {
195     if ($item = $this->getByHash($cidhash)) {
196       $item->expire = REQUEST_TIME - 1;
197       $this->writeItem($cidhash, $item);
198     }
199   }
200
201   /**
202    * {@inheritdoc}
203    */
204   public function invalidateMultiple(array $cids) {
205     foreach ($cids as $cid) {
206       $this->invalidate($cid);
207     }
208   }
209
210   /**
211    * {@inheritdoc}
212    */
213   public function invalidateAll() {
214     foreach ($this->storage()->listAll() as $cidhash) {
215       $this->invalidatebyHash($cidhash);
216     }
217   }
218
219   /**
220    * {@inheritdoc}
221    */
222   public function garbageCollection() {
223   }
224
225   /**
226    * {@inheritdoc}
227    */
228   public function removeBin() {
229     $this->cache = [];
230     $this->storage()->deleteAll();
231   }
232
233   /**
234    * Writes a cache item to PhpStorage.
235    *
236    * @param string $cidhash
237    *   The hashed version of the original cache ID after being normalized.
238    * @param \stdClass $item
239    *   The cache item to store.
240    */
241   protected function writeItem($cidhash, \stdClass $item) {
242     $content = '<?php return unserialize(' . var_export(serialize($item), TRUE) . ');';
243     $this->storage()->save($cidhash, $content);
244   }
245
246   /**
247    * Gets the PHP code storage object to use.
248    *
249    * @return \Drupal\Component\PhpStorage\PhpStorageInterface
250    */
251   protected function storage() {
252     if (!isset($this->storage)) {
253       $this->storage = PhpStorageFactory::get($this->bin);
254     }
255     return $this->storage;
256   }
257
258   /**
259    * Ensures a normalized cache ID.
260    *
261    * @param string $cid
262    *   The passed in cache ID.
263    *
264    * @return string
265    *   A normalized cache ID.
266    */
267   protected function normalizeCid($cid) {
268     return Crypt::hashBase64($cid);
269   }
270
271 }