TYPO3 CMS  TYPO3_6-2
Typo3DatabaseBackend.php
Go to the documentation of this file.
1 <?php
3 
25 
29  const FAKED_UNLIMITED_EXPIRE = 2145909600;
33  protected $cacheTable;
34 
38  protected $tagsTable;
39 
43  protected $compression = FALSE;
44 
48  protected $compressionLevel = -1;
49 
53  protected $identifierField;
54 
58  protected $expiresField;
59 
63  protected $maximumLifetime;
64 
69 
73  protected $expiredStatement;
74 
78  protected $tableList;
79 
83  protected $tableJoin;
84 
92  public function setCache(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $cache) {
93  parent::setCache($cache);
94  $this->cacheTable = 'cf_' . $this->cacheIdentifier;
95  $this->tagsTable = 'cf_' . $this->cacheIdentifier . '_tags';
97  }
98 
104  protected function initializeCommonReferences() {
105  $this->identifierField = $this->cacheTable . '.identifier';
106  $this->expiresField = $this->cacheTable . '.expires';
107  $this->maximumLifetime = self::FAKED_UNLIMITED_EXPIRE - $GLOBALS['EXEC_TIME'];
108  $this->tableList = $this->cacheTable . ', ' . $this->tagsTable;
109  $this->tableJoin = $this->identifierField . ' = ' . $this->tagsTable . '.identifier';
110  $this->expiredStatement = $this->expiresField . ' < ' . $GLOBALS['EXEC_TIME'];
111  $this->notExpiredStatement = $this->expiresField . ' >= ' . $GLOBALS['EXEC_TIME'];
112  }
113 
125  public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
127  if (!is_string($data)) {
128  throw new \TYPO3\CMS\Core\Cache\Exception\InvalidDataException(
129  'The specified data is of type "' . gettype($data) . '" but a string is expected.',
130  1236518298
131  );
132  }
133  if (is_null($lifetime)) {
134  $lifetime = $this->defaultLifetime;
135  }
136  if ($lifetime === 0 || $lifetime > $this->maximumLifetime) {
137  $lifetime = $this->maximumLifetime;
138  }
139  $expires = $GLOBALS['EXEC_TIME'] + $lifetime;
140  $this->remove($entryIdentifier);
141  if ($this->compression) {
142  $data = gzcompress($data, $this->compressionLevel);
143  }
144  $GLOBALS['TYPO3_DB']->exec_INSERTquery($this->cacheTable, array(
145  'identifier' => $entryIdentifier,
146  'expires' => $expires,
147  'content' => $data
148  ));
149  if (count($tags)) {
150  $fields = array();
151  $fields[] = 'identifier';
152  $fields[] = 'tag';
153  $tagRows = array();
154  foreach ($tags as $tag) {
155  $tagRow = array();
156  $tagRow[] = $entryIdentifier;
157  $tagRow[] = $tag;
158  $tagRows[] = $tagRow;
159  }
160  $GLOBALS['TYPO3_DB']->exec_INSERTmultipleRows($this->tagsTable, $fields, $tagRows);
161  }
162  }
163 
170  public function get($entryIdentifier) {
172 
173  $cacheEntry = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
174  'content',
175  $this->cacheTable,
176  'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable) . ' AND ' . $this->notExpiredStatement
177  );
178  if (is_array($cacheEntry)) {
179  $cacheEntry = $cacheEntry['content'];
180  }
181  if ($this->compression && strlen($cacheEntry)) {
182  $cacheEntry = gzuncompress($cacheEntry);
183  }
184  return $cacheEntry !== NULL ? $cacheEntry : FALSE;
185  }
186 
193  public function has($entryIdentifier) {
195  $hasEntry = FALSE;
196  $cacheEntries = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
197  '*',
198  $this->cacheTable,
199  'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable) . ' AND ' . $this->notExpiredStatement
200  );
201  if ($cacheEntries >= 1) {
202  $hasEntry = TRUE;
203  }
204  return $hasEntry;
205  }
206 
214  public function remove($entryIdentifier) {
216  $entryRemoved = FALSE;
217  $GLOBALS['TYPO3_DB']->exec_DELETEquery(
218  $this->cacheTable,
219  'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable)
220  );
221  // we need to save the affected rows as mysqli_affected_rows just returns the amount of affected rows
222  // of the last call
223  $affectedRows = $GLOBALS['TYPO3_DB']->sql_affected_rows();
224  $GLOBALS['TYPO3_DB']->exec_DELETEquery(
225  $this->tagsTable,
226  'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->tagsTable)
227  );
228  if ($affectedRows == 1) {
229  $entryRemoved = TRUE;
230  }
231  return $entryRemoved;
232  }
233 
240  public function findIdentifiersByTag($tag) {
242  $cacheEntryIdentifiers = array();
243  $cacheEntryIdentifierRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
244  $this->identifierField,
245  $this->tableList,
246  $this->tagsTable . '.tag = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($tag, $this->tagsTable) . ' AND ' . $this->tableJoin . ' AND ' . $this->notExpiredStatement,
247  $this->identifierField
248  );
249  foreach ($cacheEntryIdentifierRows as $cacheEntryIdentifierRow) {
250  $cacheEntryIdentifiers[$cacheEntryIdentifierRow['identifier']] = $cacheEntryIdentifierRow['identifier'];
251  }
252  return $cacheEntryIdentifiers;
253  }
254 
260  public function flush() {
262  $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery($this->cacheTable);
263  $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery($this->tagsTable);
264  }
265 
272  public function flushByTag($tag) {
274 
275  if ($this->isConnectionMysql()) {
276  $GLOBALS['TYPO3_DB']->sql_query('
277  DELETE tags2, cache1'
278  . ' FROM ' . $this->tagsTable . ' AS tags1'
279  . ' JOIN ' . $this->tagsTable . ' AS tags2 ON tags1.identifier = tags2.identifier'
280  . ' JOIN ' . $this->cacheTable . ' AS cache1 ON tags1.identifier = cache1.identifier'
281  . ' WHERE tags1.tag = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($tag, $this->tagsTable)
282  );
283  } else {
284  $tagsTableWhereClause = $this->tagsTable . '.tag = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($tag, $this->tagsTable);
285  $cacheEntryIdentifierRowsResource = $GLOBALS['TYPO3_DB']->exec_SELECTquery('DISTINCT identifier', $this->tagsTable, $tagsTableWhereClause);
286  $cacheEntryIdentifiers = array();
287  while ($cacheEntryIdentifierRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($cacheEntryIdentifierRowsResource)) {
288  $cacheEntryIdentifiers[] = $GLOBALS['TYPO3_DB']->fullQuoteStr($cacheEntryIdentifierRow['identifier'], $this->cacheTable);
289  }
290  $GLOBALS['TYPO3_DB']->sql_free_result($cacheEntryIdentifierRowsResource);
291  if (!empty($cacheEntryIdentifiers)) {
292  $deleteWhereClause = 'identifier IN (' . implode(', ', $cacheEntryIdentifiers) . ')';
293  $GLOBALS['TYPO3_DB']->exec_DELETEquery($this->cacheTable, $deleteWhereClause);
294  $GLOBALS['TYPO3_DB']->exec_DELETEquery($this->tagsTable, $deleteWhereClause);
295  }
296  }
297  }
298 
304  public function collectGarbage() {
306 
307  if ($this->isConnectionMysql()) {
308  // First delete all expired rows from cache table and their connected tag rows
309  $GLOBALS['TYPO3_DB']->sql_query(
310  'DELETE cache, tags'
311  . ' FROM ' . $this->cacheTable . ' AS cache'
312  . ' LEFT OUTER JOIN ' . $this->tagsTable . ' AS tags ON cache.identifier = tags.identifier'
313  . ' WHERE cache.expires < ' . $GLOBALS['EXEC_TIME']
314  );
315  // Then delete possible "orphaned" rows from tags table - tags that have no cache row for whatever reason
316  $GLOBALS['TYPO3_DB']->sql_query(
317  'DELETE tags'
318  . ' FROM ' . $this->tagsTable . ' AS tags'
319  . ' LEFT OUTER JOIN ' . $this->cacheTable . ' AS cache ON tags.identifier = cache.identifier'
320  . ' WHERE cache.identifier IS NULL'
321  );
322  } else {
323  // Get identifiers of expired cache entries
324  $cacheEntryIdentifierRowsResource = $GLOBALS['TYPO3_DB']->exec_SELECTquery('DISTINCT identifier', $this->cacheTable, 'expires < ' . $GLOBALS['EXEC_TIME']);
325  $cacheEntryIdentifiers = array();
326  while ($cacheEntryIdentifierRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($cacheEntryIdentifierRowsResource)) {
327  $cacheEntryIdentifiers[] = $GLOBALS['TYPO3_DB']->fullQuoteStr($cacheEntryIdentifierRow['identifier'], $this->tagsTable);
328  }
329  $GLOBALS['TYPO3_DB']->sql_free_result($cacheEntryIdentifierRowsResource);
330  // Delete tag rows connected to expired cache entries
331  if (!empty($cacheEntryIdentifiers)) {
332  $GLOBALS['TYPO3_DB']->exec_DELETEquery($this->tagsTable, 'identifier IN (' . implode(', ', $cacheEntryIdentifiers) . ')');
333  }
334  // Delete expired cache rows
335  $GLOBALS['TYPO3_DB']->exec_DELETEquery($this->cacheTable, 'expires < ' . $GLOBALS['EXEC_TIME']);
336 
337  // Find out which "orphaned" tags rows exists that have no cache row and delete those, too.
338  $result = $GLOBALS['TYPO3_DB']->sql_query(
339  'SELECT tags.identifier'
340  . ' FROM ' . $this->tagsTable . ' AS tags'
341  . ' LEFT OUTER JOIN ' . $this->cacheTable . ' AS cache ON tags.identifier = cache.identifier'
342  . ' WHERE cache.identifier IS NULL'
343  . ' GROUP BY tags.identifier'
344  );
345 
346  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
347  $tagsEntryIdentifiers[] = $GLOBALS['TYPO3_DB']->fullQuoteStr($row['identifier'], $this->tagsTable);
348  }
349 
350  if (!empty($tagsEntryIdentifiers)) {
351  $GLOBALS['TYPO3_DB']->sql_query(
352  'DELETE'
353  . ' FROM ' . $this->tagsTable
354  . ' WHERE identifier IN (' . implode(',', $tagsEntryIdentifiers) . ')'
355  );
356  }
357  }
358  }
359 
365  public function getCacheTable() {
367  return $this->cacheTable;
368  }
369 
375  public function getTagsTable() {
377  return $this->tagsTable;
378  }
379 
385  public function setCompression($compression) {
386  $this->compression = $compression;
387  }
388 
397  if ($compressionLevel >= -1 && $compressionLevel <= 9) {
398  $this->compressionLevel = $compressionLevel;
399  }
400  }
401 
409  if (!$this->cache instanceof \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface) {
410  throw new \TYPO3\CMS\Core\Cache\Exception('No cache frontend has been set via setCache() yet.', 1236518288);
411  }
412  }
413 
421  public function getTableDefinitions() {
422  $cacheTableSql = file_get_contents(
423  \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('core') .
424  'Resources/Private/Sql/Cache/Backend/Typo3DatabaseBackendCache.sql'
425  );
426  $requiredTableStructures = str_replace('###CACHE_TABLE###', $this->cacheTable, $cacheTableSql) . LF . LF;
427  $tagsTableSql = file_get_contents(
428  \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('core') .
429  'Resources/Private/Sql/Cache/Backend/Typo3DatabaseBackendTags.sql'
430  );
431  $requiredTableStructures .= str_replace('###TAGS_TABLE###', $this->tagsTable, $tagsTableSql) . LF;
432  return $requiredTableStructures;
433  }
434 
441  protected function isConnectionMysql()
442  {
443  return !((bool)\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('dbal'));
444  }
445 }
setCache(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $cache)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]