‪TYPO3CMS  11.5
PdoBackend.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
23 
31 {
35  protected ‪$dataSourceName;
36 
40  protected ‪$username;
41 
45  protected ‪$password;
46 
50  protected ‪$databaseHandle;
51 
55  protected ‪$pdoDriver;
56 
57  public function ‪__construct(‪$context, array $options = [])
58  {
59  trigger_error(__CLASS__ . ' will be removed in TYPO3 v12, use Typo3DatabaseBackend instead.', E_USER_DEPRECATED);
60  parent::__construct(‪$context, $options);
61  }
62 
68  public function ‪setDataSourceName($DSN)
69  {
70  $this->dataSourceName = $DSN;
71  }
72 
78  public function ‪setUsername(‪$username)
79  {
80  $this->username = ‪$username;
81  }
82 
88  public function ‪setPassword(‪$password)
89  {
90  $this->password = ‪$password;
91  }
92 
96  public function ‪initializeObject()
97  {
98  $this->‪connect();
99  }
100 
112  public function set($entryIdentifier, $data, array $tags = [], $lifetime = null)
113  {
114  if (!$this->cache instanceof ‪FrontendInterface) {
115  throw new ‪Exception('No cache frontend has been set yet via setCache().', 1259515600);
116  }
117  if (!is_string($data)) {
118  throw new InvalidDataException('The specified data is of type "' . gettype($data) . '" but a string is expected.', 1259515601);
119  }
120  $this->remove($entryIdentifier);
121  $lifetime = $lifetime ?? ‪$this->defaultLifetime;
122  $statementHandle = $this->databaseHandle->prepare('INSERT INTO "cache" ("identifier", "context", "cache", "created", "lifetime", "content") VALUES (?, ?, ?, ?, ?, ?)');
123  $result = $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier, ‪$GLOBALS['EXEC_TIME'], $lifetime, $data]);
124  if ($result === false) {
125  throw new Exception('The cache entry "' . $entryIdentifier . '" could not be written.', 1259530791);
126  }
127  $statementHandle = $this->databaseHandle->prepare('INSERT INTO "tags" ("identifier", "context", "cache", "tag") VALUES (?, ?, ?, ?)');
128  foreach ($tags as $tag) {
129  $result = $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier, $tag]);
130  if ($result === false) {
131  throw new Exception('The tag "' . $tag . ' for cache entry "' . $entryIdentifier . '" could not be written.', 1259530751);
132  }
133  }
134  }
135 
142  public function get($entryIdentifier)
143  {
144  $statementHandle = $this->databaseHandle->prepare('SELECT "content" FROM "cache" WHERE "identifier"=? AND "context"=? AND "cache"=?' . $this->‪getNotExpiredStatement());
145  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
146  return $statementHandle->fetchColumn();
147  }
148 
155  public function ‪has($entryIdentifier)
156  {
157  $statementHandle = $this->databaseHandle->prepare('SELECT COUNT("identifier") FROM "cache" WHERE "identifier"=? AND "context"=? AND "cache"=?' . $this->‪getNotExpiredStatement());
158  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
159  return $statementHandle->fetchColumn() > 0;
160  }
161 
170  public function remove($entryIdentifier)
171  {
172  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "identifier"=? AND "context"=? AND "cache"=?');
173  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
174  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "identifier"=? AND "context"=? AND "cache"=?');
175  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
176  return $statementHandle->rowCount() > 0;
177  }
178 
182  public function ‪flush()
183  {
184  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "context"=? AND "cache"=?');
185  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
186  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=?');
187  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
188  }
189 
195  public function ‪flushByTag($tag)
196  {
197  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=? AND "identifier" IN (SELECT "identifier" FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?)');
198  $statementHandle->execute([$this->context, $this->cacheIdentifier, $this->context, $this->cacheIdentifier, $tag]);
199  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?');
200  $statementHandle->execute([$this->context, $this->cacheIdentifier, $tag]);
201  }
202 
210  public function ‪findIdentifiersByTag($tag)
211  {
212  $statementHandle = $this->databaseHandle->prepare('SELECT "identifier" FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?');
213  $statementHandle->execute([$this->context, $this->cacheIdentifier, $tag]);
214  return $statementHandle->fetchAll(\PDO::FETCH_COLUMN);
215  }
216 
220  public function ‪collectGarbage()
221  {
222  $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'] . ')');
223  $statementHandle->execute([$this->context, $this->cacheIdentifier, $this->context, $this->cacheIdentifier]);
224  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=? AND "lifetime" > 0 AND "created" + "lifetime" < ' . ‪$GLOBALS['EXEC_TIME']);
225  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
226  }
227 
233  protected function ‪getNotExpiredStatement()
234  {
235  return ' AND ("lifetime" = 0 OR "created" + "lifetime" >= ' . ‪$GLOBALS['EXEC_TIME'] . ')';
236  }
237 
243  protected function ‪connect()
244  {
245  try {
246  $splitdsn = explode(':', $this->dataSourceName, 2);
247  $this->pdoDriver = $splitdsn[0];
248  if ($this->pdoDriver === 'sqlite' && !file_exists($splitdsn[1])) {
249  $this->databaseHandle = GeneralUtility::makeInstance(\PDO::class, $this->dataSourceName, $this->username, $this->password);
250  $this->‪createCacheTables();
251  } else {
252  $this->databaseHandle = GeneralUtility::makeInstance(\PDO::class, $this->dataSourceName, $this->username, $this->password);
253  }
254  $this->databaseHandle->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
255  if (strpos($this->pdoDriver, 'mysql') === 0) {
256  $this->databaseHandle->exec('SET SESSION sql_mode=\'ANSI\';');
257  }
258  } catch (\PDOException $e) {
259  throw new \RuntimeException('Could not connect to cache table with DSN "' . $this->dataSourceName . '". PDO error: ' . $e->getMessage(), 1334736164);
260  }
261  }
262 
268  protected function ‪createCacheTables()
269  {
270  try {
271  $this->‪importSql(
272  $this->databaseHandle,
273  $this->pdoDriver,
275  'Resources/Private/Sql/Cache/Backend/PdoBackendCacheAndTags.sql'
276  );
277  } catch (\PDOException $e) {
278  throw new \RuntimeException('Could not create cache tables with DSN "' . $this->dataSourceName . '". PDO error: ' . $e->getMessage(), 1259576985);
279  }
280  }
281 
293  protected function ‪importSql(\PDO ‪$databaseHandle, string ‪$pdoDriver, string $pathAndFilename): void
294  {
295  $sql = file($pathAndFilename, FILE_IGNORE_NEW_LINES & FILE_SKIP_EMPTY_LINES);
296  if ($sql === false) {
297  throw new \RuntimeException('Error while reading file "' . $pathAndFilename . '".', 1601021306);
298  }
299  // Remove MySQL style key length delimiters (yuck!) if we are not setting up a MySQL db
300  if (strpos(‪$pdoDriver, 'mysql') !== 0) {
301  $sql = preg_replace('/"\\([0-9]+\\)/', '"', $sql);
302  }
303  $statement = '';
304  foreach ($sql as $line) {
305  $statement .= ' ' . trim($line);
306  if (substr($statement, -1) === ';') {
307  ‪$databaseHandle->exec($statement);
308  $statement = '';
309  }
310  }
311  }
312 }
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\has
‪bool has($entryIdentifier)
Definition: PdoBackend.php:150
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\importSql
‪importSql(\PDO $databaseHandle, string $pdoDriver, string $pathAndFilename)
Definition: PdoBackend.php:288
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\flush
‪flush()
Definition: PdoBackend.php:177
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\$pdoDriver
‪string $pdoDriver
Definition: PdoBackend.php:50
‪TYPO3\CMS\Core\Cache\Backend\TaggableBackendInterface
Definition: TaggableBackendInterface.php:22
‪TYPO3\CMS\Core\Cache\Backend\AbstractBackend\$defaultLifetime
‪int $defaultLifetime
Definition: AbstractBackend.php:57
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\setDataSourceName
‪setDataSourceName($DSN)
Definition: PdoBackend.php:63
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:43
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\$username
‪string $username
Definition: PdoBackend.php:38
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\$password
‪string $password
Definition: PdoBackend.php:42
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\__construct
‪__construct($context, array $options=[])
Definition: PdoBackend.php:52
‪TYPO3\CMS\Core\Cache\Exception
Definition: DuplicateIdentifierException.php:16
‪TYPO3\CMS\Core\Cache\Exception\InvalidDataException
Definition: InvalidDataException.php:23
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\$dataSourceName
‪string $dataSourceName
Definition: PdoBackend.php:34
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\initializeObject
‪initializeObject()
Definition: PdoBackend.php:91
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\createCacheTables
‪createCacheTables()
Definition: PdoBackend.php:263
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\collectGarbage
‪collectGarbage()
Definition: PdoBackend.php:215
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\getNotExpiredStatement
‪string getNotExpiredStatement()
Definition: PdoBackend.php:228
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend
Definition: PdoBackend.php:31
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\flushByTag
‪flushByTag($tag)
Definition: PdoBackend.php:190
‪TYPO3\CMS\Core\Cache\Backend\AbstractBackend
Definition: AbstractBackend.php:28
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\findIdentifiersByTag
‪array findIdentifiersByTag($tag)
Definition: PdoBackend.php:205
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\setUsername
‪setUsername($username)
Definition: PdoBackend.php:73
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static string extPath($key, $script='')
Definition: ExtensionManagementUtility.php:142
‪TYPO3\CMS\Core\Cache\Backend
Definition: AbstractBackend.php:16
‪TYPO3\CMS\Core\Cache\Backend\AbstractBackend\$context
‪string $context
Definition: AbstractBackend.php:51
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\$databaseHandle
‪PDO $databaseHandle
Definition: PdoBackend.php:46
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\connect
‪connect()
Definition: PdoBackend.php:238
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Core\Cache\Backend\PdoBackend\setPassword
‪setPassword($password)
Definition: PdoBackend.php:83
‪TYPO3\CMS\Core\Cache\Exception
Definition: Exception.php:21