TYPO3 CMS  TYPO3_6-2
CacheManager.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Cache;
3 
18 
19 
30 
34  protected $cacheFactory;
35 
39  protected $caches = array();
40 
44  protected $cacheConfigurations = array();
45 
54  protected $cacheGroups = array();
55 
59  protected $defaultCacheConfiguration = array(
60  'frontend' => 'TYPO3\\CMS\\Core\\Cache\\Frontend\\VariableFrontend',
61  'backend' => 'TYPO3\\CMS\\Core\\Cache\\Backend\\Typo3DatabaseBackend',
62  'options' => array(),
63  'groups' => array('all')
64  );
65 
71  $this->cacheFactory = $cacheFactory;
72  }
73 
91  foreach ($cacheConfigurations as $identifier => $configuration) {
92  if (!is_array($configuration)) {
93  throw new \InvalidArgumentException('The cache configuration for cache "' . $identifier . '" was not an array as expected.', 1231259656);
94  }
95  $this->cacheConfigurations[$identifier] = $configuration;
96  }
97  }
98 
107  public function registerCache(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $cache) {
108  $identifier = $cache->getIdentifier();
109  if (isset($this->caches[$identifier])) {
110  throw new \TYPO3\CMS\Core\Cache\Exception\DuplicateIdentifierException('A cache with identifier "' . $identifier . '" has already been registered.', 1203698223);
111  }
112  $this->caches[$identifier] = $cache;
113  }
114 
123  public function getCache($identifier) {
124  if ($this->hasCache($identifier) === FALSE) {
125  throw new \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException('A cache with identifier "' . $identifier . '" does not exist.', 1203699034);
126  }
127  if (!isset($this->caches[$identifier])) {
128  $this->createCache($identifier);
129  }
130  return $this->caches[$identifier];
131  }
132 
140  public function hasCache($identifier) {
141  return isset($this->caches[$identifier]) || isset($this->cacheConfigurations[$identifier]);
142  }
143 
150  public function flushCaches() {
151  $this->createAllCaches();
152  foreach ($this->caches as $cache) {
153  $cache->flush();
154  }
155  }
156 
165  public function flushCachesInGroup($groupIdentifier) {
166  $this->createAllCaches();
167  if (isset($this->cacheGroups[$groupIdentifier])) {
168  foreach ($this->cacheGroups[$groupIdentifier] as $cacheIdentifier) {
169  if (isset($this->caches[$cacheIdentifier])) {
170  $this->caches[$cacheIdentifier]->flush();
171  }
172  }
173  } else {
174  throw new NoSuchCacheGroupException('No cache in the specified group \'' . $groupIdentifier . '\'', 1390334120);
175  }
176  }
177 
188  public function flushCachesInGroupByTag($groupIdentifier, $tag) {
189  $this->createAllCaches();
190  if (isset($this->cacheGroups[$groupIdentifier])) {
191  foreach ($this->cacheGroups[$groupIdentifier] as $cacheIdentifier) {
192  if (isset($this->caches[$cacheIdentifier])) {
193  $this->caches[$cacheIdentifier]->flushByTag($tag);
194  }
195  }
196  } else {
197  throw new NoSuchCacheGroupException('No cache in the specified group \'' . $groupIdentifier . '\'', 1390337129);
198  }
199  }
200 
201 
210  public function flushCachesByTag($tag) {
211  $this->createAllCaches();
212  foreach ($this->caches as $cache) {
213  $cache->flushByTag($tag);
214  }
215  }
216 
235  public function flushClassFileCachesByChangedFiles($fileMonitorIdentifier, array $changedFiles) {
236  $modifiedClassNamesWithUnderscores = array();
237  $objectClassesCache = $this->getCache('FLOW3_Object_Classes');
238  $objectConfigurationCache = $this->getCache('FLOW3_Object_Configuration');
239  switch ($fileMonitorIdentifier) {
240  case 'FLOW3_ClassFiles':
241  $modifiedAspectClassNamesWithUnderscores = array();
242  foreach ($changedFiles as $pathAndFilename => $status) {
243  $pathAndFilename = str_replace(FLOW3_PATH_PACKAGES, '', $pathAndFilename);
244  $matches = array();
245  if (preg_match('/[^\\/]+\\/(.+)\\/(Classes|Tests)\\/(.+)\\.php/', $pathAndFilename, $matches) === 1) {
246  $classNameWithUnderscores = str_replace(array('/', '.'), '_', $matches[1] . '_' . ($matches[2] === 'Tests' ? 'Tests_' : '') . $matches[3]);
247  $modifiedClassNamesWithUnderscores[$classNameWithUnderscores] = TRUE;
248  // If an aspect was modified, the whole code cache needs to be flushed, so keep track of them:
249  if (substr($classNameWithUnderscores, -6, 6) === 'Aspect') {
250  $modifiedAspectClassNamesWithUnderscores[$classNameWithUnderscores] = TRUE;
251  }
252  // As long as no modified aspect was found, we are optimistic that only part of the cache needs to be flushed:
253  if (count($modifiedAspectClassNamesWithUnderscores) === 0) {
254  $objectClassesCache->remove($classNameWithUnderscores);
255  }
256  }
257  }
258  $flushDoctrineProxyCache = FALSE;
259  if (count($modifiedClassNamesWithUnderscores) > 0) {
260  $reflectionStatusCache = $this->getCache('FLOW3_Reflection_Status');
261  foreach ($modifiedClassNamesWithUnderscores as $classNameWithUnderscores => $_) {
262  $reflectionStatusCache->remove($classNameWithUnderscores);
263  if ($flushDoctrineProxyCache === FALSE && preg_match('/_Domain_Model_(.+)/', $classNameWithUnderscores) === 1) {
264  $flushDoctrineProxyCache = TRUE;
265  }
266  }
267  $objectConfigurationCache->remove('allCompiledCodeUpToDate');
268  }
269  if (count($modifiedAspectClassNamesWithUnderscores) > 0) {
270  $this->systemLogger->log('Aspect classes have been modified, flushing the whole proxy classes cache.', LOG_INFO);
271  $objectClassesCache->flush();
272  }
273  if ($flushDoctrineProxyCache === TRUE) {
274  $this->systemLogger->log('Domain model changes have been detected, triggering Doctrine 2 proxy rebuilding.', LOG_INFO);
275  $objectConfigurationCache->remove('doctrineProxyCodeUpToDate');
276  }
277  break;
278  case 'FLOW3_ConfigurationFiles':
279  $policyChangeDetected = FALSE;
280  $routesChangeDetected = FALSE;
281  foreach ($changedFiles as $pathAndFilename => $_) {
282  $filename = basename($pathAndFilename);
283  if (!in_array($filename, array('Policy.yaml', 'Routes.yaml'))) {
284  continue;
285  }
286  if ($policyChangeDetected === FALSE && $filename === 'Policy.yaml') {
287  $this->systemLogger->log('The security policies have changed, flushing the policy cache.', LOG_INFO);
288  $this->getCache('FLOW3_Security_Policy')->flush();
289  $policyChangeDetected = TRUE;
290  } elseif ($routesChangeDetected === FALSE && $filename === 'Routes.yaml') {
291  $this->systemLogger->log('A Routes.yaml file has been changed, flushing the routing cache.', LOG_INFO);
292  $this->getCache('FLOW3_Mvc_Routing_FindMatchResults')->flush();
293  $this->getCache('FLOW3_Mvc_Routing_Resolve')->flush();
294  $routesChangeDetected = TRUE;
295  }
296  }
297  $this->systemLogger->log('The configuration has changed, triggering an AOP proxy class rebuild.', LOG_INFO);
298  $objectConfigurationCache->remove('allAspectClassesUpToDate');
299  $objectConfigurationCache->remove('allCompiledCodeUpToDate');
300  $objectClassesCache->flush();
301  break;
302  case 'FLOW3_TranslationFiles':
303  foreach ($changedFiles as $pathAndFilename => $status) {
304  $matches = array();
305  if (preg_match('/\\/Translations\\/.+\\.xlf/', $pathAndFilename, $matches) === 1) {
306  $this->systemLogger->log('The localization files have changed, thus flushing the I18n XML model cache.', LOG_INFO);
307  $this->getCache('FLOW3_I18n_XmlModelCache')->flush();
308  break;
309  }
310  }
311  break;
312  }
313  }
314 
330  static public function getClassTag($className = '') {
332  }
333 
339  protected function createAllCaches() {
340  foreach ($this->cacheConfigurations as $identifier => $_) {
341  if (!isset($this->caches[$identifier])) {
342  $this->createCache($identifier);
343  }
344  }
345  }
346 
353  protected function createCache($identifier) {
354  if (isset($this->cacheConfigurations[$identifier]['frontend'])) {
355  $frontend = $this->cacheConfigurations[$identifier]['frontend'];
356  } else {
357  $frontend = $this->defaultCacheConfiguration['frontend'];
358  }
359  if (isset($this->cacheConfigurations[$identifier]['backend'])) {
360  $backend = $this->cacheConfigurations[$identifier]['backend'];
361  } else {
362  $backend = $this->defaultCacheConfiguration['backend'];
363  }
364  if (isset($this->cacheConfigurations[$identifier]['options'])) {
365  $backendOptions = $this->cacheConfigurations[$identifier]['options'];
366  } else {
367  $backendOptions = $this->defaultCacheConfiguration['options'];
368  }
369 
370  // Add the cache identifier to the groups that it should be attached to, or use the default ones.
371  if (isset($this->cacheConfigurations[$identifier]['groups']) && is_array($this->cacheConfigurations[$identifier]['groups'])) {
372  $assignedGroups = $this->cacheConfigurations[$identifier]['groups'];
373  } else {
374  $assignedGroups = $this->defaultCacheConfiguration['groups'];
375  }
376  foreach ($assignedGroups as $groupIdentifier) {
377  if (!isset($this->cacheGroups[$groupIdentifier])) {
378  $this->cacheGroups[$groupIdentifier] = array();
379  }
380  $this->cacheGroups[$groupIdentifier][] = $identifier;
381  }
382 
383  $this->cacheFactory->create($identifier, $frontend, $backend, $backendOptions);
384  }
385 
386 }
setCacheConfigurations(array $cacheConfigurations)
flushCachesInGroup($groupIdentifier)
registerCache(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $cache)
flushClassFileCachesByChangedFiles($fileMonitorIdentifier, array $changedFiles)
static getClassTag($className='')
injectCacheFactory(\TYPO3\CMS\Core\Cache\CacheFactory $cacheFactory)
flushCachesInGroupByTag($groupIdentifier, $tag)