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