Added feature #14666: Caching framework: Backport PhpFrontend from FLOW3 and refactor...
authorChristian Kuhn <lolli@schwarzbu.ch>
Wed, 9 Jun 2010 20:20:03 +0000 (20:20 +0000)
committerChristian Kuhn <lolli@schwarzbu.ch>
Wed, 9 Jun 2010 20:20:03 +0000 (20:20 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@7857 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
t3lib/cache/backend/class.t3lib_cache_backend_filebackend.php
t3lib/cache/backend/interfaces/interface.t3lib_cache_backend_phpcapablebackend.php [new file with mode: 0644]
t3lib/cache/frontend/class.t3lib_cache_frontend_phpfrontend.php [new file with mode: 0644]
t3lib/core_autoload.php
tests/t3lib/cache/backend/t3lib_cache_backend_filebackendtestcase.php
tests/t3lib/cache/frontend/t3lib_cache_frontend_phpfrontendtestcase.php [new file with mode: 0644]

index 267f1e7..df4f304 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -18,6 +18,7 @@
 
 2010-06-09  Christian Kuhn  <lolli@schwarzbu.ch>
 
+       * Added feature #14666: Caching framework: Backport PhpFrontend from FLOW3 and refactor FileBackend
        * Added feature #14655: Caching framework: Implement PDO backend
 
 2010-06-08  Stanislas Rolland  <typo3@sjbr.ca>
index 4a26d63..6873b24 100644 (file)
  * @api
  * @version $Id$
  */
-class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBackend {
+class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBackend implements t3lib_cache_backend_PhpCapableBackend {
 
        const SEPARATOR = '^';
 
        const EXPIRYTIME_FORMAT = 'YmdHis';
        const EXPIRYTIME_LENGTH = 14;
 
+       const DATASIZE_DIGITS = 10;
+
        /**
         * @var string Directory where the files are stored
         */
        protected $cacheDirectory = '';
 
+       /**
+        * @var string Absolute path to root, usually document root of website
+        */
        protected $root = '/';
 
        /**
         * Maximum allowed file path length in the current environment.
-        * Will be set in initializeObject()
         *
         * @var integer
         */
@@ -63,18 +67,28 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
        public function __construct(array $options = array()) {
                parent::__construct($options);
 
+               if (is_null($this->maximumPathLength)) {
+                       $this->maximumPathLength = t3lib_div::getMaximumPathLength();
+               }
+       }
+
+       /**
+        * Sets a reference to the cache frontend which uses this backend and
+        * initializes the default cache directory
+        *
+        * @void
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function setCache(t3lib_cache_frontend_frontend $cache) {
+               parent::setCache($cache);
+
                if (empty($this->cacheDirectory)) {
                        $cacheDirectory = 'typo3temp/cache/';
                        try {
                                $this->setCacheDirectory($cacheDirectory);
                        } catch(t3lib_cache_Exception $exception) {
-
                        }
                }
-
-               if (is_null($this->maximumPathLength)) {
-                       $this->maximumPathLength = t3lib_div::getMaximumPathLength();
-               }
        }
 
        /**
@@ -92,8 +106,6 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
                $documentRoot = PATH_site;
 
                if (($open_basedir = ini_get('open_basedir'))) {
-
-
                        if (TYPO3_OS === 'WIN') {
                                $delimiter = ';';
                                $cacheDirectory = str_replace('\\', '/', $cacheDirectory);
@@ -107,10 +119,9 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
                                        $cacheDirectory = PATH_site . $cacheDirectory;
                                }
                        }
-                       $basedirs = explode($delimiter, $open_basedir);
 
+                       $basedirs = explode($delimiter, $open_basedir);
                        $cacheDirectoryInBaseDir = FALSE;
-
                        foreach ($basedirs as $basedir) {
                                if (TYPO3_OS === 'WIN') {
                                        $basedir = str_replace('\\', '/', $basedir);
@@ -125,7 +136,6 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
                                        break;
                                }
                        }
-
                        if (!$cacheDirectoryInBaseDir) {
                                throw new t3lib_cache_Exception(
                                        'Open_basedir restriction in effect. The directory "' . $cacheDirectory . '" is not in an allowed path.'
@@ -133,17 +143,19 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
                        }
                } else {
                        if ($cacheDirectory[0] == '/') {
-                                       // absolute path to cache directory.
+                                       // Absolute path to cache directory.
                                $documentRoot = '/';
                        }
-
                        if (TYPO3_OS === 'WIN') {
                                $documentRoot = '';
                        }
                }
 
-               // after this point all paths have '/' as directory seperator
-
+                       // After this point all paths have '/' as directory seperator
+               if ($cacheDirectory[strlen($cacheDirectory) - 1] !== '/') {
+                       $cacheDirectory .= '/';
+               }
+               $cacheDirectory .= $this->cacheIdentifier;
                if ($cacheDirectory[strlen($cacheDirectory) - 1] !== '/') {
                        $cacheDirectory .= '/';
                }
@@ -154,14 +166,12 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
                                $cacheDirectory
                        );
                }
-
                if (!is_dir($documentRoot . $cacheDirectory)) {
                        throw new t3lib_cache_Exception(
                                'The directory "' . $documentRoot . $cacheDirectory . '" does not exist.',
                                1203965199
                        );
                }
-
                if (!is_writable($documentRoot . $cacheDirectory)) {
                        throw new t3lib_cache_Exception(
                                'The directory "' . $documentRoot . $cacheDirectory . '" is not writable.',
@@ -169,16 +179,6 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
                        );
                }
 
-               $tagsDirectory = $cacheDirectory . 'tags/';
-
-
-
-               if (!is_writable($documentRoot . $tagsDirectory)) {
-                       t3lib_div::mkdir_deep(
-                               $documentRoot,
-                               $tagsDirectory
-                       );
-               }
                $this->root = $documentRoot;
                $this->cacheDirectory =  $cacheDirectory;
        }
@@ -188,6 +188,7 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
         *
         * @return string Full path of the cache directory
         * @author Robert Lemke <robert@typo3.org>
+        * @api
         */
        public function getCacheDirectory() {
                return $this->root . $this->cacheDirectory;
@@ -196,14 +197,15 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
        /**
         * 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 Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited lifetime.
+        * @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 lifetime.
         * @return void
         * @throws t3lib_cache_Exception if the directory does not exist or is not writable or exceeds the maximum allowed path length, or if no cache frontend has been set.
         * @throws t3lib_cache_exception_InvalidData if the data to bes stored is not a string.
         * @author Robert Lemke <robert@typo3.org>
+        * @api
         */
        public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
                if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
@@ -220,157 +222,92 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
                        );
                }
 
-               $expirytime = $this->calculateExpiryTime($lifetime);
-               $cacheEntryPath = $this->renderCacheEntryPath($entryIdentifier);
-               $absCacheEntryPath = $this->root . $cacheEntryPath;
-
-
-               if (!is_writable($absCacheEntryPath)) {
-                       try {
-                               t3lib_div::mkdir_deep(
-                                       $this->root,
-                                       $cacheEntryPath
-                               );
-                       } catch(Exception $exception) {
-
-                       }
-
-                       if (!is_writable($absCacheEntryPath)) {
-                               throw new t3lib_cache_Exception(
-                                       'The cache directory "' . $absCacheEntryPath . '" could not be created.',
-                                       1204026250
-                               );
-                       }
-               }
-
                $this->remove($entryIdentifier);
 
-               $data = $expirytime->format(self::EXPIRYTIME_FORMAT) . $data;
-               $cacheEntryPathAndFilename = $absCacheEntryPath . uniqid() . '.temp';
-               if (strlen($cacheEntryPathAndFilename) > $this->maximumPathLength) {
+               $temporaryCacheEntryPathAndFilename = $this->root . $this->cacheDirectory . uniqid() . '.temp';
+               if (strlen($temporaryCacheEntryPathAndFilename) > $this->maximumPathLength) {
                        throw new t3lib_cache_Exception(
-                               'The length of the temporary cache file path "' . $cacheEntryPathAndFilename .
-                                       '" is ' . strlen($cacheEntryPathAndFilename) . ' characters long and exceeds the maximum path length of ' .
+                               'The length of the temporary cache file path "' . $temporaryCacheEntryPathAndFilename .
+                                       '" is ' . strlen($temporaryCacheEntryPathAndFilename) . ' characters long and exceeds the maximum path length of ' .
                                        $this->maximumPathLength . '. Please consider setting the temporaryDirectoryBase option to a shorter path. ',
                                1248710426
                        );
                }
-               $result = file_put_contents($cacheEntryPathAndFilename, $data);
+
+               $expiryTime = ($lifetime === NULL) ? 0 : ($GLOBALS['EXEC_TIME'] + $lifetime);
+               $metaData = str_pad($expiryTime, self::EXPIRYTIME_LENGTH) . implode(' ', $tags) . str_pad(strlen($data), self::DATASIZE_DIGITS);
+               $result = file_put_contents($temporaryCacheEntryPathAndFilename, $data . $metaData);
+
                if ($result === FALSE) {
-                       throw new t3lib_cache_Exception(
-                               'The temporary cache file "' . $cacheEntryPathAndFilename . '" could not be written.',
+                       throw new t3lib_cache_exception(
+                               'The temporary cache file "' . $temporaryCacheEntryPathAndFilename . '" could not be written.',
                                1204026251
                        );
                }
 
-               for ($i = 0; $i < 5; $i++) {
-                       $result = rename($cacheEntryPathAndFilename, $absCacheEntryPath . $entryIdentifier);
-                       if ($result === TRUE) {
-                               break;
-                       }
+               $i = 0;
+               $cacheEntryPathAndFilename = $this->root . $this->cacheDirectory . $entryIdentifier;
+                       // @TODO: Figure out why the heck this is done and maybe find a smarter solution, report to FLOW3
+               while (!rename($temporaryCacheEntryPathAndFilename, $cacheEntryPathAndFilename) && $i < 5) {
+                       $i++;
                }
 
+                       // @FIXME: At least the result of rename() should be handled here, report to FLOW3
                if ($result === FALSE) {
-                       throw new t3lib_cache_Exception(
-                               'The cache file "' . $entryIdentifier . '" could not be written.',
+                       throw new t3lib_cache_exception(
+                               'The cache file "' . $cacheEntryPathAndFilename . '" could not be written.',
                                1222361632
                        );
                }
-
-               foreach ($tags as $tag) {
-                       $this->setTag($entryIdentifier, $tag);
-               }
-       }
-
-       /**
-        * Creates a tag that is associated with the given cache identifier
-        *
-        * @param string $entryIdentifier An identifier for this specific cache entry
-        * @param string $tag Tag to associate with this cache entry
-        * @return void
-        * @throws t3lib_cache_Exception if the tag path is not writable or exceeds the maximum allowed path length
-        * @author Bastian Waidelich <bastian@typo3.org>
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       protected function setTag($entryIdentifier, $tag) {
-               $tagPath = $this->cacheDirectory . 'tags/' . $tag . '/';
-               $absTagPath = $this->root . $tagPath;
-               if (!is_writable($absTagPath)) {
-                       t3lib_div::mkdir_deep($this->root, $tagPath);
-                       if (!is_writable($absTagPath)) {
-                               throw new t3lib_cache_Exception(
-                                       'The tag directory "' . $absTagPath . '" could not be created.',
-                                       1238242144
-                               );
-                       }
-               }
-
-               $tagPathAndFilename = $absTagPath . $this->cacheIdentifier
-                       . self::SEPARATOR . $entryIdentifier;
-               if (strlen($tagPathAndFilename) > $this->maximumPathLength) {
-                       throw new t3lib_cache_Exception(
-                               'The length of the tag path "' . $tagPathAndFilename . '" is ' . strlen($tagPathAndFilename) .
-                                       ' characters long and exceeds the maximum path length of ' . $this->maximumPathLength .
-                                       '. Please consider setting the temporaryDirectoryBase option to a shorter path. ',
-                               1248710426
-                       );
-               }
-               touch($tagPathAndFilename);
        }
 
        /**
         * Loads data from a cache file.
         *
-        * @param string An identifier which describes the cache entry to load
+        * @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>
         * @author Karsten Dambekalns <karsten@typo3.org>
+        * @api
         */
        public function get($entryIdentifier) {
-               $pathAndFilename = $this->root . $this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier;
-               return ($this->isCacheFileExpired($pathAndFilename)) ? FALSE : file_get_contents($pathAndFilename, NULL, NULL, self::EXPIRYTIME_LENGTH);
+               $pathAndFilename = $this->root . $this->cacheDirectory . $entryIdentifier;
+               if ($this->isCacheFileExpired($pathAndFilename)) {
+                       return FALSE;
+               }
+               $dataSize = (integer)file_get_contents($pathAndFilename, NULL, NULL, filesize($pathAndFilename) - self::DATASIZE_DIGITS, self::DATASIZE_DIGITS);
+               return file_get_contents($pathAndFilename, NULL, NULL, 0, $dataSize);
        }
 
        /**
         * Checks if a cache entry with the specified identifier exists.
         *
-        * @param       string $entryIdentifier
-        * @return      boolean TRUE if such an entry exists, FALSE if not
+        * @param string $entryIdentifier 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 Robert Lemke <robert@typo3.org>
+        * @api
         */
        public function has($entryIdentifier) {
-               return !$this->isCacheFileExpired($this->root . $this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier);
+               return !$this->isCacheFileExpired($this->root . $this->cacheDirectory . $entryIdentifier);
        }
 
        /**
         * Removes all cache entries matching the specified identifier.
         * Usually this only affects one entry.
         *
-        * @param string Specifies the cache entry to remove
+        * @param string $entryIdentifier 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 Robert Lemke <robert@typo3.org>
+        * @api
         */
        public function remove($entryIdentifier) {
-               $pathAndFilename = $this->root . $this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier;
-
+               $pathAndFilename = $this->root . $this->cacheDirectory . $entryIdentifier;
                if (!file_exists($pathAndFilename)) {
                        return FALSE;
                }
-
                if (unlink($pathAndFilename) === FALSE) {
                        return FALSE;
                }
-
-               foreach($this->findTagFilesByEntry($entryIdentifier) as $pathAndFilename) {
-                       if (!file_exists($pathAndFilename)) {
-                               return FALSE;
-                       }
-
-                       if (unlink($pathAndFilename) === FALSE) {
-                               return FALSE;
-                       }
-               }
-
                return TRUE;
        }
 
@@ -378,63 +315,63 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
         * Finds and returns all cache entry identifiers which are tagged by the
         * specified tag.
         *
-        * @param string The tag to search for
+        * @param string $searchedTag 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>
         * @author Karsten Dambekalns <karsten@typo3.org>
+        * @api
         */
-       public function findIdentifiersByTag($tag) {
-               if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
-                       throw new t3lib_cache_Exception(
-                               'Yet no cache frontend has been set via setCache().',
-                               1204111376
-                       );
-               }
-
-               $path = $this->root . $this->cacheDirectory . 'tags/';
-               $pattern = $path . $tag . '/' . $this->cacheIdentifier . self::SEPARATOR . '*';
-               $filesFound = glob($pattern);
-
-               if ($filesFound === FALSE || count($filesFound) === 0) {
-                       return array();
-               }
+       public function findIdentifiersByTag($searchedTag) {
+               $entryIdentifiers = array();
+               $now = $GLOBALS['EXEC_TIME'];
+               for ($directoryIterator = t3lib_div::makeInstance('DirectoryIterator', $this->root . $this->cacheDirectory); $directoryIterator->valid(); $directoryIterator->next()) {
+                       if ($directoryIterator->isDot()) {
+                               continue;
+                       }
+                       $cacheEntryPathAndFilename = $directoryIterator->getPathname();
+                       $index = (integer)file_get_contents($cacheEntryPathAndFilename, NULL, NULL, filesize($cacheEntryPathAndFilename) - self::DATASIZE_DIGITS, self::DATASIZE_DIGITS);
+                       $metaData = file_get_contents($cacheEntryPathAndFilename, NULL, NULL, $index);
 
-               $cacheEntries = array();
-               foreach ($filesFound as $filename) {
-                       list(,$entryIdentifier) = explode(self::SEPARATOR, basename($filename));
-                       if ($this->has($entryIdentifier)) {
-                               $cacheEntries[$entryIdentifier] = $entryIdentifier;
+                       $expiryTime = (integer)substr($metaData, 0, self::EXPIRYTIME_LENGTH);
+                       if ($expiryTime !== 0 && $expiryTime < $now) {
+                               continue;
+                       }
+                       if (in_array($searchedTag, explode(' ', substr($metaData, self::EXPIRYTIME_LENGTH, -self::DATASIZE_DIGITS)))) {
+                               $entryIdentifiers[] = $directoryIterator->getFilename();
                        }
                }
-
-               return array_values($cacheEntries);
+               return $entryIdentifiers;
        }
 
        /**
         * Finds and returns all cache entry identifiers which are tagged by the
         * specified tags.
         *
-        * @param array Array of tags to search for
+        * @param array $searchedTags Array of tags to search for
         * @return array An array with identifiers of all matching entries. An empty array if no entries matched
         * @author Ingo Renner <ingo@typo3.org>
+        * @author Christian Kuhn <lolli@schwarzbu.ch>
+        * @api
         */
-       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);
+       public function findIdentifiersByTags(array $searchedTags) {
+               $entryIdentifiers = array();
+               for ($directoryIterator = t3lib_div::makeInstance('DirectoryIterator', $this->root . $this->cacheDirectory); $directoryIterator->valid(); $directoryIterator->next()) {
+                       if ($directoryIterator->isDot()) {
+                               continue;
+                       }
+                       $cacheEntryPathAndFilename = $directoryIterator->getPathname();
+                       $index = (integer)file_get_contents($cacheEntryPathAndFilename, NULL, NULL, filesize($cacheEntryPathAndFilename) - self::DATASIZE_DIGITS, self::DATASIZE_DIGITS);
+                       $metaData = file_get_contents($cacheEntryPathAndFilename, NULL, NULL, $index);
 
-               foreach ($intersectedTaggedEntries as $entryIdentifier) {
-                       if ($this->has($entryIdentifier)) {
-                               $foundEntries[$entryIdentifier] = $entryIdentifier;
+                       $expiryTime = (integer)substr($metaData, 0, self::EXPIRYTIME_LENGTH);
+                       if ($expiryTime !== 0 && $expiryTime < $GLOBALS['EXEC_TIME']) {
+                               continue;
+                       }
+                       if (in_array($searchedTags, explode(' ', substr($metaData, self::EXPIRYTIME_LENGTH, -self::DATASIZE_DIGITS)))) {
+                               $entryIdentifiers[] = $directoryIterator->getFilename();
                        }
                }
-
-               return $foundEntries;
+               return $entryIdentifiers;
        }
 
        /**
@@ -442,28 +379,20 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
         *
         * @return void
         * @author Robert Lemke <robert@typo3.org>
+        * @author Christian Kuhn <lolli@schwarzbu.ch>
+        * @api
         */
        public function flush() {
-               if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
-                       throw new t3lib_cache_Exception(
-                               'Yet no cache frontend has been set via setCache().',
-                               1204111376
-                       );
-               }
-
-               $dataPath = $this->root . $this->cacheDirectory . 'data/' . $this->cacheIdentifier . '/';
-               $tagsPath = $this->root . $this->cacheDirectory . 'tags/';
-
-               t3lib_div::rmdir($dataPath, true);
-               t3lib_div::rmdir($tagsPath, true);
+               t3lib_div::rmdir($this->root . $this->cacheDirectory, TRUE);
        }
 
        /**
         * Removes all cache entries of this cache which are tagged by the specified tag.
         *
-        * @param string The tag the entries must have
+        * @param string $tag The tag the entries must have
         * @return void
         * @author Ingo Renner <ingo@typo3.org>
+        * @api
         */
        public function flushByTag($tag) {
                $identifiers = $this->findIdentifiersByTag($tag);
@@ -479,9 +408,10 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
        /**
         * Removes all cache entries of this cache which are tagged by the specified tag.
         *
-        * @param array The tags the entries must have
+        * @param array $tags The tags the entries must have
         * @return void
         * @author Ingo Renner <ingo@typo3.org>
+        * @api
         */
        public function flushByTags(array $tags) {
                foreach ($tags as $tag) {
@@ -493,13 +423,17 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
         * Checks if the given cache entry files are still valid or if their
         * lifetime has exceeded.
         *
-        * @param       string  $cacheFilename
-        * @return      boolean
+        * @param string $cacheEntryPathAndFilename
+        * @return boolean
         * @author Robert Lemke <robert@typo3.org>
         */
-       protected function isCacheFileExpired($cacheFilename) {
-               $timestamp = (file_exists($cacheFilename)) ? file_get_contents($cacheFilename, NULL, NULL, 0, self::EXPIRYTIME_LENGTH) : 1;
-               return $timestamp < gmdate(self::EXPIRYTIME_FORMAT);
+       protected function isCacheFileExpired($cacheEntryPathAndFilename) {
+               if (!file_exists($cacheEntryPathAndFilename)) {
+                       return TRUE;
+               }
+               $index = (integer)file_get_contents($cacheEntryPathAndFilename, NULL, NULL, filesize($cacheEntryPathAndFilename) - self::DATASIZE_DIGITS, self::DATASIZE_DIGITS);
+               $expiryTime = file_get_contents($cacheEntryPathAndFilename, NULL, NULL, $index, self::EXPIRYTIME_LENGTH);
+               return ($expiryTime != 0 && $expiryTime < $GLOBALS['EXEC_TIME']);
        }
 
        /**
@@ -507,6 +441,7 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
         *
         * @return void
         * @author Karsten Dambekalns <karsten@typo3.org>
+        * @api
         */
        public function collectGarbage() {
                if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
@@ -516,28 +451,16 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
                        );
                }
 
-               $pattern = $this->root . $this->cacheDirectory . 'data/' . $this->cacheIdentifier . '/*/*/*';
+               $pattern = $this->root . $this->cacheDirectory . '*';
                $filesFound = glob($pattern);
 
-               foreach ($filesFound as $cacheFilename) {
-                       if ($this->isCacheFileExpired($cacheFilename)) {
-                               $this->remove(basename($cacheFilename));
+               if (is_array($filesFound)) {
+                       foreach ($filesFound as $cacheFilename) {
+                               if ($this->isCacheFileExpired($cacheFilename)) {
+                                       $this->remove(basename($cacheFilename));
+                               }
                        }
-               }
-       }
-
-       /**
-        * Renders the full path (excluding file name) leading to the given cache entry.
-        * Doesn't check if such a cache entry really exists.
-        *
-        * @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 $this->cacheDirectory . 'data/' . $this->cacheIdentifier . '/' . $identifierHash[0] . '/' . $identifierHash[1] . '/';
+               }
        }
 
        /**
@@ -559,7 +482,7 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
                        );
                }
 
-               $pattern = $this->root . $this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier;
+               $pattern = $this->root . $this->cacheDirectory . $entryIdentifier;
                $filesFound = glob($pattern);
                if ($filesFound === FALSE || count($filesFound) === 0) {
                        return FALSE;
@@ -568,28 +491,16 @@ class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBacken
                return $filesFound;
        }
 
-
        /**
-        * Tries to find the tag entries for the specified cache entry.
+        * Loads PHP code from the cache and require_onces it right away.
         *
-        * @param string $entryIdentifier The cache entry identifier to find tag files for
-        * @return array The file names (including path)
-        * @author Robert Lemke <robert@typo3.org>
-        * @throws t3lib_cache_Exception if no frontend has been set
-        * @internal
+        * @param string $entryIdentifier An identifier which describes the cache entry to load
+        * @return mixed Potential return value from the include operation
+        * @api
         */
-       protected function findTagFilesByEntry($entryIdentifier) {
-               if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
-                       throw new t3lib_cache_Exception(
-                               'Yet no cache frontend has been set via setCache().',
-                               1204111376
-                       );
-               }
-
-               $path = $this->root . $this->cacheDirectory . 'tags/';
-               $pattern = $path . '*/' . $this->cacheIdentifier . self::SEPARATOR . $entryIdentifier;
-               $tagFilesFound = glob($pattern);
-               return ($tagFilesFound ? $tagFilesFound : array());
+       public function requireOnce($entryIdentifier) {
+               $pathAndFilename = $this->root . $this->cacheDirectory . $entryIdentifier;
+               return ($this->isCacheFileExpired($pathAndFilename)) ? FALSE : require_once($pathAndFilename);
        }
 }
 
diff --git a/t3lib/cache/backend/interfaces/interface.t3lib_cache_backend_phpcapablebackend.php b/t3lib/cache/backend/interfaces/interface.t3lib_cache_backend_phpcapablebackend.php
new file mode 100644 (file)
index 0000000..832cf18
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Christian Kuhn <lolli@schwarzbu.ch>
+*  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.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  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 contract for a cache backend which is capable of storing, retrieving and
+ * including PHP source code.
+ *
+ * @version $Id$
+ * @api
+ * @author Robert Lemke <robert@typo3.org>
+ */
+interface t3lib_cache_backend_PhpCapableBackend extends t3lib_cache_backend_Backend {
+
+       /**
+        * Loads PHP code from the cache and require_onces it right away.
+        *
+        * @param string $entryIdentifier An identifier which describes the cache entry to load
+        * @return mixed Potential return value from the include operation
+        * @api
+        */
+       public function requireOnce($entryIdentifier);
+
+}
+
+?>
diff --git a/t3lib/cache/frontend/class.t3lib_cache_frontend_phpfrontend.php b/t3lib/cache/frontend/class.t3lib_cache_frontend_phpfrontend.php
new file mode 100644 (file)
index 0000000..24d6852
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Christian Kuhn <lolli@schwarzbu.ch>
+*  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 cache frontend tailored to PHP code.
+ *
+ * This file is a backport from FLOW3
+ *
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @api
+ * @scope prototype
+ * @version $Id$
+ */
+class t3lib_cache_frontend_PhpFrontend extends t3lib_cache_frontend_StringFrontend {
+       /**
+        * Constructs the cache
+        *
+        * @param string $identifier A identifier which describes this cache
+        * @param t3lib_cache_backend_PhpCapableBackend $backend Backend to be used for this cache
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function __construct($identifier, t3lib_cache_backend_PhpCapableBackend $backend) {
+               parent::__construct($identifier, $backend);
+       }
+
+       /**
+        * Saves the PHP source code in the cache.
+        *
+        * @param string $entryIdentifier An identifier used for this cache entry, for example the class name
+        * @param string $sourceCode PHP source code
+        * @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
+        * @author Robert Lemke <robert@typo3.org>
+        * @api
+        */
+       public function set($entryIdentifier, $sourceCode, $tags = array(), $lifetime = NULL) {
+               if (!$this->isValidEntryIdentifier($entryIdentifier)) {
+                       throw new InvalidArgumentException(
+                               '"' . $entryIdentifier . '" is not a valid cache entry identifier.',
+                               1264023823
+                       );
+               }
+               if (!is_string($sourceCode)) {
+                       throw new t3lib_cache_exception_InvalidData(
+                               'The given source code is not a valid string.',
+                               1264023824
+                       );
+               }
+               foreach ($tags as $tag) {
+                       if (!$this->isValidTag($tag)) {
+                               throw new InvalidArgumentException(
+                                       '"' . $tag . '" is not a valid tag for a cache entry.',
+                                       1264023825
+                               );
+                       }
+               }
+               $sourceCode = '<?php' . chr(10) . $sourceCode . chr(10) . '__halt_compiler();';
+               $this->backend->set($entryIdentifier, $sourceCode, $tags, $lifetime);
+       }
+
+       /**
+        * Loads PHP code from the cache and require_onces it right away.
+        *
+        * @param string $entryIdentifier An identifier which describes the cache entry to load
+        * @return mixed Potential return value from the include operation
+        * @author Robert Lemke <robert@typo3.org>
+        * @api
+        */
+       public function requireOnce($entryIdentifier) {
+               return $this->backend->requireOnce($entryIdentifier);
+       }
+}
+
+if (defined('TYPO3_MODE') && $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_frontend_phpfrontend.php']) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_frontend_phpfrontend.php']);
+}
+
+?>
index f47d7ee..421e09c 100644 (file)
@@ -94,6 +94,7 @@ return array(
        't3lib_cache_backend_pdobackend' => PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_pdobackend.php',
        't3lib_cache_backend_transientmemorybackend' => PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_transientmemorybackend.php',
        't3lib_cache_backend_backend' => PATH_t3lib . 'cache/backend/interfaces/interface.t3lib_cache_backend_backend.php',
+       't3lib_cache_backend_phpcapablebackend' => PATH_t3lib . 'cache/backend/interfaces/interface.t3lib_cache_backend_phpcapablebackend.php',
        't3lib_cache_exception_classalreadyloaded' => PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_classalreadyloaded.php',
        't3lib_cache_exception_duplicateidentifier' => PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_duplicateidentifier.php',
        't3lib_cache_exception_invalidbackend' => PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invalidbackend.php',
@@ -101,6 +102,7 @@ return array(
        't3lib_cache_exception_invaliddata' => PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invaliddata.php',
        't3lib_cache_exception_nosuchcache' => PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_nosuchcache.php',
        't3lib_cache_frontend_abstractfrontend' => PATH_t3lib . 'cache/frontend/class.t3lib_cache_frontend_abstractfrontend.php',
+       't3lib_cache_frontend_phpfrontend' => PATH_t3lib . 'cache/frontend/class.t3lib_cache_frontend_phpfrontend.php',
        't3lib_cache_frontend_stringfrontend' => PATH_t3lib . 'cache/frontend/class.t3lib_cache_frontend_stringfrontend.php',
        't3lib_cache_frontend_variablefrontend' => PATH_t3lib . 'cache/frontend/class.t3lib_cache_frontend_variablefrontend.php',
        't3lib_cache_frontend_frontend' => PATH_t3lib . 'cache/frontend/interfaces/interface.t3lib_cache_frontend_frontend.php',
index e1c9fd5..b78471c 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2009 Ingo Renner <ingo@typo3.org>
+*  (c) 2009-2010 Ingo Renner <ingo@typo3.org>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -50,12 +50,19 @@ require_once(PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_filebackend.p
  *
  * This file is a backport from FLOW3
  *
- * @author     Ingo Renner <ingo@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ * @author Christian Kuhn <lolli@schwarzbu.ch>
  * @package TYPO3
  * @subpackage tests
  * @version $Id$
  */
 class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
+       /**
+        * Backup of global variable EXEC_TIME
+        *
+        * @var array
+        */
+       protected $backupGlobalVariables;
 
        /**
         * If set, the tearDown() method will clean up the cache subdirectory used by this unit test.
@@ -64,6 +71,9 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         */
        protected $backend;
 
+       /**
+        * @var string Directory for testing data, relative to PATH_site
+        */
        protected $testingCacheDirectory;
 
        /**
@@ -72,6 +82,10 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @return void
         */
        public function setUp() {
+               $this->backupGlobalVariables = array(
+                       'EXEC_TIME' => $GLOBALS['EXEC_TIME'],
+               );
+
                $this->testingCacheDirectory = 'typo3temp/cache/testing/';
 
                $this->backend = t3lib_div::makeInstance(
@@ -110,7 +124,7 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @author Robert Lemke <robert@typo3.org>
         * @author Ingo Renner <ingo@typo3.org>
         */
-       public function getCacheDirectoryReturnsThePreviouslySetDirectory() {
+       public function getCacheDirectoryReturnsTheCurrentCacheDirectory() {
                $directory = $this->testingCacheDirectory;
                $fullPathToDirectory = t3lib_div::getIndpEnv('TYPO3_DOCUMENT_ROOT') . '/' . $directory;
 
@@ -125,18 +139,13 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @expectedException t3lib_cache_exception_InvalidData
         */
        public function setThrowsExceptionIfDataIsNotAString() {
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
+               $this->backend->setCache($mockCache);
                $data = array('Some data');
                $entryIdentifier = 'BackendFileTest';
 
-               $this->backend->setCache($cache);
-
                $this->backend->set($entryIdentifier, $data);
        }
 
@@ -146,39 +155,19 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @author Ingo Renner <ingo@typo3.org>
         */
        public function setReallySavesToTheSpecifiedDirectory() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
                $data = 'some data' . microtime();
                $entryIdentifier = 'BackendFileTest';
-               $entryIdentifierHash = sha1($entryIdentifier);
+               $this->backend->setCache($mockCache);
+               $pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
 
-               $this->backend->setCache($cache);
-               $this->backend->set($entryIdentifier, $data);
+               $this->backend->set($entryIdentifier, $data, array(), 10);
 
-               $cacheDirectory = $this->backend->getCacheDirectory();
-               $pathAndFilename = $cacheDirectory
-                       . 'data/'
-                       . $cacheIdentifier . '/'
-                       . $entryIdentifierHash[0] . '/'
-                       . $entryIdentifierHash[1] . '/'
-                       . $entryIdentifier;
-               $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,
-                       'The original and the retrieved data don\'t match.'
-               );
+               $this->assertFileExists($pathAndFilename);
+               $retrievedData = file_get_contents($pathAndFilename, NULL, NULL, 0, strlen($data));
+               $this->assertEquals($data, $retrievedData);
        }
 
        /**
@@ -187,37 +176,23 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @author Ingo Renner <ingo@typo3.org>
         */
        public function setOverwritesAnAlreadyExistingCacheEntryForTheSameIdentifier() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
                $data1 = 'some data' . microtime();
                $data2 = 'some data' . microtime();
                $entryIdentifier = 'BackendFileRemoveBeforeSetTest';
-               $entryIdentifierHash = sha1($entryIdentifier);
 
-               $this->backend->setCache($cache);
+               $this->backend->setCache($mockCache);
                $this->backend->set($entryIdentifier, $data1, array(), 500);
-                       // setting a second entry with the same identifier, but different
+                       // Setting a second entry with the same identifier, but different
                        // data, this should _replace_ the existing one we set before
                $this->backend->set($entryIdentifier, $data2, array(), 200);
 
-               $cacheDirectory = $this->backend->getCacheDirectory();
-               $pathAndFilename = $cacheDirectory
-                       . 'data/'
-                       . $cacheIdentifier . '/'
-                       . $entryIdentifierHash[0] . '/'
-                       . $entryIdentifierHash[1] . '/'
-                       . $entryIdentifier;
-               $this->assertTrue(file_exists($pathAndFilename), 'File does not exist.');
-               $retrievedData = file_get_contents($pathAndFilename, NULL, NULL, t3lib_cache_backend_FileBackend::EXPIRYTIME_LENGTH);
+               $pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
+
+               $this->assertFileExists($pathAndFilename);
+               $retrievedData = file_get_contents($pathAndFilename, NULL, NULL, 0, strlen($data2));
                $this->assertEquals($data2, $retrievedData);
        }
 
@@ -226,67 +201,62 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @author Robert Lemke <robert@typo3.org>
         * @author Ingo Renner <ingo@typo3.org>
         */
-       public function setReallySavesSpecifiedTags() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
+       public function setAlsoSavesSpecifiedTags() {
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
                $data = 'some data' . microtime();
                $entryIdentifier = 'BackendFileTest';
-               $entryIdentifierHash = sha1($entryIdentifier);
-
-               $this->backend->setCache($cache);
-               $tagsDirectory = $this->backend->getCacheDirectory() . 'tags/';
-
-               $this->backend->set($entryIdentifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
 
-               $this->assertTrue(is_dir($tagsDirectory . 'UnitTestTag%tag1'), 'Tag directory UnitTestTag%tag1 does not exist.');
-               $this->assertTrue(is_dir($tagsDirectory . 'UnitTestTag%tag2'), 'Tag directory UnitTestTag%tag2 does not exist.');
+               $this->backend->setCache($mockCache);
+               $this->backend->set($entryIdentifier, $data, array('Tag1', 'Tag2'));
 
-               $filename = $tagsDirectory . 'UnitTestTag%tag1/' . $cacheIdentifier . t3lib_cache_backend_FileBackend::SEPARATOR . $entryIdentifier;
-               $this->assertTrue(file_exists($filename), 'File "' . $filename . '" does not exist.');
-
-               $filename = $tagsDirectory . 'UnitTestTag%tag2/' . $cacheIdentifier . t3lib_cache_backend_FileBackend::SEPARATOR . $entryIdentifier;
-               $this->assertTrue(file_exists($filename), 'File "' . $filename . '" does not exist.');
+               $pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
+               $this->assertFileExists($pathAndFilename);
+               $retrievedData = file_get_contents($pathAndFilename, NULL, NULL, (strlen($data) + t3lib_cache_backend_FileBackend::EXPIRYTIME_LENGTH), 9);
+               $this->assertEquals('Tag1 Tag2', $retrievedData);
        }
 
        /**
         * @test
         * @author Robert Lemke <robert@typo3.org>
+        * @author Karsten Dambekalns <karsten@typo3.org>
         * @author Ingo Renner <ingo@typo3.org>
         */
-       public function getReturnsContentOfTheCorrectCacheFile() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
-
-               $this->backend->setCache($cache);
+       public function setWithUnlimitedLifetimeWritesCorrectEntry() {
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
+               $data = 'some data' . microtime();
                $entryIdentifier = 'BackendFileTest';
 
-               $data = 'some data' . microtime();
-               $this->backend->set($entryIdentifier, $data, array(), 500);
+               $this->backend->setCache($mockCache);
+               $pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
+
+               $this->backend->set($entryIdentifier, $data, array(), 0);
+
+               $this->assertFileExists($pathAndFilename);
 
-               $data = 'some other data' . microtime();
-               $this->backend->set($entryIdentifier, $data, array(), 100);
+               $dataSize = (integer)file_get_contents($pathAndFilename, NULL, NULL, filesize($pathAndFilename) - t3lib_cache_backend_FileBackend::DATASIZE_DIGITS, t3lib_cache_backend_FileBackend::DATASIZE_DIGITS);
+               $retrievedData = file_get_contents($pathAndFilename, NULL, NULL, 0, $dataSize);
 
-               $loadedData = $this->backend->get($entryIdentifier);
+               $this->assertEquals($data, $retrievedData, 'The original and the retrieved data don\'t match.');
+       }
+
+       /**
+        * @test
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function getReturnsFalseForExpiredEntries() {
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
+
+               $backend = $this->getMock('t3lib_cache_backend_FileBackend', array('isCacheFileExpired'), array(), '', FALSE);
+               $fullPathToCacheFile = t3lib_div::getIndpEnv('TYPO3_DOCUMENT_ROOT') . '/typo3temp/cache/UnitTestCache/ExpiredEntry';
+               $backend->expects($this->once())->method('isCacheFileExpired')->with($fullPathToCacheFile)->will($this->returnValue(TRUE));
+               $backend->setCache($mockCache);
 
-               $this->assertEquals($data, $loadedData, 'The original and the retrieved data don\'t match.');
+               $this->assertFalse($backend->get('ExpiredEntry'));
        }
 
        /**
@@ -294,22 +264,13 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @author Robert Lemke <robert@typo3.org>
         * @author Ingo Renner <ingo@typo3.org>
         */
-       public function hasReturnsTheCorrectResult() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
+       public function hasReturnsTrueIfAnEntryExists() {
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
-               $this->backend->setCache($cache);
+               $this->backend->setCache($mockCache);
 
                $entryIdentifier = 'BackendFileTest';
-
                $data = 'some data' . microtime();
                $this->backend->set($entryIdentifier, $data);
 
@@ -320,39 +281,34 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
        /**
         * @test
         * @author Robert Lemke <robert@typo3.org>
+        */
+       public function hasReturnsFalseForExpiredEntries() {
+               $backend = $this->getMock('t3lib_cache_backend_FileBackend', array('isCacheFileExpired'), array(), '', FALSE);
+               $backend->expects($this->exactly(2))->method('isCacheFileExpired')->will($this->onConsecutiveCalls(TRUE, FALSE));
+
+               $this->assertFalse($backend->has('foo'));
+               $this->assertTrue($backend->has('bar'));
+       }
+
+       /**
+        * @test
+        * @author Robert Lemke <robert@typo3.org>
         * @author Ingo Renner <ingo@typo3.org>
         */
        public function removeReallyRemovesACacheEntry() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
                $data = 'some data' . microtime();
-               $entryIdentifier = 'BackendFileRemovalTest';
-               $entryIdentifierHash = sha1($entryIdentifier);
-
-               $cacheDirectory = $this->backend->getCacheDirectory();
-               $this->backend->setCache($cache);
-
-               $pathAndFilename = $cacheDirectory
-                       . 'data/'
-                       . $cacheIdentifier . '/'
-                       . $entryIdentifierHash[0] . '/'
-                       . $entryIdentifierHash[1] . '/'
-                       . $entryIdentifier;
+               $entryIdentifier = 'BackendFileTest';
 
+               $this->backend->setCache($mockCache);
+               $pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
                $this->backend->set($entryIdentifier, $data);
-               $this->assertTrue(file_exists($pathAndFilename), 'The cache entry does not exist.');
 
+               $this->assertFileExists($pathAndFilename);
                $this->backend->remove($entryIdentifier);
-               $this->assertFalse(file_exists($pathAndFilename), 'The cache entry still exists.');
+               $this->assertFileNotExists($pathAndFilename);
        }
 
        /**
@@ -362,38 +318,22 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @author Ingo Renner <ingo@typo3.org>
         */
        public function collectGarbageReallyRemovesAnExpiredCacheEntry() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
                $data = 'some data' . microtime();
                $entryIdentifier = 'BackendFileRemovalTest';
-               $entryIdentifierHash = sha1($entryIdentifier);
-
-               $cacheDirectory = $this->backend->getCacheDirectory();
-               $this->backend->setCache($cache);
-
-               $pathAndFilename = $cacheDirectory
-                       . 'data/'
-                       . $cacheIdentifier . '/'
-                       . $entryIdentifierHash[0] . '/'
-                       . $entryIdentifierHash[1] . '/'
-                       . $entryIdentifier;
 
+               $this->backend->setCache($mockCache);
+               $pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
                $this->backend->set($entryIdentifier, $data, array(), 1);
-               $this->assertTrue(file_exists($pathAndFilename), 'The cache entry does not exist.');
 
-               sleep(2);
+               $this->assertFileExists($pathAndFilename);
 
+               $GLOBALS['EXEC_TIME'] += 2;
                $this->backend->collectGarbage();
-               $this->assertFalse(file_exists($pathAndFilename), 'The cache entry still exists.');
+
+               $this->assertFileNotExists($pathAndFilename);
        }
 
        /**
@@ -403,40 +343,32 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @author Ingo Renner <ingo@typo3.org>
         */
        public function collectGarbageReallyRemovesAllExpiredCacheEntries() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
                $data = 'some data' . microtime();
                $entryIdentifier = 'BackendFileRemovalTest';
 
-               $cacheDirectory = $this->backend->getCacheDirectory();
-               $this->backend->setCache($cache);
+               $this->backend->setCache($mockCache);
+               $pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
 
-               $pattern = $cacheDirectory
-                       . 'data/'
-                       . $cacheIdentifier . '/*/*/'
-                       . $entryIdentifier
-                       . '?';
-
-               $this->backend->set($entryIdentifier . 'A', $data, array(), 1);
-               $this->backend->set($entryIdentifier . 'B', $data, array(), 1);
+               $this->backend->set($entryIdentifier . 'A', $data, array(), NULL);
+               $this->backend->set($entryIdentifier . 'B', $data, array(), 10);
                $this->backend->set($entryIdentifier . 'C', $data, array(), 1);
-               $filesFound = glob($pattern);
-               $this->assertTrue(is_array($filesFound) && count($filesFound) > 0, 'The cache entries do not exist.');
+               $this->backend->set($entryIdentifier . 'D', $data, array(), 1);
 
-               sleep(2);
+               $this->assertFileExists($pathAndFilename . 'A');
+               $this->assertFileExists($pathAndFilename . 'B');
+               $this->assertFileExists($pathAndFilename . 'C');
+               $this->assertFileExists($pathAndFilename . 'D');
 
+               $GLOBALS['EXEC_TIME'] += 2;
                $this->backend->collectGarbage();
-               $filesFound = is_array(glob($pattern)) ? glob($pattern) : array();
-               $this->assertTrue(count($filesFound) === 0, 'The cache entries still exist.');
+
+               $this->assertFileExists($pathAndFilename . 'A');
+               $this->assertFileExists($pathAndFilename . 'B');
+               $this->assertFileNotExists($pathAndFilename . 'C');
+               $this->assertFileNotExists($pathAndFilename . 'D');
        }
 
        /**
@@ -444,62 +376,44 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @author Robert Lemke <robert@typo3.org>
         * @author Ingo Renner <ingo@typo3.org>
         */
-       public function removeReallyRemovesTagsOfRemovedEntry() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
+       public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag() {
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
-               $data = 'some data' . microtime();
-               $entryIdentifier = 'BackendFileTest';
+               $this->backend->setCache($mockCache);
 
-               $this->backend->setCache($cache);
+               $data = 'some data' . microtime();
+               $this->backend->set('BackendFileTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
+               $this->backend->set('BackendFileTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
+               $this->backend->set('BackendFileTest3', $data, array('UnitTestTag%test'));
 
-               $tagsDirectory = $this->backend->getCacheDirectory() . 'tags/';
+               $expectedEntry = 'BackendFileTest2';
 
-               $this->backend->set($entryIdentifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
-               $this->backend->remove($entryIdentifier);
+               $actualEntries = $this->backend->findIdentifiersByTag('UnitTestTag%special');
 
-               $this->assertTrue(!file_exists($tagsDirectory . 'UnitTestTag%tag1/' . $entryIdentifier), 'File "' . $tagsDirectory . 'UnitTestTag%tag1/' . $entryIdentifier . '" still exists.');
-               $this->assertTrue(!file_exists($tagsDirectory . 'UnitTestTag%tag2/' . $entryIdentifier), 'File "' . $tagsDirectory . 'UnitTestTag%tag2/' . $entryIdentifier . '" still exists.');
+               $this->assertTrue(is_array($actualEntries), 'actualEntries is not an array.');
+               $this->assertEquals($expectedEntry, array_pop($actualEntries));
        }
 
        /**
         * @test
-        * @author Robert Lemke <robert@typo3.org>
         * @author Ingo Renner <ingo@typo3.org>
         */
-       public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
+       public function findIdentifiersByTagDoesNotReturnExpiredEntries() {
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
-               $this->backend->setCache($cache);
+               $this->backend->setCache($mockCache);
 
-               $data = 'some data' . microtime();
+               $data = 'some data';
                $this->backend->set('BackendFileTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
-               $this->backend->set('BackendFileTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
+               $this->backend->set('BackendFileTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'), -100);
                $this->backend->set('BackendFileTest3', $data, array('UnitTestTag%test'));
 
-               $expectedEntry = 'BackendFileTest2';
-
-               $actualEntries = $this->backend->findIdentifiersByTag('UnitTestTag%special');
-               $this->assertTrue(is_array($actualEntries), 'actualEntries is not an array.');
-
-               $this->assertEquals($expectedEntry, array_pop($actualEntries));
+               $this->assertSame(array(), $this->backend->findIdentifiersByTag('UnitTestTag%special'));
+               $foundIdentifiers = $this->backend->findIdentifiersByTag('UnitTestTag%test');
+               sort($foundIdentifiers);
+               $this->assertSame(array('BackendFileTest1', 'BackendFileTest3'), $foundIdentifiers);
        }
 
        /**
@@ -507,22 +421,11 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @author Robert Lemke <robert@typo3.org>
         * @author Ingo Renner <ingo@typo3.org>
         */
-       public function flushRemovesAllCacheEntriesAndRelatedTags() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
-
-               $this->backend->setCache($cache);
+       public function flushRemovesAllCacheEntries() {
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
-               $tagsDirectory = $this->backend->getCacheDirectory() . 'tags/';
-               $cacheDirectory = $this->backend->getCacheDirectory() . 'data/' . $cacheIdentifier . '/';
+               $this->backend->setCache($mockCache);
 
                $data = 'some data' . microtime();
                $this->backend->set('BackendFileTest1', $data, array('UnitTestTag%test'));
@@ -531,19 +434,9 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
 
                $this->backend->flush();
 
-               $pattern = $cacheDirectory . '*/*/*';
+               $pattern = $this->backend->getCacheDirectory() . '*';
                $filesFound = is_array(glob($pattern)) ? glob($pattern) : array();
                $this->assertTrue(count($filesFound) === 0, 'Still files in the cache directory');
-
-               $tagPrefixTest = $tagsDirectory . 'UnitTestTag%test/' . $cacheIdentifier . '^';
-               $tagPrefixSpecial = $tagsDirectory . 'UnitTestTag%special/' . $cacheIdentifier . '^';
-               $entryIdentifier = 'BackendFileTest1';
-               $this->assertTrue(!file_exists($tagPrefixTest . $entryIdentifier), 'File "' . $tagPrefixTest . $entryIdentifier . '" still exists.');
-               $entryIdentifier = 'BackendFileTest2';
-               $this->assertTrue(!file_exists($tagPrefixTest . $entryIdentifier), 'File "' . $tagPrefixTest . $entryIdentifier . '" still exists.');
-               $this->assertTrue(!file_exists($tagPrefixSpecial . $entryIdentifier), 'File "' . $tagPrefixSpecial . $entryIdentifier . '" still exists.');
-               $entryIdentifier = 'BackendFileTest3';
-               $this->assertTrue(!file_exists($tagPrefixTest . $entryIdentifier), 'File "' . $tagPrefixTest . $entryIdentifier . '" still exists.');
        }
 
        /**
@@ -552,18 +445,10 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
         * @author Ingo Renner <ingo@typo3.org>
         */
        public function flushByTagRemovesCacheEntriesWithSpecifiedTag() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
+               $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
+               $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
 
-               $this->backend->setCache($cache);
+               $this->backend->setCache($mockCache);
 
                $data = 'some data' . microtime();
                $this->backend->set('BackendFileTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
@@ -577,138 +462,6 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
                $this->assertTrue($this->backend->has('BackendFileTest3'), 'BackendFileTest3');
        }
 
-
-       /**
-        * @test
-        * @author Robert Lemke <robert@typo3.org>
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       public function hasReturnsTheCorrectResultForEntryWithExceededLifetime() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
-
-               $this->backend->setCache($cache);
-
-               $entryIdentifier = 'BackendFileTest';
-               $data = 'some data' . microtime();
-               $this->backend->set($entryIdentifier, $data);
-
-               $expiredEntryIdentifier = 'ExpiredBackendFileTest';
-               $expiredData = 'some old data' . microtime();
-               $this->backend->set($expiredEntryIdentifier, $expiredData, array(), 1);
-
-               sleep(2);
-
-               $this->assertFalse($this->backend->has($expiredEntryIdentifier), 'has() did not return FALSE.');
-       }
-
-       /**
-        * @test
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       public function getReturnsFalseForEntryWithExceededLifetime() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
-
-               $this->backend->setCache($cache);
-
-               $entryIdentifier = 'BackendFileTest';
-               $data = 'some data' . microtime();
-               $this->backend->set($entryIdentifier, $data);
-
-               $expiredEntryIdentifier = 'ExpiredBackendFileTest';
-               $expiredData = 'some old data' . microtime();
-               $this->backend->set($expiredEntryIdentifier, $expiredData, array(), 1);
-
-               sleep(2);
-
-               $this->assertEquals($data, $this->backend->get($entryIdentifier), 'The original and the retrieved data don\'t match.');
-               $this->assertFalse($this->backend->get($expiredEntryIdentifier), 'The expired entry could be loaded.');
-       }
-
-       /**
-        * @test
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       public function findIdentifiersByTagReturnsEmptyArrayForEntryWithExceededLifetime() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
-
-               $this->backend->setCache($cache);
-
-               $this->backend->set('BackendFileTest', 'some data', array('UnitTestTag%special'), 1);
-
-               sleep(2);
-
-               $this->assertEquals(array(), $this->backend->findIdentifiersByTag('UnitTestTag%special'));
-       }
-
-       /**
-        * @test
-        * @author Robert Lemke <robert@typo3.org>
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       public function setWithUnlimitedLifetimeWritesCorrectEntry() {
-               $cacheIdentifier = 'UnitTestCache';
-               $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
-                       array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
-                       array(),
-                       '',
-                       FALSE
-               );
-               $cache->expects($this->atLeastOnce())
-                       ->method('getIdentifier')
-                       ->will($this->returnValue($cacheIdentifier));
-
-               $data = 'some data' . microtime();
-               $entryIdentifier = 'BackendFileTest';
-               $entryIdentifierHash = sha1($entryIdentifier);
-
-               $this->backend->setCache($cache);
-               $this->backend->set($entryIdentifier, $data, array(), 0);
-
-               $cacheDirectory = $this->backend->getCacheDirectory();
-
-               $pathAndFilename = $cacheDirectory
-                       . 'data/'
-                       . $cacheIdentifier . '/'
-                       . $entryIdentifierHash[0] . '/'
-                       . $entryIdentifierHash[1] . '/'
-                       . $entryIdentifier;
-               $this->assertTrue(file_exists($pathAndFilename), 'File not found.');
-
-               $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.');
-       }
-
        /**
         * @author Robert Lemke <robert@typo3.org>
         * @author Ingo Renner <ingo@typo3.org>
@@ -717,10 +470,13 @@ class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
                if (is_object($this->backend)) {
                        $directory = $this->backend->getCacheDirectory();
                        if (is_dir($directory)) {
-                               t3lib_div::rmdir($directory, true);
+                               t3lib_div::rmdir($directory, TRUE);
                        }
                }
+               foreach ($this->backupGlobalVariables as $key => $data) {
+                       $GLOBALS[$key] = $data;
+               }
        }
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/tests/t3lib/cache/frontend/t3lib_cache_frontend_phpfrontendtestcase.php b/tests/t3lib/cache/frontend/t3lib_cache_frontend_phpfrontendtestcase.php
new file mode 100644 (file)
index 0000000..35baf54
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Christian Kuhn <lolli@schwarzbu.ch>
+*  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!
+***************************************************************/
+
+
+/**
+ * Testcase for the PHP source code cache frontend
+ *
+ * This file is a backport from FLOW3
+ *
+ * @author Christian Kuhn <lolli@schwarzbu.ch>
+ * @package TYPO3
+ * @subpackage tests
+ * @version $Id$
+ */
+class t3lib_cache_frontend_PhpFrontendTestCase extends tx_phpunit_testcase {
+
+       /**
+        * @test
+        * @author Robert Lemke <robert@typo3.org>
+        * @expectedException InvalidArgumentException
+        */
+       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 Robert Lemke <robert@typo3.org>
+        */
+       public function setPassesPhpSourceCodeTagsAndLifetimeToBackend() {
+               $originalSourceCode = 'return "hello world!";';
+               $modifiedSourceCode = '<?php' . chr(10) . $originalSourceCode . chr(10) . '__halt_compiler();';
+
+               $mockBackend = $this->getMock('t3lib_cache_backend_PhpCapableBackend', array(), array(), '', FALSE);
+               $mockBackend->expects($this->once())->method('set')->with('Foo-Bar', $modifiedSourceCode, array('tags'), 1234);
+
+               $cache = t3lib_div::makeInstance('t3lib_cache_frontend_PhpFrontend', 'PhpFrontend', $mockBackend);
+               $cache->set('Foo-Bar', $originalSourceCode, array('tags'), 1234);
+       }
+
+       /**
+        * @test
+        * @author Robert Lemke <robert@typo3.org>
+        * @expectedException t3lib_cache_exception_InvalidData
+        */
+       public function setThrowsInvalidDataExceptionOnNonStringValues() {
+               $cache = $this->getMock('t3lib_cache_frontend_PhpFrontend', array('dummy'), array(), '', FALSE);
+               $cache->set('Foo-Bar', array());
+       }
+
+       /**
+        * @test
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function requireOnceCallsTheBackendsRequireOnceMethod() {
+               $mockBackend = $this->getMock('t3lib_cache_backend_PhpCapableBackend', array(), array(), '', FALSE);
+               $mockBackend->expects($this->once())->method('requireOnce')->with('Foo-Bar')->will($this->returnValue('hello world!'));
+
+               $cache = t3lib_div::makeInstance('t3lib_cache_frontend_PhpFrontend', 'PhpFrontend', $mockBackend);
+
+               $result = $cache->requireOnce('Foo-Bar');
+               $this->assertSame('hello world!', $result);
+       }
+}
+?>