TYPO3 CMS  TYPO3_7-6
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 
55  public function setDataSourceName($DSN)
56  {
57  $this->dataSourceName = $DSN;
58  }
59 
67  public function setUsername($username)
68  {
69  $this->username = $username;
70  }
71 
79  public function setPassword($password)
80  {
81  $this->password = $password;
82  }
83 
89  public function initializeObject()
90  {
91  $this->connect();
92  }
93 
107  public function set($entryIdentifier, $data, array $tags = [], $lifetime = null)
108  {
109  if (!$this->cache instanceof \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface) {
110  throw new \TYPO3\CMS\Core\Cache\Exception('No cache frontend has been set yet via setCache().', 1259515600);
111  }
112  if (!is_string($data)) {
113  throw new \TYPO3\CMS\Core\Cache\Exception\InvalidDataException('The specified data is of type "' . gettype($data) . '" but a string is expected.', 1259515601);
114  }
115  $this->remove($entryIdentifier);
116  $lifetime = $lifetime === null ? $this->defaultLifetime : $lifetime;
117  $statementHandle = $this->databaseHandle->prepare('INSERT INTO "cache" ("identifier", "context", "cache", "created", "lifetime", "content") VALUES (?, ?, ?, ?, ?, ?)');
118  $result = $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier, $GLOBALS['EXEC_TIME'], $lifetime, $data]);
119  if ($result === false) {
120  throw new \TYPO3\CMS\Core\Cache\Exception('The cache entry "' . $entryIdentifier . '" could not be written.', 1259530791);
121  }
122  $statementHandle = $this->databaseHandle->prepare('INSERT INTO "tags" ("identifier", "context", "cache", "tag") VALUES (?, ?, ?, ?)');
123  foreach ($tags as $tag) {
124  $result = $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier, $tag]);
125  if ($result === false) {
126  throw new \TYPO3\CMS\Core\Cache\Exception('The tag "' . $tag . ' for cache entry "' . $entryIdentifier . '" could not be written.', 1259530751);
127  }
128  }
129  }
130 
138  public function get($entryIdentifier)
139  {
140  $statementHandle = $this->databaseHandle->prepare('SELECT "content" FROM "cache" WHERE "identifier"=? AND "context"=? AND "cache"=?' . $this->getNotExpiredStatement());
141  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
142  return $statementHandle->fetchColumn();
143  }
144 
152  public function has($entryIdentifier)
153  {
154  $statementHandle = $this->databaseHandle->prepare('SELECT COUNT("identifier") FROM "cache" WHERE "identifier"=? AND "context"=? AND "cache"=?' . $this->getNotExpiredStatement());
155  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
156  return $statementHandle->fetchColumn() > 0;
157  }
158 
168  public function remove($entryIdentifier)
169  {
170  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "identifier"=? AND "context"=? AND "cache"=?');
171  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
172  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "identifier"=? AND "context"=? AND "cache"=?');
173  $statementHandle->execute([$entryIdentifier, $this->context, $this->cacheIdentifier]);
174  return $statementHandle->rowCount() > 0;
175  }
176 
183  public function flush()
184  {
185  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "context"=? AND "cache"=?');
186  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
187  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=?');
188  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
189  }
190 
198  public function flushByTag($tag)
199  {
200  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=? AND "identifier" IN (SELECT "identifier" FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?)');
201  $statementHandle->execute([$this->context, $this->cacheIdentifier, $this->context, $this->cacheIdentifier, $tag]);
202  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?');
203  $statementHandle->execute([$this->context, $this->cacheIdentifier, $tag]);
204  }
205 
214  public function findIdentifiersByTag($tag)
215  {
216  $statementHandle = $this->databaseHandle->prepare('SELECT "identifier" FROM "tags" WHERE "context"=? AND "cache"=? AND "tag"=?');
217  $statementHandle->execute([$this->context, $this->cacheIdentifier, $tag]);
218  return $statementHandle->fetchAll(\PDO::FETCH_COLUMN);
219  }
220 
227  public function collectGarbage()
228  {
229  $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'] . ')');
230  $statementHandle->execute([$this->context, $this->cacheIdentifier, $this->context, $this->cacheIdentifier]);
231  $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "context"=? AND "cache"=? AND "lifetime" > 0 AND "created" + "lifetime" < ' . $GLOBALS['EXEC_TIME']);
232  $statementHandle->execute([$this->context, $this->cacheIdentifier]);
233  }
234 
240  protected function getNotExpiredStatement()
241  {
242  return ' AND ("lifetime" = 0 OR "created" + "lifetime" >= ' . $GLOBALS['EXEC_TIME'] . ')';
243  }
244 
251  protected function connect()
252  {
253  try {
254  $splitdsn = explode(':', $this->dataSourceName, 2);
255  $this->pdoDriver = $splitdsn[0];
256  if ($this->pdoDriver === 'sqlite' && !file_exists($splitdsn[1])) {
257  $this->databaseHandle = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\PDO::class, $this->dataSourceName, $this->username, $this->password);
258  $this->createCacheTables();
259  } else {
260  $this->databaseHandle = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\PDO::class, $this->dataSourceName, $this->username, $this->password);
261  }
262  $this->databaseHandle->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
263  if (substr($this->pdoDriver, 0, 5) === 'mysql') {
264  $this->databaseHandle->exec('SET SESSION sql_mode=\'ANSI\';');
265  }
266  } catch (\PDOException $e) {
267  throw new \RuntimeException('Could not connect to cache table with DSN "' . $this->dataSourceName . '". PDO error: ' . $e->getMessage(), 1334736164);
268  }
269  }
270 
277  protected function createCacheTables()
278  {
279  try {
281  $this->databaseHandle,
282  $this->pdoDriver,
283  \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('core') .
284  'Resources/Private/Sql/Cache/Backend/PdoBackendCacheAndTags.sql'
285  );
286  } catch (\PDOException $e) {
287  throw new \RuntimeException('Could not create cache tables with DSN "' . $this->dataSourceName . '". PDO error: ' . $e->getMessage(), 1259576985);
288  }
289  }
290 }
static importSql(\PDO $databaseHandle, $pdoDriver, $pathAndFilename)
Definition: PdoHelper.php:35
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']