‪TYPO3CMS  ‪main
CacheService.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
29 
35 {
41  protected array ‪$hasPidColumn = [];
42  protected array ‪$clearCacheForTables = [];
46  protected \SplStack ‪$pageIdStack;
47 
49  {
50  $this->configurationManager = ‪$configurationManager;
51  $this->cacheManager = ‪$cacheManager;
52  $this->pageIdStack = new \SplStack();
53  $this->connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
54  }
55 
56  public function ‪getPageIdStack(): \SplStack
57  {
58  return ‪$this->pageIdStack;
59  }
60 
66  public function ‪clearPageCache($pageIdsToClear = null): void
67  {
68  if ($pageIdsToClear === null) {
69  $this->cacheManager->flushCachesInGroup('pages');
70  } else {
71  if (!is_array($pageIdsToClear)) {
72  $pageIdsToClear = [(int)$pageIdsToClear];
73  }
74  $tags = array_map(static fn(int $item): string => 'pageId_' . $item, $pageIdsToClear);
75  $this->cacheManager->flushCachesInGroupByTags('pages', $tags);
76  }
77  }
78 
86  public function ‪clearCachesOfRegisteredPageIds(): void
87  {
88  $frameworkConfiguration = $this->configurationManager->getConfiguration(‪ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
89  if (!empty($frameworkConfiguration['persistence']['enableAutomaticCacheClearing'] ?? false)) {
90  foreach ($this->clearCacheForTables as $table => $ids) {
91  foreach ($ids as $id) {
92  $this->‪clearPageCacheForGivenRecord($table, $id);
93  }
94  }
95  }
96  if (!$this->pageIdStack->isEmpty()) {
97  $pageIds = [];
98  while (!$this->pageIdStack->isEmpty()) {
99  $pageIds[] = (int)$this->pageIdStack->pop();
100  }
101  $pageIds = array_values(array_unique($pageIds));
102  $this->‪clearPageCache($pageIds);
103  }
104  }
105 
115  public function ‪clearCacheForRecord(string $table, int ‪$uid): void
116  {
117  if (!is_array($this->clearCacheForTables[$table] ?? null)) {
118  $this->clearCacheForTables[$table] = [];
119  }
120  $this->clearCacheForTables[$table][] = ‪$uid;
121  }
122 
133  protected function ‪clearPageCacheForGivenRecord(string $tableName, int ‪$uid): void
134  {
135  $pageIdsToClear = [];
136  $storagePage = null;
137 
138  // As determining the table columns is a costly operation this is done only once per table during runtime and cached then
139  if (!isset($this->hasPidColumn[$tableName])) {
140  $columns = $this->connectionPool
141  ->getConnectionForTable($tableName)
142  ->createSchemaManager()
143  ->listTableColumns($tableName);
144  $this->hasPidColumn[$tableName] = array_key_exists('pid', $columns);
145  }
146 
147  if ($this->hasPidColumn[$tableName]) {
148  $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
149  $queryBuilder->getRestrictions()->removeAll();
150  $result = $queryBuilder
151  ->select('pid')
152  ->from($tableName)
153  ->where(
154  $queryBuilder->expr()->eq(
155  'uid',
156  $queryBuilder->createNamedParameter(‪$uid, ‪Connection::PARAM_INT)
157  )
158  )
159  ->executeQuery();
160  if ($row = $result->fetchAssociative()) {
161  $storagePage = $row['pid'];
162  $pageIdsToClear[] = $storagePage;
163  }
164  } elseif ($this->‪getTypoScriptFrontendController() !== null) {
165  // No PID column - we can do a best-effort to clear the cache of the current page if in FE
166  $storagePage = $this->‪getTypoScriptFrontendController()->id;
167  $pageIdsToClear[] = $storagePage;
168  }
169  if ($storagePage === null) {
170  return;
171  }
172 
173  $pageTS = BackendUtility::getPagesTSconfig($storagePage);
174  if (isset($pageTS['TCEMAIN.']['clearCacheCmd'])) {
175  $clearCacheCommands = GeneralUtility::trimExplode(',', strtolower((string)$pageTS['TCEMAIN.']['clearCacheCmd']), true);
176  $clearCacheCommands = array_unique($clearCacheCommands);
177  foreach ($clearCacheCommands as $clearCacheCommand) {
178  if (‪MathUtility::canBeInterpretedAsInteger($clearCacheCommand)) {
179  $pageIdsToClear[] = $clearCacheCommand;
180  }
181  }
182  }
183 
184  foreach ($pageIdsToClear as $pageIdToClear) {
185  $this->‪getPageIdStack()->push($pageIdToClear);
186  }
187  }
188 
190  {
191  return ‪$GLOBALS['TSFE'] ?? null;
192  }
193 }
‪TYPO3\CMS\Extbase\Service\CacheService\getTypoScriptFrontendController
‪getTypoScriptFrontendController()
Definition: CacheService.php:189
‪TYPO3\CMS\Extbase\Service\CacheService\$configurationManager
‪ConfigurationManagerInterface $configurationManager
Definition: CacheService.php:43
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:50
‪TYPO3\CMS\Extbase\Service\CacheService\__construct
‪__construct(ConfigurationManagerInterface $configurationManager, CacheManager $cacheManager)
Definition: CacheService.php:48
‪TYPO3\CMS\Extbase\Service\CacheService\clearCacheForRecord
‪clearCacheForRecord(string $table, int $uid)
Definition: CacheService.php:115
‪TYPO3\CMS\Extbase\Service\CacheService\$hasPidColumn
‪array $hasPidColumn
Definition: CacheService.php:41
‪TYPO3\CMS\Extbase\Service\CacheService\$cacheManager
‪CacheManager $cacheManager
Definition: CacheService.php:44
‪TYPO3\CMS\Extbase\Service\CacheService\clearPageCacheForGivenRecord
‪clearPageCacheForGivenRecord(string $tableName, int $uid)
Definition: CacheService.php:133
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
Definition: ConfigurationManagerInterface.php:28
‪TYPO3\CMS\Extbase\Service
Definition: CacheService.php:18
‪TYPO3\CMS\Extbase\Service\CacheService\$clearCacheForTables
‪array $clearCacheForTables
Definition: CacheService.php:42
‪TYPO3\CMS\Extbase\Service\CacheService\$connectionPool
‪ConnectionPool $connectionPool
Definition: CacheService.php:45
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface\CONFIGURATION_TYPE_FRAMEWORK
‪const CONFIGURATION_TYPE_FRAMEWORK
Definition: ConfigurationManagerInterface.php:29
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:69
‪TYPO3\CMS\Extbase\Service\CacheService\$pageIdStack
‪SplStack $pageIdStack
Definition: CacheService.php:46
‪TYPO3\CMS\Extbase\Service\CacheService\clearPageCache
‪clearPageCache($pageIdsToClear=null)
Definition: CacheService.php:66
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Extbase\Service\CacheService\clearCachesOfRegisteredPageIds
‪clearCachesOfRegisteredPageIds()
Definition: CacheService.php:86
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:39
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:103
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:22
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Extbase\Service\CacheService
Definition: CacheService.php:35
‪TYPO3\CMS\Extbase\Service\CacheService\getPageIdStack
‪getPageIdStack()
Definition: CacheService.php:56
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:48
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51