|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2008-2011 Ingo Renner <ingo@typo3.org> 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * 00017 * This script is distributed in the hope that it will be useful, 00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 * GNU General Public License for more details. 00021 * 00022 * This copyright notice MUST APPEAR in all copies of the script! 00023 ***************************************************************/ 00024 00025 00026 /** 00027 * A caching backend which stores cache entries in database tables 00028 * 00029 * @package TYPO3 00030 * @subpackage t3lib_cache 00031 * @api 00032 * @version $Id: class.t3lib_cache_backend_dbbackend.php 10128 2011-01-18 21:56:30Z lolli $ 00033 */ 00034 class t3lib_cache_backend_DbBackend extends t3lib_cache_backend_AbstractBackend { 00035 00036 protected $cacheTable; 00037 protected $tagsTable; 00038 00039 /** 00040 * @var boolean Indicates wether data is compressed or not (requires php zlib) 00041 */ 00042 protected $compression = FALSE; 00043 00044 /** 00045 * @var integer -1 to 9, indicates zlib compression level: -1 = default level 6, 0 = no compression, 9 maximum compression 00046 */ 00047 protected $compressionLevel = -1; 00048 00049 protected $identifierField; 00050 protected $creationField; 00051 protected $lifetimeField; 00052 protected $notExpiredStatement; 00053 protected $tableList; 00054 protected $tableJoin; 00055 00056 /** 00057 * Constructs this backend 00058 * 00059 * @param array $options Configuration options - depends on the actual backend 00060 */ 00061 public function __construct(array $options = array()) { 00062 parent::__construct($options); 00063 00064 if (!$this->cacheTable) { 00065 throw new t3lib_cache_Exception( 00066 'No table to write data to has been set using the setting "cacheTable".', 00067 1253534136 00068 ); 00069 } 00070 00071 if (!$this->tagsTable) { 00072 throw new t3lib_cache_Exception( 00073 'No table to write tags to has been set using the setting "tagsTable".', 00074 1253534137 00075 ); 00076 } 00077 00078 $this->initializeCommonReferences(); 00079 } 00080 00081 /** 00082 * Initializes common references used in this backend. 00083 * 00084 * @return void 00085 */ 00086 protected function initializeCommonReferences() { 00087 $this->identifierField = $this->cacheTable . '.identifier'; 00088 $this->creationField = $this->cacheTable . '.crdate'; 00089 $this->lifetimeField = $this->cacheTable . '.lifetime'; 00090 $this->tableList = $this->cacheTable . ', ' . $this->tagsTable; 00091 $this->tableJoin = $this->identifierField . ' = ' . $this->tagsTable . '.identifier'; 00092 $this->notExpiredStatement = '(' . $this->creationField . ' + ' . $this->lifetimeField . 00093 ' >= ' . $GLOBALS['EXEC_TIME'] . ' OR ' . $this->lifetimeField . ' = 0)'; 00094 } 00095 00096 /** 00097 * Saves data in a cache file. 00098 * 00099 * @param string An identifier for this specific cache entry 00100 * @param string The data to be stored 00101 * @param array Tags to associate with this cache entry 00102 * @param integer Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited liftime. 00103 * @return void 00104 * @throws t3lib_cache_Exception if no cache frontend has been set. 00105 * @throws t3lib_cache_exception_InvalidData if the data to be stored is not a string. 00106 * @author Ingo Renner <ingo@typo3.org> 00107 */ 00108 public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) { 00109 if (!$this->cache instanceof t3lib_cache_frontend_Frontend) { 00110 throw new t3lib_cache_Exception( 00111 'No cache frontend has been set via setCache() yet.', 00112 1236518288 00113 ); 00114 } 00115 00116 if (!is_string($data)) { 00117 throw new t3lib_cache_exception_InvalidData( 00118 'The specified data is of type "' . gettype($data) . '" but a string is expected.', 00119 1236518298 00120 ); 00121 } 00122 00123 if (is_null($lifetime)) { 00124 $lifetime = $this->defaultLifetime; 00125 } 00126 00127 $this->remove($entryIdentifier); 00128 00129 if ($this->compression) { 00130 $data = gzcompress($data, $this->compressionLevel); 00131 } 00132 00133 $GLOBALS['TYPO3_DB']->exec_INSERTquery( 00134 $this->cacheTable, 00135 array( 00136 'identifier' => $entryIdentifier, 00137 'crdate' => $GLOBALS['EXEC_TIME'], 00138 'content' => $data, 00139 'lifetime' => $lifetime 00140 ) 00141 ); 00142 00143 if (count($tags)) { 00144 $fields = array(); 00145 $fields[] = 'identifier'; 00146 $fields[] = 'tag'; 00147 00148 $tagRows = array(); 00149 foreach ($tags as $tag) { 00150 $tagRow = array(); 00151 $tagRow[] = $entryIdentifier; 00152 $tagRow[] = $tag; 00153 $tagRows[] = $tagRow; 00154 } 00155 00156 $GLOBALS['TYPO3_DB']->exec_INSERTmultipleRows( 00157 $this->tagsTable, 00158 $fields, 00159 $tagRows 00160 ); 00161 } 00162 } 00163 00164 /** 00165 * Loads data from a cache file. 00166 * 00167 * @param string An identifier which describes the cache entry to load 00168 * @return mixed The cache entry's data as a string or FALSE if the cache entry could not be loaded 00169 * @author Ingo Renner <ingo@typo3.org> 00170 */ 00171 public function get($entryIdentifier) { 00172 $cacheEntry = false; 00173 00174 $cacheEntry = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow( 00175 'content', 00176 $this->cacheTable, 00177 'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable) . ' ' 00178 . 'AND (crdate + lifetime >= ' . $GLOBALS['EXEC_TIME'] . ' OR lifetime = 0)' 00179 ); 00180 00181 if (is_array($cacheEntry)) { 00182 $cacheEntry = $cacheEntry['content']; 00183 } 00184 00185 if ($this->compression && strlen($cacheEntry)) { 00186 $cacheEntry = gzuncompress($cacheEntry); 00187 } 00188 00189 return $cacheEntry; 00190 } 00191 00192 /** 00193 * Checks if a cache entry with the specified identifier exists. 00194 * 00195 * @param string Specifies the identifier to check for existence 00196 * @return boolean TRUE if such an entry exists, FALSE if not 00197 * @author Ingo Renner <ingo@typo3.org> 00198 */ 00199 public function has($entryIdentifier) { 00200 $hasEntry = FALSE; 00201 00202 $cacheEntries = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows( 00203 '*', 00204 $this->cacheTable, 00205 'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable) . 00206 ' AND (crdate + lifetime >= ' . $GLOBALS['EXEC_TIME'] . ' OR lifetime = 0)' 00207 ); 00208 if ($cacheEntries >= 1) { 00209 $hasEntry = TRUE; 00210 } 00211 00212 return $hasEntry; 00213 } 00214 00215 /** 00216 * Removes all cache entries matching the specified identifier. 00217 * Usually this only affects one entry. 00218 * 00219 * @param string Specifies the cache entry to remove 00220 * @return boolean TRUE if (at least) an entry could be removed or FALSE if no entry was found 00221 * @author Ingo Renner <ingo@typo3.org> 00222 */ 00223 public function remove($entryIdentifier) { 00224 $entryRemoved = false; 00225 00226 $res = $GLOBALS['TYPO3_DB']->exec_DELETEquery( 00227 $this->cacheTable, 00228 'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable) 00229 ); 00230 00231 $GLOBALS['TYPO3_DB']->exec_DELETEquery( 00232 $this->tagsTable, 00233 'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->tagsTable) 00234 ); 00235 00236 if ($GLOBALS['TYPO3_DB']->sql_affected_rows($res) == 1) { 00237 $entryRemoved = true; 00238 } 00239 00240 return $entryRemoved; 00241 } 00242 00243 /** 00244 * Finds and returns all cache entries which are tagged by the specified tag. 00245 * 00246 * @param string The tag to search for 00247 * @return array An array with identifiers of all matching entries. An empty array if no entries matched 00248 * @author Ingo Renner <ingo@typo3.org> 00249 */ 00250 public function findIdentifiersByTag($tag) { 00251 $cacheEntryIdentifiers = array(); 00252 00253 $cacheEntryIdentifierRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( 00254 $this->identifierField, 00255 $this->tableList, 00256 $this->getQueryForTag($tag) . 00257 ' AND ' . $this->tableJoin . 00258 ' AND ' . $this->notExpiredStatement, 00259 $this->identifierField 00260 ); 00261 00262 foreach ($cacheEntryIdentifierRows as $cacheEntryIdentifierRow) { 00263 $cacheEntryIdentifiers[$cacheEntryIdentifierRow['identifier']] = $cacheEntryIdentifierRow['identifier']; 00264 } 00265 00266 return $cacheEntryIdentifiers; 00267 } 00268 00269 /** 00270 * Finds and returns all cache entry identifiers which are tagged by the 00271 * specified tags. 00272 * 00273 * @param array Array of tags to search for 00274 * @return array An array with identifiers of all matching entries. An empty array if no entries matched 00275 * @author Ingo Renner <ingo@typo3.org> 00276 */ 00277 public function findIdentifiersByTags(array $tags) { 00278 $cacheEntryIdentifiers = array(); 00279 $whereClause = array(); 00280 00281 foreach ($tags as $tag) { 00282 $whereClause[] = $this->getQueryForTag($tag); 00283 } 00284 00285 $whereClause[] = $this->tableJoin; 00286 $whereClause[] = $this->notExpiredStatement; 00287 00288 $cacheEntryIdentifierRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( 00289 $this->identifierField, 00290 $this->tableList, 00291 implode(' AND ', $whereClause), 00292 $this->identifierField 00293 ); 00294 00295 foreach ($cacheEntryIdentifierRows as $cacheEntryIdentifierRow) { 00296 $cacheEntryIdentifiers[$cacheEntryIdentifierRow['identifier']] = $cacheEntryIdentifierRow['identifier']; 00297 } 00298 00299 return $cacheEntryIdentifiers; 00300 } 00301 00302 /** 00303 * Removes all cache entries of this cache. 00304 * 00305 * @return void 00306 * @author Ingo Renner <ingo@typo3.org> 00307 */ 00308 public function flush() { 00309 $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery($this->cacheTable); 00310 $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery($this->tagsTable); 00311 } 00312 00313 /** 00314 * Removes all cache entries of this cache which are tagged by the specified tag. 00315 * 00316 * @param string The tag the entries must have 00317 * @return void 00318 */ 00319 public function flushByTag($tag) { 00320 $tagsTableWhereClause = $this->getQueryForTag($tag); 00321 00322 $this->deleteCacheTableRowsByTagsTableWhereClause($tagsTableWhereClause); 00323 00324 $GLOBALS['TYPO3_DB']->exec_DELETEquery( 00325 $this->tagsTable, 00326 $tagsTableWhereClause 00327 ); 00328 } 00329 00330 /** 00331 * Removes all cache entries of this cache which are tagged by the specified tags. 00332 * 00333 * @param array The tags the entries must have 00334 * @return void 00335 */ 00336 public function flushByTags(array $tags) { 00337 if (count($tags)) { 00338 $listQueryConditions = array(); 00339 foreach ($tags as $tag) { 00340 $listQueryConditions[$tag] = $this->getQueryForTag($tag); 00341 } 00342 00343 $tagsTableWhereClause = implode(' OR ', $listQueryConditions); 00344 00345 $this->deleteCacheTableRowsByTagsTableWhereClause($tagsTableWhereClause); 00346 00347 $GLOBALS['TYPO3_DB']->exec_DELETEquery( 00348 $this->tagsTable, 00349 $tagsTableWhereClause 00350 ); 00351 } 00352 } 00353 00354 /** 00355 * Does garbage collection 00356 * 00357 * @return void 00358 * @author Ingo Renner <ingo@typo3.org> 00359 */ 00360 public function collectGarbage() { 00361 // Get identifiers of expired cache entries 00362 $tagsEntryIdentifierRowsResource = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00363 'identifier', 00364 $this->cacheTable, 00365 'crdate + lifetime < ' . $GLOBALS['EXEC_TIME'] . ' AND lifetime > 0' 00366 ); 00367 00368 $tagsEntryIdentifiers = array(); 00369 while ($tagsEntryIdentifierRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($tagsEntryIdentifierRowsResource)) { 00370 $tagsEntryIdentifiers[] = $GLOBALS['TYPO3_DB']->fullQuoteStr( 00371 $tagsEntryIdentifierRow['identifier'], 00372 $this->tagsTable 00373 ); 00374 } 00375 $GLOBALS['TYPO3_DB']->sql_free_result($tagsEntryIdentifierRowsResource); 00376 00377 // Delete tag rows connected to expired cache entries 00378 if (count($tagsEntryIdentifiers)) { 00379 $GLOBALS['TYPO3_DB']->exec_DELETEquery( 00380 $this->tagsTable, 00381 'identifier IN (' . implode(', ', $tagsEntryIdentifiers) . ')' 00382 ); 00383 } 00384 00385 // Delete expired cache rows 00386 $GLOBALS['TYPO3_DB']->exec_DELETEquery( 00387 $this->cacheTable, 00388 'crdate + lifetime < ' . $GLOBALS['EXEC_TIME'] . ' AND lifetime > 0' 00389 ); 00390 } 00391 00392 /** 00393 * Sets the table where the cache entries are stored. The specified table 00394 * must exist already. 00395 * 00396 * @param string The table. 00397 * @return void 00398 * @throws t3lib_cache_Exception if the table does not exist. 00399 * @author Ingo Renner <ingo@typo3.org> 00400 */ 00401 public function setCacheTable($cacheTable) { 00402 $this->cacheTable = $cacheTable; 00403 $this->initializeCommonReferences(); 00404 } 00405 00406 /** 00407 * Returns the table where the cache entries are stored. 00408 * 00409 * @return string The cache table. 00410 * @author Ingo Renner <ingo@typo3.org> 00411 */ 00412 public function getCacheTable() { 00413 return $this->cacheTable; 00414 } 00415 00416 /** 00417 * Sets the table where cache tags are stored. 00418 * 00419 * @param string $tagsTabls: Name of the table 00420 * @return void 00421 */ 00422 public function setTagsTable($tagsTable) { 00423 $this->tagsTable = $tagsTable; 00424 $this->initializeCommonReferences(); 00425 } 00426 00427 /** 00428 * Gets the table where cache tags are stored. 00429 * 00430 * @return string Name of the table storing tags 00431 */ 00432 public function getTagsTable() { 00433 return $this->tagsTable; 00434 } 00435 00436 /** 00437 * Enable data compression 00438 * 00439 * @param boolean TRUE to enable compression 00440 */ 00441 public function setCompression($compression) { 00442 $this->compression = $compression; 00443 } 00444 00445 /** 00446 * Set data compression level. 00447 * If compression is enabled and this is not set, 00448 * gzcompress default level will be used 00449 * 00450 * @param integer -1 to 9: Compression level 00451 */ 00452 public function setCompressionLevel($compressionLevel) { 00453 if ($compressionLevel >= -1 && $compressionLevel <= 9) { 00454 $this->compressionLevel = $compressionLevel; 00455 } 00456 } 00457 00458 /** 00459 * Gets the query to be used for selecting entries by a tag. The asterisk ("*") 00460 * is allowed as a wildcard at the beginning and the end of a tag. 00461 * 00462 * @param string The tag to search for, the "*" wildcard is supported 00463 * @return string the query to be used for selecting entries 00464 * @author Oliver Hader <oliver@typo3.org> 00465 */ 00466 protected function getQueryForTag($tag) { 00467 if (strpos($tag, '*') === false) { 00468 $query = $this->tagsTable . '.tag = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($tag, $this->tagsTable); 00469 } else { 00470 $patternForLike = $GLOBALS['TYPO3_DB']->escapeStrForLike( 00471 $GLOBALS['TYPO3_DB']->quoteStr($tag, $this->tagsTable), 00472 $this->tagsTable 00473 ); 00474 $query = $this->tagsTable . '.tag LIKE \'' . $patternForLike . '\''; 00475 } 00476 00477 return $query; 00478 } 00479 00480 /** 00481 * Deletes rows in cache table found by where clause on tags table 00482 * 00483 * @param string The where clause for the tags table 00484 * @return void 00485 */ 00486 protected function deleteCacheTableRowsByTagsTableWhereClause($tagsTableWhereClause) { 00487 $cacheEntryIdentifierRowsRessource = $GLOBALS['TYPO3_DB']->exec_SELECTquery( 00488 'DISTINCT identifier', 00489 $this->tagsTable, 00490 $tagsTableWhereClause 00491 ); 00492 00493 $cacheEntryIdentifiers = array(); 00494 while ($cacheEntryIdentifierRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($cacheEntryIdentifierRowsRessource)) { 00495 $cacheEntryIdentifiers[] = $GLOBALS['TYPO3_DB']->fullQuoteStr( 00496 $cacheEntryIdentifierRow['identifier'], 00497 $this->cacheTable 00498 ); 00499 } 00500 $GLOBALS['TYPO3_DB']->sql_free_result($cacheEntryIdentifierRowsRessource); 00501 00502 if (count($cacheEntryIdentifiers)) { 00503 $GLOBALS['TYPO3_DB']->exec_DELETEquery( 00504 $this->cacheTable, 00505 'identifier IN (' . implode(', ', $cacheEntryIdentifiers) . ')' 00506 ); 00507 } 00508 } 00509 } 00510 00511 00512 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php'])) { 00513 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php']); 00514 } 00515 00516 ?>
1.8.0