+2009-06-02 Ingo Renner <ingo@typo3.org>
+
+ * Updated the caching framework to the according FLOW3 revision 2616
+
2009-06-15 Martin Kutschker <masi@typo3.org>
* Fixed bug #11119: DBAL: Mapping in query does not takes care of remapping "table.field" in a WHERE clause (thanks to Xavier Perseguers)
*/
abstract class t3lib_cache_backend_AbstractBackend implements t3lib_cache_backend_Backend {
+ const DATETIME_EXPIRYTIME_UNLIMITED = '9999-12-31T23:59:59+0000';
+ const UNLIMITED_LIFETIME = 0;
+
/**
* Reference to the cache which uses this backend
*
$this->defaultLifetime = $defaultLifetime;
}
+ /**
+ * Calculates the expiry time by the given lifetime. If no lifetime is
+ * specified, the default lifetime is used.
+ *
+ * @param integer $lifetime The lifetime in seconds
+ * @return \DateTime The expiry time
+ * @author Robert Lemke <robert@typo3.org>
+ * @internal
+ */
+ protected function calculateExpiryTime($lifetime = NULL) {
+ if ($lifetime === self::UNLIMITED_LIFETIME || ($lifetime === NULL && $this->defaultLifetime === self::UNLIMITED_LIFETIME)) {
+ $expiryTime = new DateTime(self::DATETIME_EXPIRYTIME_UNLIMITED, new DateTimeZone('UTC'));
+ } else {
+ if ($lifetime === NULL) {
+ $lifetime = $this->defaultLifetime;
+ }
+ $expiryTime = new DateTime('now +' . $lifetime . ' seconds', new DateTimeZone('UTC'));
+ }
+
+ return $expiryTime;
+ }
+
+
}
* @param mixed $options Configuration options - unused here
* @author Robert Lemke <robert@typo3.org>
* @author Karsten Dambekalns <karsten@typo3.org>
- *
*/
public function __construct($options = array()) {
if (!extension_loaded('apc')) {
* @throws t3lib_cache_exception_InvalidData if $data is not a string
* @author Christian Jul Jensen <julle@typo3.org>
* @author Karsten Dambekalns <karsten@typo3.org>
- **/
+ */
public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
throw new t3lib_cache_Exception(
* @param string $entryIdentifier
* @param array $tags
* @author Karsten Dambekalns <karsten@typo3.org>
+ * @author Dmitry Dulepov <dmitry.@typo3.org>
*/
protected function addIdentifierToTags($entryIdentifier, array $tags) {
foreach ($tags as $tag) {
* @param string $entryIdentifier
* @param array $tags
* @author Karsten Dambekalns <karsten@typo3.org>
+ * @author Dmitry Dulepov <dmitry.@typo3.org>
*/
protected function removeIdentifierFromAllTags($entryIdentifier) {
// Get tags for this identifier
Related Question: Why aren't there warnings in the FE as the caches get
initialized in tslib_fe's constructor which is also before a DB conection
exsits?
+ Assumption Ingo Renner: Is a custom error_reporting level causing that?
+
+ There's also an unit test for that check (also deactivated for now
$result = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
'id',
*/
class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBackend {
- const SEPARATOR = '@';
+ const SEPARATOR = '^';
- const FILENAME_EXPIRYTIME_FORMAT = 'YmdHis';
- const FILENAME_EXPIRYTIME_GLOB = '??????????????';
- const FILENAME_EXPIRYTIME_UNLIMITED = '99991231235959';
+ const EXPIRYTIME_FORMAT = 'YmdHis';
+ const EXPIRYTIME_LENGTH = 14;
/**
* @var string Directory where the files are stored
protected $cacheDirectory = '';
protected $root = '/';
-
+
/**
* Constructs this backend
*
);
}
- if ($lifetime === 0 || ($lifetime === NULL && $this->defaultLifetime === 0)) {
- $expiryTime = new DateTime('9999-12-31T23:59:59+0000', new DateTimeZone('UTC'));
- } else {
- if ($lifetime === NULL) {
- $lifetime = $this->defaultLifetime;
- }
- $expiryTime = new DateTime('now +' . $lifetime . ' seconds', new DateTimeZone('UTC'));
- }
-
+ $expirytime = $this->calculateExpiryTime($lifetime);
$cacheEntryPath = $this->renderCacheEntryPath($entryIdentifier);
- $filename = $this->renderCacheFilename($entryIdentifier, $expiryTime);
if (!is_writable($cacheEntryPath)) {
try {
$this->remove($entryIdentifier);
- $temporaryFilename = $filename . '.' . uniqid() . '.temp';
+ $data = $expirytime->format(self::EXPIRYTIME_FORMAT) . $data;
+ $temporaryFilename = uniqid() . '.temp';
$result = file_put_contents($cacheEntryPath . $temporaryFilename, $data);
if ($result === FALSE) {
throw new t3lib_cache_Exception(
}
for ($i = 0; $i < 5; $i++) {
- $result = rename(
- $cacheEntryPath . $temporaryFilename,
- $cacheEntryPath . $filename
- );
-
+ $result = rename($cacheEntryPath . $temporaryFilename, $cacheEntryPath . $entryIdentifier);
if ($result === TRUE) {
break;
}
if ($result === FALSE) {
throw new t3lib_cache_Exception(
- 'The cache file "' . $filename . '" could not be written.',
+ 'The cache file "' . $entryIdentifier . '" could not be written.',
1222361632
);
}
$this->root,
$tagPath
);
+ if (!is_writable($tagPath)) {
+ throw new t3lib_cache_Exception(
+ 'The tag directory "' . $tagPath . '" could not be created.',
+ 1238242144
+ );
+ }
}
touch($tagPath
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function get($entryIdentifier) {
- $pathsAndFilenames = $this->findCacheFilesByIdentifier($entryIdentifier);
-
- if ($pathsAndFilenames === FALSE) {
- return FALSE;
- }
- $pathAndFilename = array_pop($pathsAndFilenames);
-
- return ($this->isCacheFileExpired($pathAndFilename)) ? FALSE : file_get_contents($pathAndFilename);
+ $pathAndFilename = $this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier;
+ return ($this->isCacheFileExpired($pathAndFilename)) ? FALSE : file_get_contents($pathAndFilename, NULL, NULL, self::EXPIRYTIME_LENGTH);
}
/**
* @param string $entryIdentifier
* @return boolean TRUE if such an entry exists, FALSE if not
* @author Robert Lemke <robert@typo3.org>
- * @author Karsten Dambekalns <karsten@typo3.org>
*/
public function has($entryIdentifier) {
- $pathsAndFilenames = $this->findCacheFilesByIdentifier($entryIdentifier);
-
- if ($pathsAndFilenames === FALSE) return FALSE;
-
- return !$this->isCacheFileExpired(array_pop($pathsAndFilenames));
+ return !$this->isCacheFileExpired($this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier);
}
/**
* @author Robert Lemke <robert@typo3.org>
*/
public function remove($entryIdentifier) {
- $pathsAndFilenames = $this->findCacheFilesByIdentifier($entryIdentifier);
+ $pathAndFilename = $this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier;
- if ($pathsAndFilenames === FALSE) {
+ if (!file_exists($pathAndFilename)) {
return FALSE;
}
- foreach ($pathsAndFilenames as $pathAndFilename) {
- $result = unlink($pathAndFilename);
- if ($result === FALSE) {
- return FALSE;
- }
- }
-
- $pathsAndFilenames = $this->findTagFilesByEntry($entryIdentifier);
- if ($pathsAndFilenames === FALSE) {
+ if (unlink ($pathAndFilename) === FALSE) {
return FALSE;
}
- foreach ($pathsAndFilenames as $pathAndFilename) {
- $result = unlink($pathAndFilename);
- if ($result === FALSE) {
+ foreach($this->findTagFilesByEntry($entryIdentifier) as $pathAndFilename) {
+ if (!file_exists($pathAndFilename)) {
+ return FALSE;
+ }
+
+ if (unlink ($pathAndFilename) === FALSE) {
return FALSE;
}
}
* @author Robert Lemke <robert@typo3.org>
*/
protected function isCacheFileExpired($cacheFilename) {
- list($timestamp) = explode(self::SEPARATOR, basename($cacheFilename), 2);
- return $timestamp < gmdate('YmdHis');
+ $timestamp = (file_exists($cacheFilename)) ? file_get_contents($cacheFilename, NULL, NULL, 0, self::EXPIRYTIME_LENGTH) : 1;
+ return $timestamp < gmdate(self::EXPIRYTIME_FORMAT);
}
/**
- * Does garbage collection for the given entry or all entries.
+ * Does garbage collection
*
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
$pattern = $this->cacheDirectory . 'data/' . $this->cache->getIdentifier() . '/*/*/*';
$filesFound = glob($pattern);
- foreach ($filesFound as $cacheFile) {
- $splitFilename = explode(self::SEPARATOR, basename($cacheFile), 2);
- if ($splitFilename[0] < gmdate('YmdHis')) {
- $this->remove($splitFilename[1]);
- }
- }
- }
-
- /**
- * Renders a file name for the specified cache entry
- *
- * @param string Identifier for the cache entry
- * @param DateTime Date and time specifying the expiration of the entry. Must be a UTC time.
- * @return string Filename of the cache data file
- * @author Robert Lemke <robert@typo3.org>
- */
- protected function renderCacheFilename($identifier, DateTime $expiryTime) {
- $filename = $expiryTime->format(self::FILENAME_EXPIRYTIME_FORMAT) . self::SEPARATOR . $identifier;
-
- return $filename;
+ foreach ($filesFound as $cacheFilename) {
+ if ($this->isCacheFileExpired($cacheFilename)) {
+ $this->remove(basename($cacheFilename));
+ }
+ }
}
/**
* @param string $identifier Identifier for the cache entry
* @return string Absolute path leading to the directory containing the cache entry
* @author Robert Lemke <robert@typo3.org>
+ * @internal
*/
protected function renderCacheEntryPath($identifier) {
$identifierHash = sha1($identifier);
* @return mixed The file names (including path) as an array if one or more entries could be found, otherwise FALSE
* @author Robert Lemke <robert@typo3.org>
* @throws t3lib_cache_Exception if no frontend has been set
+ * @internal
*/
protected function findCacheFilesByIdentifier($entryIdentifier) {
if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
);
}
- $pattern = $this->renderCacheEntryPath($entryIdentifier) . self::FILENAME_EXPIRYTIME_GLOB . self::SEPARATOR . $entryIdentifier;
+ $pattern = $this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier;
$filesFound = glob($pattern);
+ if ($filesFound === FALSE || count($filesFound) === 0) {
+ return FALSE;
+ }
return $filesFound;
}
* Tries to find the tag entries for the specified cache entry.
*
* @param string The cache entry identifier to find tag files for
- * @return mixed The file names (including path) as an array if one or more entries could be found, otherwise FALSE
+ * @return array The file names (including path)
* @author Robert Lemke <robert@typo3.org>
* @throws t3lib_cache_Exception if no frontend has been set
+ * @internal
*/
protected function findTagFilesByEntry($entryIdentifier) {
if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
);
}
- $path = $this->cacheDirectory . 'tags/';
- $pattern = $path . '*/' . $this->cache->getIdentifier() . self::SEPARATOR . $entryIdentifier;
- $filesFound = glob($pattern);
-
- if ($filesFound === FALSE || count($filesFound) === 0) {
- return FALSE;
- }
-
- return $filesFound;
+ $path = $this->cacheDirectory . 'tags/';
+ $pattern = $path . '*/' . $this->cache->getIdentifier() . self::SEPARATOR . $entryIdentifier;
+ return glob($pattern);
}
}
+++ /dev/null
-<?php
-/***************************************************************
-* Copyright notice
-*
-* (c) 2008-2009 Ingo Renner <ingo@typo3.org>
-* All rights reserved
-*
-* This script is part of the TYPO3 project. The TYPO3 project is
-* free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* The GNU General Public License can be found at
-* http://www.gnu.org/copyleft/gpl.html.
-*
-* This script is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* This copyright notice MUST APPEAR in all copies of the script!
-***************************************************************/
-
-
-/**
- * A caching backend which saves it's data in $GLOBALS - a very short living cache, probably useful only during page rendering
- *
- * @package TYPO3
- * @subpackage t3lib_cache
- * @version $Id$
- */
-class t3lib_cache_backend_GlobalsBackend extends t3lib_cache_backend_AbstractBackend {
-
- /**
- * Constructs this backend
- *
- * @param mixed Configuration options - depends on the actual backend
- */
- public function __construct(array $options = array()) {
- parent::__construct($options);
-
- if (!isset($GLOBALS['typo3CacheStorage'])) {
- $GLOBALS['typo3CacheStorage'] = array();
- }
-
- if (!is_object($this->cache)) {
- throw new t3lib_cache_Exception(
- 'No cache frontend has been set yet via setCache().',
- 1217611408
- );
- }
-
- $GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()] = array(
- 'data' => array(),
- 'tags' => array()
- );
- }
-
- /**
- * Saves data in a cache file.
- *
- * @param string An identifier for this specific cache entry
- * @param string The data to be stored
- * @param array Tags to associate with this cache entry
- * @param integer Ignored as $GLOBALS lasts for the time of the script execution only anyway
- * @return void
- * @throws t3lib_cache_Exception if the directory does not exist or is not writable, or if no cache frontend has been set.
- * @author Ingo Renner <ingo@typo3.org>
- */
- public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
- if (!self::isValidEntryIdentifier($entryIdentifier)) {
- throw new InvalidArgumentException(
- '"' . $entryIdentifier . '" is not a valid cache entry identifier.',
- 1217611184
- );
- }
-
- if (!is_object($this->cache)) {
- throw new t3lib_cache_Exception(
- 'No cache frontend has been set yet via setCache().',
- 1217611191
- );
- }
-
- if (!is_string($data)) {
- throw new t3lib_cache_Exception_InvalidData(
- 'The specified data is of type "' . gettype($data) . '" but a string is expected.',
- 1217611199
- );
- }
-
- foreach ($tags as $tag) {
- if (!self::isValidTag($tag)) {
- throw new InvalidArgumentException(
- '"' . $tag . '" is not a valid tag for a cache entry.',
- 1217611205
- );
- }
- }
-
- // saving data
- $GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['data'][$entryIdentifier] = $data;
-
- // tagging
- foreach ($tags as $tag) {
- if (!isset($GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['tags'][$tag])) {
- $GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['tags'][$tag] = array();
- }
-
- $GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['tags'][$tag][] = $entryIdentifier;
- }
-
- }
-
- /**
- * Loads data from a cache file.
- *
- * @param string An identifier which describes the cache entry to load
- * @return mixed The cache entry's content as a string or FALSE if the cache entry could not be loaded
- * @author Ingo Renner <ingo@typo3.org>
- */
- public function get($entryIdentifier) {
- $cacheEntry = FALSE;
-
- if (isset($GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['data'][$entryIdentifier])) {
- $cacheEntry = $GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['data'][$entryIdentifier];
- }
-
- return $cacheEntry;
- }
-
- /**
- * Checks if a cache entry with the specified identifier exists.
- *
- * @param unknown_type
- * @return boolean TRUE if such an entry exists, FALSE if not
- * @author Ingo Renner <ingo@typo3.org>
- */
- public function has($entryIdentifier) {
- return isset($GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['data'][$entryIdentifier]);
- }
-
- /**
- * Removes all cache entries matching the specified identifier.
- * Usually this only affects one entry.
- *
- * @param string Specifies the cache entry to remove
- * @return boolean TRUE if (at least) an entry could be removed or FALSE if no entry was found
- * @author Ingo Renner <ingo@typo3.org>
- */
- public function remove($entryIdentifier) {
- $cacheEntryFound = $this->has($entryIdentifier);
-
- if ($cacheEntryFound) {
- unset($GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['data'][$entryIdentifier]);
- }
-
- return $cacheEntryFound;
- }
-
- /**
- * Finds and returns all cache entries which are tagged by the specified tag.
- * The asterisk ("*") is allowed as a wildcard at the beginning and the end of
- * the tag.
- *
- * @param string The tag to search for, the "*" wildcard is supported
- * @return array An array with identifiers of all matching entries. An empty array if no entries matched
- * @author Ingo Renner <ingo@typo3.org>
- */
- public function findEntriesByTag($tag) {
- $taggedEntries = array();
-
- if (!empty($GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['tags'][$tag])) {
- $taggedEntries = $GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['tags'][$tag];
- }
-
- return $taggedEntries;
- }
-
- /**
- * Finds and returns all cache entry identifiers which are tagged by the specified tags.
- * The asterisk ("*") is allowed as a wildcard at the beginning and the end of
- * a tag.
- *
- * @param array Array of tags to search for, the "*" wildcard is supported
- * @return array An array with identifiers of all matching entries. An empty array if no entries matched
- * @author Ingo Renner <ingo@typo3.org>
- */
- public function findEntriesByTags(array $tags) {
- $taggedEntries = array();
- $foundEntries = array();
-
- foreach ($tags as $tag) {
- $taggedEntries[$tag] = $this->findEntriesByTag($tag);
- }
-
- $intersectedTaggedEntries = call_user_func_array('array_intersect', $taggedEntries);
-
- foreach ($intersectedTaggedEntries as $entryIdentifier) {
- $foundEntries[$entryIdentifier] = $entryIdentifier;
- }
-
- return $foundEntries;
- }
-
- /**
- * Removes all cache entries of this cache.
- *
- * @return void
- * @author Ingo Renner <ingo@typo3.org>
- */
- public function flush() {
- $GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['data'] = array();
- $GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['tags'] = array();
- }
-
- /**
- * Removes all cache entries of this cache which are tagged by the specified tag.
- *
- * @param string The tag the entries must have
- * @return void
- * @author Ingo Renner <ingo@typo3.org>
- */
- public function flushByTag($tag) {
- unset($GLOBALS['typo3CacheStorage'][$this->cache->getIdentifier()]['tags'][$tag]);
- }
-
- /**
- * Removes all cache entries of this cache which are tagged by the specified tag.
- *
- * @param array The tags the entries must have
- * @return void
- * @author Ingo Renner <ingo@typo3.org>
- */
- public function flushByTags(array $tags) {
- foreach ($tags as $tag) {
- $this->flushByTag($tag);
- }
- }
-
- /**
- * Does nothing, as the cache is destroyed when the script ends
- *
- * @return void
- */
- public function collectGarbage() {
- }
-}
-
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_globalsbackend.php']) {
- include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_globalsbackend.php']);
-}
-
-?>
\ No newline at end of file
}
/**
- * Sets for compression flags bit
+ * Setter for compression flags bit
*
- * @param boolean New value of compression flag
- * @return void
- * @author Christian Jul Jensen <julle@typo3.org>
+ * @param boolean $useCompression
+ * @return void
+ * @author Christian Jul Jensen <julle@typo3.org>
*/
protected function setCompression($useCompression) {
- if ($useCompression === TRUE) {
+ if ($useCompression === TRUE) {
$this->flags ^= MEMCACHE_COMPRESSED;
} else {
$this->flags &= ~MEMCACHE_COMPRESSED;
* @throws t3lib_cache_exception_InvalidData if $data is not a string
* @author Christian Jul Jensen <julle@typo3.org>
* @author Karsten Dambekalns <karsten@typo3.org>
- **/
+ */
public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
if (strlen($this->identifierPrefix . $entryIdentifier) > 250) {
throw new InvalidArgumentException(
*
* @return array
* @author Karsten Dambekalns <karsten@typo3.org>
+ * @internal
*/
protected function getTagIndex() {
$tagIndex = $this->memcache->get($this->identifierPrefix . 'tagIndex');
*
* @param array Array of tags
* @author Karsten Dambekalns <karsten@typo3.org>
+ * @internal
*/
protected function setTagIndex(array $tags) {
$this->memcache->set($this->identifierPrefix . 'tagIndex', array_unique($tags), 0, 0);
* @param array Array of tags
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
+ * @internal
*/
protected function addTagsToTagIndex(array $tags) {
if(count($tags)) {
* @param array $tags
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
+ * @internal
*/
protected function removeTagsFromTagIndex(array $tags) {
if(count($tags)) {
* @param string $entryIdentifier
* @param array Array of tags
* @author Karsten Dambekalns <karsten@typo3.org>
- * @author Dmitry Dulepov
+ * @author Dmitry Dulepov <dmitry@typo3.org>
+ * @internal
*/
protected function addIdentifierToTags($entryIdentifier, array $tags) {
if ($this->serverConnected) {
* @param string $entryIdentifier
* @param array Array of tags
* @author Karsten Dambekalns <karsten@typo3.org>
- * @author Dmitry Dulepov
+ * @author Dmitry Dulepov <dmitry@typo3.org>
+ * @internal
*/
protected function removeIdentifierFromAllTags($entryIdentifier) {
if ($this->serverConnected) {
*
* @param string Identifier to find tags by
* @return array Array with tags
- * @author Dmitry Dulepov
+ * @author Dmitry Dulepov <dmitry@typo3.org>
+ * @internal
*/
protected function findTagsByIdentifier($identifier) {
$tags = $this->memcache->get($this->identifierPrefix . 'ident_' . $identifier);
--- /dev/null
+<?php
+/***************************************************************
+* Copyright notice
+*
+* (c) 2009 Ingo Renner <ingo@typo3.org>
+* All rights reserved
+*
+* This script is part of the TYPO3 project. The TYPO3 project is
+* free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* The GNU General Public License can be found at
+* http://www.gnu.org/copyleft/gpl.html.
+*
+* This script is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+
+/**
+ * A caching backend which stores cache entries during one script run.
+ *
+ * This file is a backport from FLOW3
+ *
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @version $Id$
+ */
+class t3lib_cache_backend_TransientMemoryBackend extends t3lib_cache_backend_AbstractBackend {
+
+ /**
+ * @var array
+ */
+ protected $entries = array();
+
+ /**
+ * @var array
+ */
+ protected $tagsAndEntries = array();
+
+ /**
+ * Saves data in the cache.
+ *
+ * @param string $entryIdentifier An identifier for this specific cache entry
+ * @param string $data The data to be stored
+ * @param array $tags Tags to associate with this cache entry
+ * @param integer $lifetime Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited liftime.
+ * @return void
+ * @throws t3lib_cache_Exception if no cache frontend has been set.
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
+ if (!$this->cache instanceof t3lib_cache_frontend_Frontend) throw new t3lib_cache_Exception('No cache frontend has been set yet via setCache().', 1238244992);
+ if (!is_string($data)) throw new t3lib_cache_exception_InvalidData('The specified data is of type "' . gettype($data) . '" but a string is expected.', 1238244993);
+ $this->entries[$entryIdentifier] = $data;
+ foreach ($tags as $tag) {
+ $this->tagsAndEntries[$tag][$entryIdentifier] = TRUE;
+ }
+ }
+
+ /**
+ * Loads data from the cache.
+ *
+ * @param string $entryIdentifier An identifier which describes the cache entry to load
+ * @return mixed The cache entry's content as a string or FALSE if the cache entry could not be loaded
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function get($entryIdentifier) {
+ return (isset($this->entries[$entryIdentifier])) ? $this->entries[$entryIdentifier] : FALSE;
+ }
+
+ /**
+ * Checks if a cache entry with the specified identifier exists.
+ *
+ * @param string $entryIdentifier An identifier specifying the cache entry
+ * @return boolean TRUE if such an entry exists, FALSE if not
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function has($entryIdentifier) {
+ return isset($this->entries[$entryIdentifier]);
+ }
+
+ /**
+ * Removes all cache entries matching the specified identifier.
+ *
+ * @param string $entryIdentifier Specifies the cache entry to remove
+ * @return boolean TRUE if the entry could be removed or FALSE if no entry was found
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function remove($entryIdentifier) {
+ if (isset($this->entries[$entryIdentifier])) {
+ unset($this->entries[$entryIdentifier]);
+ foreach (array_keys($this->tagsAndEntries) as $tag) {
+ if (isset($this->tagsAndEntries[$tag][$entryIdentifier])) {
+ unset ($this->tagsAndEntries[$tag][$entryIdentifier]);
+ }
+ }
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+
+ /**
+ * Finds and returns all cache entry identifiers which are tagged by the
+ * specified tag.
+ *
+ * @param string $tag The tag to search for
+ * @return array An array with identifiers of all matching entries. An empty array if no entries matched
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function findIdentifiersByTag($tag) {
+ if (isset($this->tagsAndEntries[$tag])) {
+ return array_keys($this->tagsAndEntries[$tag]);
+ } else {
+ return array();
+ }
+ }
+
+ /**
+ * Finds and returns all cache entry identifiers which are tagged by the
+ * specified tags.
+ * The asterisk ("*") is allowed as a wildcard at the beginning and the end
+ * of a tag.
+ *
+ * @param array Array of tags to search for, the "*" wildcard is supported
+ * @return array An array with identifiers of all matching entries. An empty array if no entries matched
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function findIdentifiersByTags(array $tags) {
+ $taggedEntries = array();
+ $foundEntries = array();
+
+ foreach ($tags as $tag) {
+ $taggedEntries[$tag] = $this->findIdentifiersByTag($tag);
+ }
+
+ $intersectedTaggedEntries = call_user_func_array('array_intersect', $taggedEntries);
+
+ foreach ($intersectedTaggedEntries as $entryIdentifier) {
+ $foundEntries[$entryIdentifier] = $entryIdentifier;
+ }
+
+ return $foundEntries;
+ }
+
+ /**
+ * Removes all cache entries of this cache.
+ *
+ * @return void
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function flush() {
+ $this->entries = array();
+ $this->tagsAndEntries = array();
+ }
+
+ /**
+ * Removes all cache entries of this cache which are tagged by the specified tag.
+ *
+ * @param string $tag The tag the entries must have
+ * @return void
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function flushByTag($tag) {
+ $identifiers = $this->findIdentifiersByTag($tag);
+ foreach ($identifiers as $identifier) {
+ $this->remove($identifier);
+ }
+ }
+
+ /**
+ * Removes all cache entries of this cache which are tagged by the specified tags.
+ *
+ * @param array The tags the entries must have
+ * @return void
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function flushByTags(array $tags) {
+ foreach ($tags as $tag) {
+ $this->flushByTag($tag);
+ }
+ }
+
+ /**
+ * Does nothing
+ *
+ * @return void
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function collectGarbage() {
+ }
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_transientmemorybackend.php']) {
+ include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_transientmemorybackend.php']);
+}
+
+?>
\ No newline at end of file
* @param t3lib_cache_Manager The cache manager
* @return void
* @author Robert Lemke <robert@typo3.org>
+ * @internal
*/
public function setCacheManager(t3lib_cache_Manager $cacheManager) {
$this->cacheManager = $cacheManager;
protected $cacheFactory;
/**
- * @var array Registered Caches
+ * @var array
*/
protected $caches = array();
+ /**
+ * @var array
+ */
protected $cacheConfigurations = array(
'default' => array(
'frontend' => 't3lib_cache_frontend_VariableFrontend',
* @param array The cache configurations to set
* @return void
* @author Robert Lemke <robert@typo3.org>
+ * @internal
*/
public function setCacheConfigurations(array $cacheConfigurations) {
foreach ($cacheConfigurations as $identifier => $configuration) {
* @return void
* @author Robert Lemke <robert@typo3.org>
* @author Ingo Renner <ingo@typo3.org>
+ * @internal
*/
public function setCacheFactory(t3lib_cache_Factory $cacheFactory) {
$this->cacheFactory = $cacheFactory;
*
* @return void
* @author Robert Lemke <robert@typo3.org>
+ * @internal
*/
public function initialize() {
foreach ($this->cacheConfigurations as $identifier => $configuration) {
* @param string Identifies which cache to return
* @return t3lib_cache_frontend_Cache The specified cache frontend
* @throws t3lib_cache_exception_NoSuchCache
+ * @author Robert Lemke <robert@typo3.org>
*/
public function getCache($identifier) {
if (!isset($this->caches[$identifier])) {
* @param t3lib_cache_backend_Backend Backend to be used for this cache
* @author Robert Lemke <robert@typo3.org>
* @throws InvalidArgumentException if the identifier doesn't match PATTERN_ENTRYIDENTIFIER
+ * @internal
*/
public function __construct($identifier, t3lib_cache_backend_Backend $backend) {
if (!preg_match(self::PATTERN_ENTRYIDENTIFIER, $identifier)) {
* @param string An identifier used for this cache entry
* @param string The variable to cache
* @param array Tags to associate with this cache entry
- * @param integer The lifetime in seconds for this cache entry
+ * @param integer Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited liftime.
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
*/
* @param string $entryIdentifier An identifier used for this cache entry
* @param mixed $variable The variable to cache
* @param array $tags Tags to associate with this cache entry
- * @param integer The lifetime in seconds for this cache entry
+ * @param integer $lifetime Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited liftime.
* @return void
* @author Robert Lemke <robert@typo3.org>
* @author Karsten Dambekalns <karsten@typo3.org>
* @param string Something which identifies the data - depends on concrete cache
* @param mixed The data to cache - also depends on the concrete cache implementation
* @param array Tags to associate with this cache entry
- * @param integer The lifetime in seconds for this cache entry
+ * @param integer Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited liftime.
* @return void
*/
public function set($entryIdentifier, $data, $tags = array(), $lifetime = NULL);
*
* @param string An identifier specifying the cache entry
* @return boolean TRUE if such an entry exists, FALSE if not
+ * @internal
*/
public function remove($entryIdentifier);
--- /dev/null
+2616
\ No newline at end of file
--- /dev/null
+<?php
+/***************************************************************
+* Copyright notice
+*
+* (c) 2009 Ingo Renner <ingo@typo3.org>
+* All rights reserved
+*
+* This script is part of the TYPO3 project. The TYPO3 project is
+* free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* The GNU General Public License can be found at
+* http://www.gnu.org/copyleft/gpl.html.
+*
+* This script is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+
+/**
+ * A caching backend which forgets everything immediately
+ * Used in t3lib_cache_FactoryTestCase
+ *
+ * This file is a backport from FLOW3
+ *
+ * @package TYPO3
+ * @subpackage tests
+ * @version $Id$
+ */
+class t3lib_cache_backend_MockBackend extends t3lib_cache_backend_NullBackend {
+
+ /**
+ * @var mixed
+ */
+ protected $someOption;
+
+ /**
+ * Sets some option
+ *
+ * @param mixed $value
+ * @return void
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function setSomeOption($value) {
+ $this->someOption = $value;
+ }
+
+ /**
+ * Returns the option value
+ *
+ * @return mixed
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function getSomeOption() {
+ return $this->someOption;
+ }
+
+}
+
+?>
\ No newline at end of file
$backend = new $className(array('someOption' => 'someValue'));
$this->assertSame('someValue', $backend->getSomeOption());
}
-
}
?>
\ No newline at end of file
/**
* @test
- * @author Ingo Renner <ingo@typo3.org>
* @expectedException t3lib_cache_Exception
+ * @author Ingo Renner <ingo@typo3.org>
*/
- public function setCacheTableThrowsExceptionOnNonExistentTable() {
- $this->backend->setCacheTable('test_cache_non_existent_table');
- }
+# deactivated as the according check in the DB backend causes trouble during TYPO3's initialization
+# public function setCacheTableThrowsExceptionOnNonExistentTable() {
+# $this->backend->setCacheTable('test_cache_non_existent_table');
+# }
/**
* @test
/**
* @test
- * @author Ingo Renner <ingo@typo3.org>
* @expectedException t3lib_cache_exception_InvalidData
+ * @author Ingo Renner <ingo@typo3.org>
*/
public function setThrowsExceptionIfDataIsNotAString() {
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
$this->backend->set($entryIdentifier, $data);
$cacheDirectory = $this->backend->getCacheDirectory();
- $pattern = $cacheDirectory
+ $pathAndFilename = $cacheDirectory
. 'data/'
. $cacheIdentifier . '/'
. $entryIdentifierHash[0] . '/'
. $entryIdentifierHash[1] . '/'
- . t3lib_cache_backend_FileBackend::FILENAME_EXPIRYTIME_GLOB
- . t3lib_cache_backend_FileBackend::SEPARATOR
. $entryIdentifier;
- $filesFound = glob($pattern);
- $this->assertTrue(is_array($filesFound), 'filesFound was no array.');
-
- $retrievedData = file_get_contents(array_pop($filesFound));
+ $this->assertTrue(file_exists($pathAndFilename), 'File does not exist.');
+ $retrievedData = file_get_contents($pathAndFilename, NULL, NULL, t3lib_cache_backend_FileBackend::EXPIRYTIME_LENGTH);
$this->assertEquals(
$data,
$retrievedData,
* @author Robert Lemke <robert@typo3.org>
* @author Ingo Renner <ingo@typo3.org>
*/
- public function setRemovesAnAlreadyExistingCacheEntryForTheSameIdentifier() {
+ public function setOverwritesAnAlreadyExistingCacheEntryForTheSameIdentifier() {
$cacheIdentifier = 'UnitTestCache';
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
$this->backend->set($entryIdentifier, $data2, array(), 200);
$cacheDirectory = $this->backend->getCacheDirectory();
- $pattern = $cacheDirectory
+ $pathAndFilename = $cacheDirectory
. 'data/'
. $cacheIdentifier . '/'
. $entryIdentifierHash[0] . '/'
. $entryIdentifierHash[1] . '/'
- . t3lib_cache_backend_FileBackend::FILENAME_EXPIRYTIME_GLOB
- . t3lib_cache_backend_FileBackend::SEPARATOR
. $entryIdentifier;
- $filesFound = glob($pattern);
- $this->assertEquals(1, count($filesFound), 'There was not exactly one cache entry.');
+ $this->assertTrue(file_exists($pathAndFilename), 'File does not exist.');
+ $retrievedData = file_get_contents($pathAndFilename, NULL, NULL, t3lib_cache_backend_FileBackend::EXPIRYTIME_LENGTH);
+ $this->assertEquals($data2, $retrievedData);
}
/**
$cacheDirectory = $this->backend->getCacheDirectory();
$this->backend->setCache($cache);
- $pattern = $cacheDirectory
+ $pathAndFilename = $cacheDirectory
. 'data/'
. $cacheIdentifier . '/'
. $entryIdentifierHash[0] . '/'
. $entryIdentifierHash[1] . '/'
- . t3lib_cache_backend_FileBackend::FILENAME_EXPIRYTIME_GLOB
- . t3lib_cache_backend_FileBackend::SEPARATOR
. $entryIdentifier;
+
$this->backend->set($entryIdentifier, $data);
- $filesFound = glob($pattern);
- $this->assertTrue(is_array($filesFound) && count($filesFound) > 0, 'The cache entry does not exist.');
+ $this->assertTrue(file_exists($pathAndFilename), 'The cache entry does not exist.');
$this->backend->remove($entryIdentifier);
- $filesFound = glob($pattern);
- $this->assertTrue(count($filesFound) == 0, 'The cache entry still exists.');
+ $this->assertFalse(file_exists($pathAndFilename), 'The cache entry still exists.');
}
/**
$cacheDirectory = $this->backend->getCacheDirectory();
$this->backend->setCache($cache);
- $pattern = $cacheDirectory
+ $pathAndFilename = $cacheDirectory
. 'data/'
. $cacheIdentifier . '/'
. $entryIdentifierHash[0] . '/'
. $entryIdentifierHash[1] . '/'
- . t3lib_cache_backend_FileBackend::FILENAME_EXPIRYTIME_GLOB
- . t3lib_cache_backend_FileBackend::SEPARATOR
. $entryIdentifier;
$this->backend->set($entryIdentifier, $data, array(), 1);
- $filesFound = glob($pattern);
- $this->assertTrue(is_array($filesFound) && count($filesFound) > 0, 'The cache entry does not exist.');
+ $this->assertTrue(file_exists($pathAndFilename), 'The cache entry does not exist.');
sleep(2);
$this->backend->collectGarbage();
- $filesFound = glob($pattern);
- $this->assertTrue(count($filesFound) == 0, 'The cache entry still exists.');
+ $this->assertFalse(file_exists($pathAndFilename), 'The cache entry still exists.');
}
/**
$cacheDirectory = $this->backend->getCacheDirectory();
$this->backend->setCache($cache);
+// $pattern = $cacheDirectory
+// . 'data/'
+// . $cacheIdentifier . '/*/*/'
+// . t3lib_cache_backend_FileBackend::FILENAME_EXPIRYTIME_GLOB
+// . t3lib_cache_backend_FileBackend::SEPARATOR
+// . $entryIdentifier
+// . '?';
$pattern = $cacheDirectory
. 'data/'
. $cacheIdentifier . '/*/*/'
- . t3lib_cache_backend_FileBackend::FILENAME_EXPIRYTIME_GLOB
- . t3lib_cache_backend_FileBackend::SEPARATOR
. $entryIdentifier
. '?';
$cacheDirectory = $this->backend->getCacheDirectory();
- $pattern = $cacheDirectory
+ $pathAndFilename = $cacheDirectory
. 'data/'
. $cacheIdentifier . '/'
. $entryIdentifierHash[0] . '/'
. $entryIdentifierHash[1] . '/'
- . t3lib_cache_backend_FileBackend::FILENAME_EXPIRYTIME_UNLIMITED
- . t3lib_cache_backend_FileBackend::SEPARATOR
. $entryIdentifier;
+ $this->assertTrue(file_exists($pathAndFilename), 'File not found.');
- $filesFound = glob($pattern);
- $this->assertTrue(is_array($filesFound), 'filesFound was no array.');
-
- $retrievedData = file_get_contents(array_pop($filesFound));
+ $retrievedData = file_get_contents($pathAndFilename, NULL, NULL, t3lib_cache_backend_FileBackend::EXPIRYTIME_LENGTH);
$this->assertEquals($data, $retrievedData, 'The original and the retrieved data don\'t match.');
}
--- /dev/null
+<?php
+/***************************************************************
+* Copyright notice
+*
+* (c) 2009 Ingo Renner <ingo@typo3.org>
+* All rights reserved
+*
+* This script is part of the TYPO3 project. The TYPO3 project is
+* free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* The GNU General Public License can be found at
+* http://www.gnu.org/copyleft/gpl.html.
+*
+* This script is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+
+ // TODO implement autoloading so that we only require stuff we really need
+require_once(PATH_t3lib . 'class.t3lib_cache.php');
+
+require_once(PATH_t3lib . 'cache/backend/interfaces/interface.t3lib_cache_backend_backend.php');
+require_once(PATH_t3lib . 'cache/frontend/interfaces/interface.t3lib_cache_frontend_frontend.php');
+
+require_once(PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_abstractbackend.php');
+require_once(PATH_t3lib . 'cache/frontend/class.t3lib_cache_frontend_abstractfrontend.php');
+require_once(PATH_t3lib . 'cache/class.t3lib_cache_exception.php');
+require_once(PATH_t3lib . 'cache/class.t3lib_cache_factory.php');
+require_once(PATH_t3lib . 'cache/class.t3lib_cache_manager.php');
+require_once(PATH_t3lib . 'cache/frontend/class.t3lib_cache_frontend_variablefrontend.php');
+
+require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_classalreadyloaded.php');
+require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_duplicateidentifier.php');
+require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invalidbackend.php');
+require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invalidcache.php');
+require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invaliddata.php');
+require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_nosuchcache.php');
+
+require_once(PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_transientmemorybackend.php');
+
+/**
+ * Testcase for the TransientMemory cache backend
+ *
+ * This file is a backport from FLOW3
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage tests
+ * @version $Id$
+ */
+class t3lib_cache_backend_TransientMemoryBackendTestCase extends tx_phpunit_testcase {
+
+ /**
+ * @expectedException t3lib_cache_Exception
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ */
+ public function setThrowsExceptionIfNoFrontEndHasBeenSet() {
+ $backend = new t3lib_cache_backend_TransientMemoryBackend();
+
+ $data = 'Some data';
+ $identifier = 'MyIdentifier';
+ $backend->set($identifier, $data);
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function itIsPossibleToSetAndCheckExistenceInCache() {
+ $cache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
+ $backend = new t3lib_cache_backend_TransientMemoryBackend();
+ $backend->setCache($cache);
+
+ $data = 'Some data';
+ $identifier = 'MyIdentifier';
+ $backend->set($identifier, $data);
+ $inCache = $backend->has($identifier);
+ $this->assertTrue($inCache);
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function itIsPossibleToSetAndGetEntry() {
+ $cache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
+ $backend = new t3lib_cache_backend_TransientMemoryBackend();
+ $backend->setCache($cache);
+
+ $data = 'Some data';
+ $identifier = 'MyIdentifier';
+ $backend->set($identifier, $data);
+ $fetchedData = $backend->get($identifier);
+ $this->assertEquals($data, $fetchedData);
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function itIsPossibleToRemoveEntryFromCache() {
+ $cache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
+ $backend = new t3lib_cache_backend_TransientMemoryBackend();
+ $backend->setCache($cache);
+
+ $data = 'Some data';
+ $identifier = 'MyIdentifier';
+ $backend->set($identifier, $data);
+ $backend->remove($identifier);
+ $inCache = $backend->has($identifier);
+ $this->assertFalse($inCache);
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function itIsPossibleToOverwriteAnEntryInTheCache() {
+ $cache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
+ $backend = new t3lib_cache_backend_TransientMemoryBackend();
+ $backend->setCache($cache);
+
+ $data = 'Some data';
+ $identifier = 'MyIdentifier';
+ $backend->set($identifier, $data);
+ $otherData = 'some other data';
+ $backend->set($identifier, $otherData);
+ $fetchedData = $backend->get($identifier);
+ $this->assertEquals($otherData, $fetchedData);
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag() {
+ $cache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
+ $backend = new t3lib_cache_backend_TransientMemoryBackend();
+ $backend->setCache($cache);
+
+ $data = 'Some data';
+ $entryIdentifier = 'MyIdentifier';
+ $backend->set($entryIdentifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
+
+ $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag1');
+ $this->assertEquals($entryIdentifier, $retrieved[0]);
+
+ $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag2');
+ $this->assertEquals($entryIdentifier, $retrieved[0]);
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function hasReturnsFalseIfTheEntryDoesntExist() {
+ $cache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
+ $backend = new t3lib_cache_backend_TransientMemoryBackend();
+ $backend->setCache($cache);
+
+ $identifier = 'NonExistingIdentifier';
+ $inCache = $backend->has($identifier);
+ $this->assertFalse($inCache);
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function removeReturnsFalseIfTheEntryDoesntExist() {
+ $cache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
+ $backend = new t3lib_cache_backend_TransientMemoryBackend();
+ $backend->setCache($cache);
+
+ $identifier = 'NonExistingIdentifier';
+ $inCache = $backend->remove($identifier);
+ $this->assertFalse($inCache);
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Karsten Dambekalns <karsten@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function flushByTagRemovesCacheEntriesWithSpecifiedTag() {
+ $cache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
+ $backend = new t3lib_cache_backend_TransientMemoryBackend();
+ $backend->setCache($cache);
+
+ $data = 'some data' . microtime();
+ $backend->set('TransientMemoryBackendTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
+ $backend->set('TransientMemoryBackendTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
+ $backend->set('TransientMemoryBackendTest3', $data, array('UnitTestTag%test'));
+
+ $backend->flushByTag('UnitTestTag%special');
+
+ $this->assertTrue($backend->has('TransientMemoryBackendTest1'), 'TransientMemoryBackendTest1');
+ $this->assertFalse($backend->has('TransientMemoryBackendTest2'), 'TransientMemoryBackendTest2');
+ $this->assertTrue($backend->has('TransientMemoryBackendTest3'), 'TransientMemoryBackendTest3');
+ }
+
+ /**
+ * @test
+ * @author Karsten Dambekalns <karsten@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function flushRemovesAllCacheEntries() {
+ $cache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
+ $backend = new t3lib_cache_backend_TransientMemoryBackend();
+ $backend->setCache($cache);
+
+ $data = 'some data' . microtime();
+ $backend->set('TransientMemoryBackendTest1', $data);
+ $backend->set('TransientMemoryBackendTest2', $data);
+ $backend->set('TransientMemoryBackendTest3', $data);
+
+ $backend->flush();
+
+ $this->assertFalse($backend->has('TransientMemoryBackendTest1'), 'TransientMemoryBackendTest1');
+ $this->assertFalse($backend->has('TransientMemoryBackendTest2'), 'TransientMemoryBackendTest2');
+ $this->assertFalse($backend->has('TransientMemoryBackendTest3'), 'TransientMemoryBackendTest3');
+ }
+}
+
+?>
\ No newline at end of file
*/
public function theConstructorAcceptsValidIdentifiers() {
$mockBackend = $this->getMock('t3lib_cache_backend_AbstractBackend', array('get', 'set', 'has', 'remove', 'findIdentifiersByTag', 'findIdentifiersByTags', 'flush', 'flushByTag', 'flushByTags', 'collectGarbage'), array(), '', FALSE);
- foreach (array('x', 'someValue', '123fivesixseveneight', 'ab_cd%', rawurlencode('package://some/äöü$&% sadf'), str_repeat('x', 250)) as $identifier) {
+ foreach (array('x', 'someValue', '123fivesixseveneight', 'some&', 'ab_cd%', rawurlencode('package://some/äöü$&% sadf'), str_repeat('x', 250)) as $identifier) {
$abstractCache = $this->getMock('t3lib_cache_frontend_StringFrontend', array('__construct', 'get', 'set', 'has', 'remove', 'getByTag', 'flush', 'flushByTag', 'collectGarbage'), array($identifier, $mockBackend));
}
}
*/
public function theConstructorRejectsInvalidIdentifiers() {
$mockBackend = $this->getMock('t3lib_cache_backend_AbstractBackend', array('get', 'set', 'has', 'remove', 'findIdentifiersByTag', 'findIdentifiersByTags', 'flush', 'flushByTag', 'flushByTags', 'collectGarbage'), array(), '', FALSE);
- foreach (array('', 'abc def', 'foo!', 'bar:', 'some/', 'bla*', 'one+', 'äöü', str_repeat('x', 251), 'x$', '\\a', 'b#', 'some&') as $identifier) {
+ foreach (array('', 'abc def', 'foo!', 'bar:', 'some/', 'bla*', 'one+', 'äöü', str_repeat('x', 251), 'x$', '\\a', 'b#') as $identifier) {
try {
$abstractCache = $this->getMock('t3lib_cache_frontend_StringFrontend', array('__construct', 'get', 'set', 'has', 'remove', 'getByTag', 'flush', 'flushByTag', 'collectGarbage'), array($identifier, $mockBackend));
$this->fail('Identifier "' . $identifier . '" was not rejected.');
$identifier = 'someCacheIdentifier';
$backend = $this->getMock('t3lib_cache_backend_AbstractBackend', array(), array(), '', FALSE);
$cache = $this->getMock('t3lib_cache_frontend_StringFrontend', array('__construct', 'get', 'set', 'has', 'remove', 'getByTag'), array($identifier, $backend));
- foreach (array('', 'abc def', 'foo!', 'bar:', 'some/', 'bla*', 'one+', 'äöü', str_repeat('x', 251), 'x$', '\\a', 'b#', 'some&') as $entryIdentifier) {
+ foreach (array('', 'abc def', 'foo!', 'bar:', 'some/', 'bla*', 'one+', 'äöü', str_repeat('x', 251), 'x$', '\\a', 'b#') as $entryIdentifier) {
$this->assertFalse($cache->isValidEntryIdentifier($entryIdentifier), 'Invalid identifier "' . $entryIdentifier . '" was not rejected.');
}
}
$identifier = 'someCacheIdentifier';
$backend = $this->getMock('t3lib_cache_backend_AbstractBackend', array(), array(), '', FALSE);
$cache = $this->getMock('t3lib_cache_frontend_StringFrontend', array('__construct', 'get', 'set', 'has', 'remove', 'getByTag'), array($identifier, $backend));
- foreach (array('_', 'abcdef', 'foo', 'bar123', '3some', '_bl_a', 'one%TWO', str_repeat('x', 250)) as $entryIdentifier) {
+ foreach (array('_', 'abcdef', 'foo', 'bar123', '3some', '_bl_a', 'some&', 'one%TWO', str_repeat('x', 250)) as $entryIdentifier) {
$this->assertTrue($cache->isValidEntryIdentifier($entryIdentifier), 'Valid identifier "' . $entryIdentifier . '" was not accepted.');
}
}
$identifier = 'someCacheIdentifier';
$backend = $this->getMock('t3lib_cache_backend_AbstractBackend', array(), array(), '', FALSE);
$cache = $this->getMock('t3lib_cache_frontend_StringFrontend', array('__construct', 'get', 'set', 'has', 'remove', 'getByTag'), array($identifier, $backend));
- foreach (array('', 'abc def', 'foo!', 'bar:', 'some/', 'bla*', 'one+', 'äöü', str_repeat('x', 251), 'x$', '\\a', 'b#', 'some&') as $tag) {
+ foreach (array('', 'abc def', 'foo!', 'bar:', 'some/', 'bla*', 'one+', 'äöü', str_repeat('x', 251), 'x$', '\\a', 'b#') as $tag) {
$this->assertFalse($cache->isValidTag($tag), 'Invalid tag "' . $tag . '" was not rejected.');
}
}
$identifier = 'someCacheIdentifier';
$backend = $this->getMock('t3lib_cache_backend_AbstractBackend', array(), array(), '', FALSE);
$cache = $this->getMock('t3lib_cache_frontend_StringFrontend', array('__construct', 'get', 'set', 'has', 'remove', 'getByTag'), array($identifier, $backend));
- foreach (array('abcdef', 'foo_baar', 'bar123', '3some', 'file%Thing', '%x%', str_repeat('x', 250)) as $tag) {
+ foreach (array('abcdef', 'foo-bar', 'foo_baar', 'bar123', '3some', 'file%Thing', 'some&', '%x%', str_repeat('x', 250)) as $tag) {
$this->assertTrue($cache->isValidTag($tag), 'Valid tag "' . $tag . '" was not accepted.');
}
}
class t3lib_cache_frontend_StringFrontendTestCase extends tx_phpunit_testcase {
/**
+ * @expectedException InvalidArgumentException
* @test
* @author Robert Lemke <robert@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function setChecksIfTheIdentifierIsValid() {
+ $cache = $this->getMock('t3lib_cache_frontend_StringFrontend', array('isValidEntryIdentifier'), array(), '', FALSE);
+ $cache->expects($this->once())->method('isValidEntryIdentifier')->with('foo')->will($this->returnValue(FALSE));
+ $cache->set('foo', 'bar');
+ }
+
+ /**
+ * @test
* @author Karsten Dambekalns <karsten@typo3.org>
* @author Ingo Renner <ingo@typo3.org>
*/
- public function setRejectsInvalidIdentifiers() {
+ public function setPassesStringToBackend() {
$theString = 'Just some value';
- $backend = $this->getMock('t3lib_cache_backend_Backend', array(), array(), '', FALSE);
- $backend->expects($this->never())->method('set');
+ $backend = $this->getMock('t3lib_cache_backend_AbstractBackend', array('get', 'set', 'has', 'remove', 'findIdentifiersByTag', 'findIdentifiersByTags', 'flush', 'flushByTag', 'flushByTags', 'collectGarbage'), array(), '', FALSE);
+ $backend->expects($this->once())->method('set')->with($this->equalTo('StringCacheTest'), $this->equalTo($theString));
$cache = new t3lib_cache_frontend_StringFrontend('StringFrontend', $backend);
-
- foreach (array('', 'abc def', 'foo!', 'bar:', 'some/', 'bla*', 'one+', 'äöü', str_repeat('x', 251), 'x$', '\\a', 'b#', 'some&') as $entryIdentifier) {
- try {
- $cache->set($entryIdentifier, $theString);
- $this->fail('set() did no reject the entry identifier "' . $entryIdentifier . '".');
- } catch (InvalidArgumentException $exception) {
- }
- }
+ $cache->set('StringCacheTest', $theString);
}
/**
* @author Karsten Dambekalns <karsten@typo3.org>
* @author Ingo Renner <ingo@typo3.org>
*/
- public function setPassesStringToBackend() {
+ public function setPassesLifetimeToBackend() {
$theString = 'Just some value';
+ $theLifetime = 1234;
$backend = $this->getMock('t3lib_cache_backend_AbstractBackend', array('get', 'set', 'has', 'remove', 'findIdentifiersByTag', 'findIdentifiersByTags', 'flush', 'flushByTag', 'flushByTags', 'collectGarbage'), array(), '', FALSE);
- $backend->expects($this->once())->method('set')->with($this->equalTo('StringCacheTest'), $this->equalTo($theString));
+ $backend->expects($this->once())->method('set')->with($this->equalTo('StringCacheTest'), $this->equalTo($theString), $this->equalTo(array()), $this->equalTo($theLifetime));
$cache = new t3lib_cache_frontend_StringFrontend('StringFrontend', $backend);
- $cache->set('StringCacheTest', $theString);
+ $cache->set('StringCacheTest', $theString, array(), $theLifetime);
}
/**
class t3lib_cache_frontend_VariableFrontendTestCase extends tx_phpunit_testcase {
/**
+ * @expectedException InvalidArgumentException
* @test
* @author Robert Lemke <robert@typo3.org>
- * @author Karsten Dambekalns <karsten@typo3.org>
* @author Ingo Renner <ingo@typo3.org>
*/
- public function setRejectsInvalidIdentifiers() {
- $theString = 'Just some value';
- $backend = $this->getMock('t3lib_cache_backend_Backend', array(), array(), '', FALSE);
- $backend->expects($this->never())->method('set');
-
- $cache = new t3lib_cache_frontend_VariableFrontend('VariableFrontend', $backend);
-
- foreach (array('', 'abc def', 'foo!', 'bar:', 'some/', 'bla*', 'one+', 'äöü', str_repeat('x', 251), 'x$', '\\a', 'b#', 'some&') as $entryIdentifier) {
- try {
- $cache->set($entryIdentifier, $theString);
- $this->fail('set() did no reject the entry identifier "' . $entryIdentifier . '".');
- } catch (InvalidArgumentException $exception) {
- }
- }
+ public function setChecksIfTheIdentifierIsValid() {
+ $cache = $this->getMock('t3lib_cache_frontend_StringFrontend', array('isValidEntryIdentifier'), array(), '', FALSE);
+ $cache->expects($this->once())->method('isValidEntryIdentifier')->with('foo')->will($this->returnValue(FALSE));
+ $cache->set('foo', 'bar');
}
/**
$cache->set('VariableCacheTest', $theArray);
}
+ /**
+ * @test
+ * @author Karsten Dambekalns <karsten@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function setPassesLifetimeToBackend() {
+ $theString = 'Just some value';
+ $theLifetime = 1234;
+ $backend = $this->getMock('t3lib_cache_backend_AbstractBackend', array('get', 'set', 'has', 'remove', 'findIdentifiersByTag', 'findIdentifiersByTags', 'flush', 'flushByTag', 'flushByTags', 'collectGarbage'), array(), '', FALSE);
+ $backend->expects($this->once())->method('set')->with($this->equalTo('VariableCacheTest'), $this->equalTo(serialize($theString)), $this->equalTo(array()), $this->equalTo($theLifetime));
+
+ $cache = new t3lib_cache_frontend_VariableFrontend('VariableFrontend', $backend);
+ $cache->set('VariableCacheTest', $theString, array(), $theLifetime);
+ }
+
/**
* @test
* @author Robert Lemke <robert@typo3.org>
--- /dev/null
+<?php
+/***************************************************************
+* Copyright notice
+*
+* (c) 2009 Ingo Renner <ingo@typo3.org>
+* All rights reserved
+*
+* This script is part of the TYPO3 project. The TYPO3 project is
+* free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* The GNU General Public License can be found at
+* http://www.gnu.org/copyleft/gpl.html.
+*
+* This script is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+
+require_once(PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_nullbackend.php');
+require_once('backend/class.t3lib_cache_backend_mockbackend.php');
+
+/**
+ * Testcase for the Cache Factory
+ *
+ * This file is a backport from FLOW3
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage tests
+ * @version $Id$
+ */
+class t3lib_cache_FactoryTestCase extends tx_phpunit_testcase {
+
+ /**
+ * Sets up this testcase
+ *
+ * @return void
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function setUp() {
+ $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheBackends']['t3lib_cache_backend_MockBackend'] = 'typo3_src/tests/t3lib/cache/backend/class.t3lib_cache_backend_mockbackend.php:t3lib_cache_backend_MockBackend';
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Karsten Dambekalns <karsten@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function createReturnsInstanceOfTheSpecifiedCacheFrontend() {
+ $backend = $this->getMock('t3lib_cache_backend_NullBackend', array(), array(), '', FALSE);
+ $cache = $this->getMock('t3lib_cache_frontend_VariableFrontend', array(), array(), '', FALSE);
+
+ $mockCacheManager = $this->getMock('t3lib_cache_Manager', array('registerCache'), array(), '', FALSE);
+ $factory = new t3lib_cache_Factory();
+ $factory->setCacheManager($mockCacheManager);
+
+ $cache = $factory->create('TYPO3_Cache_FactoryTest_Cache', 't3lib_cache_frontend_VariableFrontend', 't3lib_cache_backend_NullBackend');
+ $this->assertType('t3lib_cache_frontend_VariableFrontend', $cache);
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Karsten Dambekalns <karsten@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function createInjectsAnInstanceOfTheSpecifiedBackendIntoTheCacheFrontend() {
+ $backend = $this->getMock('t3lib_cache_backend_FileBackend', array(), array(), '', FALSE);
+ $cache = $this->getMock('t3lib_cache_frontend_VariableFrontend', array(), array(), '', FALSE);
+
+ $mockCacheManager = $this->getMock('t3lib_cache_Manager', array('registerCache'), array(), '', FALSE);
+ $factory = new t3lib_cache_Factory();
+ $factory->setCacheManager($mockCacheManager);
+
+ $factory->create('TYPO3_Cache_FactoryTest_Cache', 't3lib_cache_frontend_VariableFrontend', 't3lib_cache_backend_FileBackend');
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Karsten Dambekalns <karsten@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+ public function createPassesBackendOptionsToTheCreatedBackend() {
+ $someValue = microtime();
+ $backendOptions = array('someOption' => $someValue);
+
+ $cache = $this->getMock('t3lib_cache_frontend_VariableFrontend', array(), array(), '', FALSE);
+
+ $mockCacheManager = $this->getMock('t3lib_cache_Manager', array('registerCache'), array(), '', FALSE);
+ $factory = new t3lib_cache_Factory();
+ $factory->setCacheManager($mockCacheManager);
+
+ $cache = $factory->create('TYPO3_Cache_FactoryTest_Cache', 't3lib_cache_frontend_VariableFrontend', 't3lib_cache_backend_MockBackend', $backendOptions);
+
+ $this->assertEquals($someValue, $cache->getBackend()->getSomeOption(), 'create() did not pass the backend options to the backend.');
+ }
+
+ /**
+ * @test
+ * @author Robert Lemke <robert@typo3.org>
+ * @author Karsten Dambekalns <karsten@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+/*
+ Not working yet
+
+ public function createRegistersTheCacheAtTheCacheManager() {
+ $cacheIdentifier = 'TYPO3_Cache_FactoryTest_Cache';
+ $backend = $this->getMock('t3lib_cache_backend_NullBackend', array(), array(), '', FALSE);
+ $cache = $this->getMock('t3lib_cache_frontend_VariableFrontend', array('getCache'), array($cacheIdentifier, $backend), '', true);
+ $cache->getBackend()->setCache($cache);
+
+ $mockCacheManager = $this->getMock('t3lib_cache_Manager', array('registerCache'), array(), '', FALSE);
+ $mockCacheManager->expects($this->once())->method('registerCache')->with($cache);
+# $mockCacheManager->expects($this->once())->method('registerCache')->with('t3lib_cache_frontend_VariableFrontend');
+ $factory = new t3lib_cache_Factory();
+ $factory->setCacheManager($mockCacheManager);
+
+ $factory->create($cacheIdentifier, 't3lib_cache_frontend_VariableFrontend', 't3lib_cache_backend_NullBackend');
+ }
+*/
+}
+
+?>
\ No newline at end of file