TYPO3 CMS  TYPO3_8-7
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 {
26  protected $dataSourceName;
27 
31  protected $username;
32 
36  protected $password;
37 
41  protected $databaseHandle;
42 
46  protected $pdoDriver;
47 
54  public function setDataSourceName($DSN)
55  {
56  $this->dataSourceName = $DSN;
57  }
58 
65  public function setUsername($username)
66  {
67  $this->username = $username;
68  }
69 
76  public function setPassword($password)
77  {
78  $this->password = $password;
79  }
80 
84  public function initializeObject()
85  {
86  $this->connect();
87  }
88 
101  public function set($entryIdentifier, $data, array $tags = [], $lifetime = null)
102  {
103  if (!$this->cache instanceof \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface) {
104  throw new \TYPO3\CMS\Core\Cache\Exception('No cache frontend has been set yet via setCache().', 1259515600);
105  }
106  if (!is_string($data)) {
107  throw new \TYPO3\CMS\Core\Cache\Exception\InvalidDataException('The specified data is of type "' . gettype($data) . '" but a string is expected.', 1259515601);
108  }
109  $this->remove($entryIdentifier);
110  $lifetime = $lifetime === null ? $this->defaultLifetime : $lifetime;
111  $statementHandle = $this->databaseHandle->prepare('INSERT INTO "cache" ("identifier", "context", "cache", "created", "lifetime", "content") VALUES (?, ?, ?, ?, ?, ?)');
112  $result = $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier, $GLOBALS['EXEC_TIME'], $lifetime, $data]);
113  if ($result === false) {
114  throw new \TYPO3\CMS\Core\Cache\Exception('The cache entry "' . $entryIdentifier . '" could not be written.', 1259530791);
115  }
116  $statementHandle = $this->databaseHandle->prepare('INSERT INTO "tags" ("identifier", "context", "cache", "tag") VALUES (?, ?, ?, ?)');
117  foreach ($tags as $tag) {
118  $result = $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier, $tag]);
119  if ($result === false) {
120  throw new \TYPO3\CMS\Core\Cache\Exception('The tag "' . $tag . ' for cache entry "' . $entryIdentifier . '" could not be written.', 1259530751);
121  }
122  }
123  }
124 
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 
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 
162  public function remove($entryIdentifier)
163  {
164  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "identifier"=? AND "context"=? AND "cache"=?');
165  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
166  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "identifier"=? AND "context"=? AND "cache"=?');
167  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
168  return $statementHandle->rowCount() > 0;
169  }
170 
176  public function flush()
177  {
178  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "context"=? AND "cache"=?');
179  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
180  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=?');
181  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
182  }
183 
190  public function flushByTag($tag)
191  {
192  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=? AND "identifier" IN (SELECT "identifier" FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?)');
193  $statementHandle->execute([$this->context, $this->cacheIdentifier, $this->context, $this->cacheIdentifier, $tag]);
194  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?');
195  $statementHandle->execute([$this->context, $this->cacheIdentifier, $tag]);
196  }
197 
206  public function findIdentifiersByTag($tag)
207  {
208  $statementHandle = $this->databaseHandle->prepare('SELECT "identifier" FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?');
209  $statementHandle->execute([$this->context, $this->cacheIdentifier, $tag]);
210  return $statementHandle->fetchAll(\PDO::FETCH_COLUMN);
211  }
212 
218  public function collectGarbage()
219  {
220  $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'] . ')');
221  $statementHandle->execute([$this->context, $this->cacheIdentifier, $this->context, $this->cacheIdentifier]);
222  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=? AND "lifetime" > 0 AND "created" + "lifetime" < ' . $GLOBALS['EXEC_TIME']);
223  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
224  }
225 
231  protected function getNotExpiredStatement()
232  {
233  return ' AND ("lifetime" = 0 OR "created" + "lifetime" >= ' . $GLOBALS['EXEC_TIME'] . ')';
234  }
235 
241  protected function connect()
242  {
243  try {
244  $splitdsn = explode(':', $this->dataSourceName, 2);
245  $this->pdoDriver = $splitdsn[0];
246  if ($this->pdoDriver === 'sqlite' && !file_exists($splitdsn[1])) {
247  $this->databaseHandle = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\PDO::class, $this->dataSourceName, $this->username, $this->password);
248  $this->createCacheTables();
249  } else {
250  $this->databaseHandle = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\PDO::class, $this->dataSourceName, $this->username, $this->password);
251  }
252  $this->databaseHandle->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
253  if (substr($this->pdoDriver, 0, 5) === 'mysql') {
254  $this->databaseHandle->exec('SET SESSION sql_mode=\'ANSI\';');
255  }
256  } catch (\PDOException $e) {
257  throw new \RuntimeException('Could not connect to cache table with DSN "' . $this->dataSourceName . '". PDO error: ' . $e->getMessage(), 1334736164);
258  }
259  }
260 
266  protected function createCacheTables()
267  {
268  try {
270  $this->databaseHandle,
271  $this->pdoDriver,
272  \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('core') .
273  'Resources/Private/Sql/Cache/Backend/PdoBackendCacheAndTags.sql'
274  );
275  } catch (\PDOException $e) {
276  throw new \RuntimeException('Could not create cache tables with DSN "' . $this->dataSourceName . '". PDO error: ' . $e->getMessage(), 1259576985);
277  }
278  }
279 }
static importSql(\PDO $databaseHandle, $pdoDriver, $pathAndFilename)
Definition: PdoHelper.php:34
static makeInstance($className,... $constructorArguments)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']