‪TYPO3CMS  9.5
PdoBackend.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 
22 
27 {
31  protected ‪$dataSourceName;
32 
36  protected ‪$username;
37 
41  protected ‪$password;
42 
46  protected ‪$databaseHandle;
47 
51  protected ‪$pdoDriver;
52 
58  public function ‪setDataSourceName($DSN)
59  {
60  $this->dataSourceName = $DSN;
61  }
62 
68  public function ‪setUsername(‪$username)
69  {
70  $this->username = ‪$username;
71  }
72 
78  public function ‪setPassword(‪$password)
79  {
80  $this->password = ‪$password;
81  }
82 
86  public function ‪initializeObject()
87  {
88  $this->‪connect();
89  }
90 
102  public function set($entryIdentifier, $data, array $tags = [], $lifetime = null)
103  {
104  if (!$this->cache instanceof ‪FrontendInterface) {
105  throw new ‪Exception('No cache frontend has been set yet via setCache().', 1259515600);
106  }
107  if (!is_string($data)) {
108  throw new InvalidDataException('The specified data is of type "' . gettype($data) . '" but a string is expected.', 1259515601);
109  }
110  $this->remove($entryIdentifier);
111  $lifetime = $lifetime ?? ‪$this->defaultLifetime;
112  $statementHandle = $this->databaseHandle->prepare('INSERT INTO "cache" ("identifier", "context", "cache", "created", "lifetime", "content") VALUES (?, ?, ?, ?, ?, ?)');
113  $result = $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier, ‪$GLOBALS['EXEC_TIME'], $lifetime, $data]);
114  if ($result === false) {
115  throw new Exception('The cache entry "' . $entryIdentifier . '" could not be written.', 1259530791);
116  }
117  $statementHandle = $this->databaseHandle->prepare('INSERT INTO "tags" ("identifier", "context", "cache", "tag") VALUES (?, ?, ?, ?)');
118  foreach ($tags as $tag) {
119  $result = $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier, $tag]);
120  if ($result === false) {
121  throw new Exception('The tag "' . $tag . ' for cache entry "' . $entryIdentifier . '" could not be written.', 1259530751);
122  }
123  }
124  }
125 
132  public function get($entryIdentifier)
133  {
134  $statementHandle = $this->databaseHandle->prepare('SELECT "content" FROM "cache" WHERE "identifier"=? AND "context"=? AND "cache"=?' . $this->‪getNotExpiredStatement());
135  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
136  return $statementHandle->fetchColumn();
137  }
138 
145  public function ‪has($entryIdentifier)
146  {
147  $statementHandle = $this->databaseHandle->prepare('SELECT COUNT("identifier") FROM "cache" WHERE "identifier"=? AND "context"=? AND "cache"=?' . $this->‪getNotExpiredStatement());
148  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
149  return $statementHandle->fetchColumn() > 0;
150  }
151 
160  public function remove($entryIdentifier)
161  {
162  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "identifier"=? AND "context"=? AND "cache"=?');
163  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
164  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "identifier"=? AND "context"=? AND "cache"=?');
165  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
166  return $statementHandle->rowCount() > 0;
167  }
168 
172  public function ‪flush()
173  {
174  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "context"=? AND "cache"=?');
175  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
176  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=?');
177  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
178  }
179 
185  public function ‪flushByTag($tag)
186  {
187  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=? AND "identifier" IN (SELECT "identifier" FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?)');
188  $statementHandle->execute([$this->context, $this->cacheIdentifier, $this->context, $this->cacheIdentifier, $tag]);
189  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?');
190  $statementHandle->execute([$this->context, $this->cacheIdentifier, $tag]);
191  }
192 
200  public function ‪findIdentifiersByTag($tag)
201  {
202  $statementHandle = $this->databaseHandle->prepare('SELECT "identifier" FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?');
203  $statementHandle->execute([$this->context, $this->cacheIdentifier, $tag]);
204  return $statementHandle->fetchAll(\PDO::FETCH_COLUMN);
205  }
206 
210  public function ‪collectGarbage()
211  {
212  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "context"=? AND "cache"=? AND "identifier" IN ' . '(SELECT "identifier" FROM "cache" WHERE "context"=? AND "cache"=? AND "lifetime" > 0 AND "created" + "lifetime" < ' . ‪$GLOBALS['EXEC_TIME'] . ')');
213  $statementHandle->execute([$this->context, $this->cacheIdentifier, $this->context, $this->cacheIdentifier]);
214  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=? AND "lifetime" > 0 AND "created" + "lifetime" < ' . ‪$GLOBALS['EXEC_TIME']);
215  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
216  }
217 
223  protected function ‪getNotExpiredStatement()
224  {
225  return ' AND ("lifetime" = 0 OR "created" + "lifetime" >= ' . ‪$GLOBALS['EXEC_TIME'] . ')';
226  }
227 
233  protected function ‪connect()
234  {
235  try {
236  $splitdsn = explode(':', $this->dataSourceName, 2);
237  $this->pdoDriver = $splitdsn[0];
238  if ($this->pdoDriver === 'sqlite' && !file_exists($splitdsn[1])) {
239  $this->databaseHandle = GeneralUtility::makeInstance(\PDO::class, $this->dataSourceName, $this->username, $this->password);
240  $this->‪createCacheTables();
241  } else {
242  $this->databaseHandle = GeneralUtility::makeInstance(\PDO::class, $this->dataSourceName, $this->username, $this->password);
243  }
244  $this->databaseHandle->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
245  if (strpos($this->pdoDriver, 'mysql') === 0) {
246  $this->databaseHandle->exec('SET SESSION sql_mode=\'ANSI\';');
247  }
248  } catch (\PDOException $e) {
249  throw new \RuntimeException('Could not connect to cache table with DSN "' . $this->dataSourceName . '". PDO error: ' . $e->getMessage(), 1334736164);
250  }
251  }
252 
258  protected function ‪createCacheTables()
259  {
260  try {
261  $this->‪importSql(
262  $this->databaseHandle,
263  $this->pdoDriver,
265  'Resources/Private/Sql/Cache/Backend/PdoBackendCacheAndTags.sql'
266  );
267  } catch (\PDOException $e) {
268  throw new \RuntimeException('Could not create cache tables with DSN "' . $this->dataSourceName . '". PDO error: ' . $e->getMessage(), 1259576985);
269  }
270  }
271 
283  protected function ‪importSql(\PDO ‪$databaseHandle, string ‪$pdoDriver, string $pathAndFilename): void
284  {
285  $sql = file($pathAndFilename, FILE_IGNORE_NEW_LINES & FILE_SKIP_EMPTY_LINES);
286  // Remove MySQL style key length delimiters (yuck!) if we are not setting up a MySQL db
287  if (strpos(‪$pdoDriver, 'mysql') !== 0) {
288  $sql = preg_replace('/"\\([0-9]+\\)/', '"', $sql);
289  }
290  $statement = '';
291  foreach ($sql as $line) {
292  $statement .= ' ' . trim($line);
293  if (substr($statement, -1) === ';') {
294  ‪$databaseHandle->exec($statement);
295  $statement = '';
296  }
297  }
298  }
299 }
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\has
‪bool has($entryIdentifier)
Definition: PdoBackend.php:140
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\importSql
‪importSql(\PDO $databaseHandle, string $pdoDriver, string $pathAndFilename)
Definition: PdoBackend.php:278
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\flush
‪flush()
Definition: PdoBackend.php:167
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\$pdoDriver
‪string $pdoDriver
Definition: PdoBackend.php:46
‪TYPO3\CMS\Core\Cache\Backend\TaggableBackendInterface
Definition: TaggableBackendInterface.php:21
‪TYPO3\CMS\Core\Cache\Backend\AbstractBackend\$defaultLifetime
‪int $defaultLifetime
Definition: AbstractBackend.php:54
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\setDataSourceName
‪setDataSourceName($DSN)
Definition: PdoBackend.php:53
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:36
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\$username
‪string $username
Definition: PdoBackend.php:34
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\$password
‪string $password
Definition: PdoBackend.php:38
‪TYPO3\CMS\Core\Cache\Exception
Definition: DuplicateIdentifierException.php:2
‪TYPO3\CMS\Core\Cache\Exception\InvalidDataException
Definition: InvalidDataException.php:21
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\$dataSourceName
‪string $dataSourceName
Definition: PdoBackend.php:30
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\initializeObject
‪initializeObject()
Definition: PdoBackend.php:81
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\createCacheTables
‪createCacheTables()
Definition: PdoBackend.php:253
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\collectGarbage
‪collectGarbage()
Definition: PdoBackend.php:205
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:21
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\getNotExpiredStatement
‪string getNotExpiredStatement()
Definition: PdoBackend.php:218
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend
Definition: PdoBackend.php:27
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\flushByTag
‪flushByTag($tag)
Definition: PdoBackend.php:180
‪TYPO3\CMS\Core\Cache\Backend\AbstractBackend
Definition: AbstractBackend.php:26
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\findIdentifiersByTag
‪array findIdentifiersByTag($tag)
Definition: PdoBackend.php:195
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\setUsername
‪setUsername($username)
Definition: PdoBackend.php:63
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static string extPath($key, $script='')
Definition: ExtensionManagementUtility.php:149
‪TYPO3\CMS\Core\Cache\Backend
Definition: AbstractBackend.php:2
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\$databaseHandle
‪PDO $databaseHandle
Definition: PdoBackend.php:42
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\connect
‪connect()
Definition: PdoBackend.php:228
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\setPassword
‪setPassword($password)
Definition: PdoBackend.php:73
‪TYPO3\CMS\Core\Cache\Exception
Definition: Exception.php:21