TYPO3 CMS  TYPO3_8-7
WincacheBackend.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
38 {
44  protected $identifierPrefix;
45 
53  public function __construct($context, array $options = [])
54  {
55  if (!extension_loaded('wincache')) {
56  throw new \TYPO3\CMS\Core\Cache\Exception('The PHP extension "wincache" must be installed and loaded in order to use the wincache backend.', 1343331520);
57  }
58  parent::__construct($context, $options);
59  }
60 
72  public function set($entryIdentifier, $data, array $tags = [], $lifetime = null)
73  {
74  if (!$this->cache instanceof \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface) {
75  throw new \TYPO3\CMS\Core\Cache\Exception('No cache frontend has been set yet via setCache().', 1343331521);
76  }
77  if (!is_string($data)) {
78  throw new \TYPO3\CMS\Core\Cache\Exception\InvalidDataException('The specified data is of type "' . gettype($data) . '" but a string is expected.', 1343331522);
79  }
80  $tags[] = '%WCBE%' . $this->cache->getIdentifier();
81  $expiration = $lifetime !== null ? $lifetime : $this->defaultLifetime;
82  $success = wincache_ucache_set($this->identifierPrefix . $entryIdentifier, $data, $expiration);
83  if ($success === true) {
84  $this->removeIdentifierFromAllTags($entryIdentifier);
85  $this->addIdentifierToTags($entryIdentifier, $tags);
86  } else {
87  throw new \TYPO3\CMS\Core\Cache\Exception('Could not set value.', 1343331523);
88  }
89  }
90 
97  public function get($entryIdentifier)
98  {
99  $success = false;
100  $value = wincache_ucache_get($this->identifierPrefix . $entryIdentifier, $success);
101  return $success ? $value : $success;
102  }
103 
110  public function has($entryIdentifier)
111  {
112  return wincache_ucache_exists($this->identifierPrefix . $entryIdentifier);
113  }
114 
123  public function remove($entryIdentifier)
124  {
125  $this->removeIdentifierFromAllTags($entryIdentifier);
126  return wincache_ucache_delete($this->identifierPrefix . $entryIdentifier);
127  }
128 
136  public function findIdentifiersByTag($tag)
137  {
138  $success = false;
139  $identifiers = wincache_ucache_get($this->identifierPrefix . 'tag_' . $tag, $success);
140  if ($success === false) {
141  return [];
142  }
143  return (array)$identifiers;
144  }
145 
153  protected function findTagsByIdentifier($identifier)
154  {
155  $success = false;
156  $tags = wincache_ucache_get($this->identifierPrefix . 'ident_' . $identifier, $success);
157  return $success ? (array)$tags : [];
158  }
159 
165  public function flush()
166  {
167  if (!$this->cache instanceof \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface) {
168  throw new \TYPO3\CMS\Core\Cache\Exception('Yet no cache frontend has been set via setCache().', 1343331524);
169  }
170  $this->flushByTag('%WCBE%' . $this->cache->getIdentifier());
171  }
172 
179  public function flushByTag($tag)
180  {
181  $identifiers = $this->findIdentifiersByTag($tag);
182  foreach ($identifiers as $identifier) {
183  $this->remove($identifier);
184  }
185  }
186 
193  protected function addIdentifierToTags($entryIdentifier, array $tags)
194  {
195  // Get identifier-to-tag index to look for updates
196  $existingTags = $this->findTagsByIdentifier($entryIdentifier);
197  $existingTagsUpdated = false;
198 
199  foreach ($tags as $tag) {
200  // Update tag-to-identifier index
201  $identifiers = $this->findIdentifiersByTag($tag);
202  if (!in_array($entryIdentifier, $identifiers, true)) {
203  $identifiers[] = $entryIdentifier;
204  wincache_ucache_set($this->identifierPrefix . 'tag_' . $tag, $identifiers);
205  }
206  // Test if identifier-to-tag index needs update
207  if (!in_array($tag, $existingTags, true)) {
208  $existingTags[] = $tag;
209  $existingTagsUpdated = true;
210  }
211  }
212 
213  // Update identifier-to-tag index if needed
214  if ($existingTagsUpdated) {
215  wincache_ucache_set($this->identifierPrefix . 'ident_' . $entryIdentifier, $existingTags);
216  }
217  }
218 
224  protected function removeIdentifierFromAllTags($entryIdentifier)
225  {
226  // Get tags for this identifier
227  $tags = $this->findTagsByIdentifier($entryIdentifier);
228  // Deassociate tags with this identifier
229  foreach ($tags as $tag) {
230  $identifiers = $this->findIdentifiersByTag($tag);
231  // Formally array_search() below should never return false due to
232  // the behavior of findTagsByIdentifier(). But if reverse index is
233  // corrupted, we still can get 'false' from array_search(). This is
234  // not a problem because we are removing this identifier from
235  // anywhere.
236  if (($key = array_search($entryIdentifier, $identifiers)) !== false) {
237  unset($identifiers[$key]);
238  if (!empty($identifiers)) {
239  wincache_ucache_set($this->identifierPrefix . 'tag_' . $tag, $identifiers);
240  } else {
241  wincache_ucache_delete($this->identifierPrefix . 'tag_' . $tag);
242  }
243  }
244  }
245  // Clear reverse tag index for this identifier
246  wincache_ucache_delete($this->identifierPrefix . 'ident_' . $entryIdentifier);
247  }
248 
252  public function collectGarbage()
253  {
254  }
255 }
addIdentifierToTags($entryIdentifier, array $tags)
__construct($context, array $options=[])