!!! Fixed issue #10614: update the caching framework to the latest version as in...
authorIngo Renner <ingo.renner@typo3.org>
Sun, 8 Mar 2009 15:39:26 +0000 (15:39 +0000)
committerIngo Renner <ingo.renner@typo3.org>
Sun, 8 Mar 2009 15:39:26 +0000 (15:39 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@5149 709f56b5-9817-0410-a4d7-c38de5d9e867

29 files changed:
ChangeLog
t3lib/cache/backend/class.t3lib_cache_backend_abstractbackend.php [new file with mode: 0644]
t3lib/cache/backend/class.t3lib_cache_backend_apcbackend.php [new file with mode: 0644]
t3lib/cache/backend/class.t3lib_cache_backend_db.php [deleted file]
t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php [new file with mode: 0644]
t3lib/cache/backend/class.t3lib_cache_backend_file.php [deleted file]
t3lib/cache/backend/class.t3lib_cache_backend_filebackend.php [new file with mode: 0644]
t3lib/cache/backend/class.t3lib_cache_backend_globals.php [deleted file]
t3lib/cache/backend/class.t3lib_cache_backend_globalsbackend.php [new file with mode: 0644]
t3lib/cache/backend/class.t3lib_cache_backend_memcached.php [deleted file]
t3lib/cache/backend/class.t3lib_cache_backend_memcachedbackend.php [new file with mode: 0644]
t3lib/cache/backend/class.t3lib_cache_backend_null.php [deleted file]
t3lib/cache/backend/class.t3lib_cache_backend_nullbackend.php [new file with mode: 0644]
t3lib/cache/backend/interfaces/interface.t3lib_cache_backend_backend.php [new file with mode: 0644]
t3lib/cache/class.t3lib_cache_abstractbackend.php [deleted file]
t3lib/cache/class.t3lib_cache_abstractcache.php [deleted file]
t3lib/cache/class.t3lib_cache_factory.php
t3lib/cache/class.t3lib_cache_manager.php
t3lib/cache/class.t3lib_cache_variablecache.php [deleted file]
t3lib/cache/frontend/class.t3lib_cache_frontend_abstractfrontend.php [new file with mode: 0644]
t3lib/cache/frontend/class.t3lib_cache_frontend_stringfrontend.php [new file with mode: 0644]
t3lib/cache/frontend/class.t3lib_cache_frontend_variablefrontend.php [new file with mode: 0644]
t3lib/cache/frontend/interfaces/interface.t3lib_cache_frontend_frontend.php [new file with mode: 0644]
t3lib/class.t3lib_cache.php
t3lib/config_default.php
t3lib/stddb/tables.sql
typo3/init.php
typo3/sysext/cms/ext_tables.sql
typo3/sysext/cms/tslib/class.tslib_fe.php

index 064d31a..83448da 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,7 @@
 2009-03-08  Ingo Renner  <ingo@typo3.org>
 
        * Added unit tests for the caching framework database cache backend (backported from FLOW3) (part of #10614)
+       * !!! Fixed issue #10614: update the caching framework to the latest version as in FLOW3
 
 2009-03-08  Tobias Liebig  <mail_typo3@etobi.de>
 
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_abstractbackend.php b/t3lib/cache/backend/class.t3lib_cache_backend_abstractbackend.php
new file mode 100644 (file)
index 0000000..6b4eca3
--- /dev/null
@@ -0,0 +1,106 @@
+<?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!
+***************************************************************/
+
+/**
+ * An abstract caching backend
+ *
+ * This file is a backport from FLOW3
+ *
+ * @author     Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @version $Id$
+ */
+abstract class t3lib_cache_backend_AbstractBackend implements t3lib_cache_backend_Backend {
+
+       /**
+        * Reference to the cache which uses this backend
+        *
+        * @var t3lib_cache_frontend_Frontend
+        */
+       protected $cache;
+
+       /**
+        * Default lifetime of a cache entry in seconds
+        *
+        * @var integer
+        */
+       protected $defaultLifetime = 3600;
+
+       /**
+        * Constructs this backend
+        *
+        * @param mixed Configuration options - depends on the actual backend
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function __construct(array $options = array()) {
+               if (is_array($options) || $options instanceof ArrayAccess) {
+                       foreach ($options as $optionKey => $optionValue) {
+                               $methodName = 'set' . ucfirst($optionKey);
+                               if (method_exists($this, $methodName)) {
+                                       $this->$methodName($optionValue);
+                               } else {
+                                       throw new InvalidArgumentException('Invalid cache backend option "' . $optionKey . '" for backend of type "' . get_class($this) . '"', 1235837747);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Sets a reference to the cache frontend which uses this backend
+        *
+        * @param t3lib_cache_frontend_Frontend The frontend for this backend
+        * @return void
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function setCache(t3lib_cache_frontend_Frontend $cache) {
+               $this->cache = $cache;
+       }
+
+       /**
+        * Sets the default lifetime for this cache backend
+        *
+        * @param integer $defaultLifeTime Default lifetime of this cache backend in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited liftime.
+        * @return void
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function setDefaultLifetime($defaultLifetime) {
+               if (!is_int($defaultLifetime) || $defaultLifetime < 0) {
+                       throw new InvalidArgumentException(
+                               'The default lifetime must be given as a positive integer.',
+                               1233072774
+                       );
+               }
+
+               $this->defaultLifetime = $defaultLifetime;
+       }
+
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_abstractbackend.php'])      {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_abstractbackend.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_apcbackend.php b/t3lib/cache/backend/class.t3lib_cache_backend_apcbackend.php
new file mode 100644 (file)
index 0000000..48a6f90
--- /dev/null
@@ -0,0 +1,401 @@
+<?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 by using APC.
+ *
+ * This backend uses the following types of keys:
+ * - tag_xxx
+ *   xxx is tag name, value is array of associated identifiers identifier. This
+ *   is "forward" tag index. It is mainly used for obtaining content by tag
+ *   (get identifier by tag -> get content by identifier)
+ * - ident_xxx
+ *   xxx is identifier, value is array of associated tags. This is "reverse" tag
+ *   index. It provides quick access for all tags associated with this identifier
+ *   and used when removing the identifier
+ * - tagIndex
+ *   Value is a List of all tags (array)
+
+ * Each key is prepended with a prefix. By default prefix consists from two parts
+ * separated by underscore character and ends in yet another underscore character:
+ * - "TYPO3"
+ * - MD5 of script path and filename and SAPI name
+ * This prefix makes sure that keys from the different installations do not
+ * conflict.
+ *
+ * This file is a backport from FLOW3
+ *
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @version $Id$
+ */
+class t3lib_cache_backend_ApcBackend extends t3lib_cache_backend_AbstractBackend {
+
+       /**
+        * A prefix to seperate stored data from other data possible stored in the APC
+        *
+        * @var string
+        */
+       protected $identifierPrefix;
+
+       /**
+        * Constructs this backend
+        *
+        * @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')) {
+                       throw new t3lib_cache_Exception(
+                               'The PHP extension "apc" must be installed and loaded in order to use the APC backend.',
+                               1232985414
+                       );
+               }
+
+               parent::__construct($options);
+       }
+
+       /**
+        * Saves data in the cache.
+        *
+        * Note on lifetime: the number of seconds may not exceed 2592000 (30 days),
+        * otherwise it is interpreted as a UNIX timestamp (seconds since epoch).
+        *
+        * @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.
+        * @throws InvalidArgumentException if the identifier is not valid
+        * @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(
+                               'No cache frontend has been set yet via setCache().',
+                               1232986818
+                       );
+               }
+
+               if (!is_string($data)) {
+                       throw new t3lib_cache_exception_InvalidData(
+                               'The specified data is of type "' . gettype($data) . '" but a string is expected.',
+                               1232986825
+                       );
+               }
+
+               $tags[] = '%APCBE%' . $this->cache->getIdentifier();
+               $expiration = $lifetime !== NULL ? $lifetime : $this->defaultLifetime;
+
+               $success = apc_store($this->identifierPrefix . $entryIdentifier, $data, $expiration);
+               if ($success === TRUE) {
+                       $this->removeIdentifierFromAllTags($entryIdentifier);
+                       $this->addTagsToTagIndex($tags);
+                       $this->addIdentifierToTags($entryIdentifier, $tags);
+               } else {
+                       throw new t3lib_cache_Exception(
+                               'Could not set value. ' . $exception->getMessage(),
+                               1232986877
+                       );
+               }
+       }
+
+       /**
+        * 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 Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function get($entryIdentifier) {
+               $success = FALSE;
+               $value = apc_fetch($this->identifierPrefix . $entryIdentifier, $success);
+
+               return ($success ? $value : $success);
+       }
+
+       /**
+        * 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 Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function has($entryIdentifier) {
+               $success = FALSE;
+               apc_fetch($this->identifierPrefix . $entryIdentifier, $success);
+               return $success;
+       }
+
+       /**
+        * Removes all cache entries matching the specified identifier.
+        * Usually this only affects one entry but if - for what reason ever -
+        * old entries for the identifier still exist, they are removed as well.
+        *
+        * @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 Christian Jul Jensen <julle@typo3.org>
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function remove($entryIdentifier) {
+               $this->removeIdentifierFromAllTags($entryIdentifier);
+
+               return apc_delete($this->identifierPrefix . $entryIdentifier);
+       }
+
+       /**
+        * 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 Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function findIdentifiersByTag($tag) {
+               $success = FALSE;
+               $identifiers = apc_fetch($this->identifierPrefix . 'tag_' . $tag, $success);
+
+               if ($success === FALSE) {
+                       return array();
+               } else {
+                       return (array) $identifiers;
+               }
+       }
+
+       /**
+        * Finds and returns all cache entry identifiers which are tagged by the
+        * specified tags.
+        *
+        * @param array 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>
+        */
+       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) {
+                       if ($this->has($entryIdentifier)) {
+                               $foundEntries[$entryIdentifier] = $entryIdentifier;
+                       }
+               }
+
+               return $foundEntries;
+       }
+
+       /**
+        * Finds all tags for the given identifier. This function uses reverse tag
+        * index to search for tags.
+        *
+        * @param string $identifier Identifier to find tags by
+        * @return array Array with tags
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function findTagsByIdentifier($identifier) {
+               $success = FALSE;
+               $tags = apc_fetch($this->identifierPrefix . 'ident_' . $identifier, $success);
+
+               return ($success ? (array)$tags : array());
+       }
+
+       /**
+        * Removes all cache entries of this cache.
+        *
+        * @return void
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       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().',
+                               1232986971
+                       );
+               }
+
+               $this->flushByTag('%APCBE%' . $this->cache->getIdentifier());
+       }
+
+       /**
+        * 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 Karsten Dambekalns <karsten@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 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);
+               }
+       }
+
+       /**
+        * Returns an array with all known tags
+        *
+        * @return array
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function getTagIndex() {
+               $success = FALSE;
+               $tagIndex = apc_fetch($this->identifierPrefix . 'tagIndex', $success);
+
+               return ($success ? (array)$tagIndex : array());
+       }
+
+       /**
+        * Saves the tags known to the backend
+        *
+        * @param array $tags
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function setTagIndex(array $tags) {
+               apc_store($this->identifierPrefix . 'tagIndex', array_unique($tags));
+       }
+
+       /**
+        * Adds the given tags to the tag index
+        *
+        * @param array $tags
+        * @return void
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function addTagsToTagIndex(array $tags) {
+               if (count($tags)) {
+                       $this->setTagIndex(array_merge($tags, $this->getTagIndex()));
+               }
+       }
+
+       /**
+        * Removes the given tags from the tag index
+        *
+        * @param array $tags
+        * @return void
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function removeTagsFromTagIndex(array $tags) {
+               if (count($tags)) {
+                       $this->setTagIndex(array_diff($this->getTagIndex(), $tags));
+               }
+       }
+
+       /**
+        * Associates the identifier with the given tags
+        *
+        * @param string $entryIdentifier
+        * @param array $tags
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function addIdentifierToTags($entryIdentifier, array $tags) {
+               foreach ($tags as $tag) {
+                               // Update tag-to-identifier index
+                       $identifiers = $this->findIdentifiersByTag($tag);
+                       if (array_search($entryIdentifier, $identifiers) === FALSE) {
+                               $identifiers[] = $entryIdentifier;
+                               apc_store($this->identifierPrefix . 'tag_' . $tag, $identifiers);
+                       }
+
+                               // Update identifier-to-tag index
+                       $existingTags = $this->findTagsByIdentifier($entryIdentifier);
+                       if (array_search($entryIdentifier, $existingTags) === false) {
+                               apc_store($this->identifierPrefix . 'ident_' . $entryIdentifier, array_merge($existingTags, $tags));
+                       }
+
+               }
+       }
+
+       /**
+        * Removes association of the identifier with the given tags
+        *
+        * @param string $entryIdentifier
+        * @param array $tags
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function removeIdentifierFromAllTags($entryIdentifier) {
+                       // Get tags for this identifier
+               $tags = $this->findTagsByIdentifier($entryIdentifier);
+                       // Deassociate tags with this identifier
+               foreach ($tags as $tag) {
+                       $identifiers = $this->findIdentifiersByTag($tag);
+                               // Formally array_search() below should never return false due to
+                               // the behavior of findTagsByIdentifier(). But if reverse index is
+                               // corrupted, we still can get 'false' from array_search(). This is
+                               // not a problem because we are removing this identifier from
+                               // anywhere.
+                       if (($key = array_search($entryIdentifier, $identifiers)) !== FALSE) {
+                               unset($identifiers[$key]);
+                               if (count($identifiers)) {
+                                       apc_store($this->identifierPrefix . 'tag_' . $tag, $identifiers);
+                               } else {
+                                       $this->removeTagsFromTagIndex(array($tag));
+                                       apc_delete($this->identifierPrefix . 'tag_' . $tag);
+                               }
+                       }
+               }
+                       // Clear reverse tag index for this identifier
+               apc_delete($this->identifierPrefix . 'ident_' . $entryIdentifier);
+       }
+
+       /**
+        * Does nothing, as APC does GC itself
+        *
+        * @return void
+        */
+       public function collectGarbage() {
+
+       }
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_apcbackend.php'])   {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_apcbackend.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_db.php b/t3lib/cache/backend/class.t3lib_cache_backend_db.php
deleted file mode 100644 (file)
index 6448528..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-<?php
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2008 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 in files
- *
- * @package TYPO3
- * @subpackage t3lib_cache
- * @version $Id$
- */
-class t3lib_cache_backend_Db extends t3lib_cache_AbstractBackend {
-
-       protected $cacheTable;
-
-       /**
-        * 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 liftime.
-        * @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 (is_null($lifetime)) {
-                       $lifetime = $this->defaultLifetime;
-               }
-
-               $this->remove($entryIdentifier);
-
-               $GLOBALS['TYPO3_DB']->exec_INSERTquery(
-                       $this->cacheTable,
-                       array(
-                               'identifier' => $entryIdentifier,
-                               'crdate'     => time(),
-                               'content'    => $data,
-                               'tags'       => implode(',', $tags),
-                               'lifetime'   => $lifetime
-                       )
-               );
-       }
-
-       /**
-        * Loads data from a cache file.
-        *
-        * @param string An identifier which describes the cache entry to load
-        * @return mixed The cache entry's data 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;
-
-               $caheEntries = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
-                       'content',
-                       $this->cacheTable,
-                       'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable) . ' '
-                               . 'AND ((crdate + lifetime) >= ' . time() . ' OR lifetime = 0)'
-               );
-
-               if (count($caheEntries) == 1) {
-                       $cacheEntry = $caheEntries[0]['content'];
-               }
-
-               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) {
-               $hasEntry = false;
-
-               $caheEntries = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
-                       'content',
-                       $this->cacheTable,
-                       'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable) . ' '
-                               . 'AND (crdate + lifetime) >= ' . time()
-               );
-
-               if (count($caheEntries) == 1) {
-                       $hasEntry = true;
-               }
-
-               return $hasEntry;
-       }
-
-       /**
-        * 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) {
-               $entryRemoved = false;
-
-               $res = $GLOBALS['TYPO3_DB']->exec_DELETEquery(
-                       $this->cacheTable,
-                       'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable)
-               );
-
-               if($GLOBALS['TYPO3_DB']->sql_affected_rows($res) == 1) {
-                       $entryRemoved = true;
-               }
-
-               return $entryRemoved;
-       }
-
-       /**
-        * 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) {
-               $cacheEntries = array();
-
-               $cacheEntryRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
-                       'identifier',
-                       $this->cacheTable,
-                       $this->getListQueryForTag($tag)
-               );
-
-               foreach ($cacheEntryRows as $cacheEntryRow) {
-                       $cacheEntries[$cacheEntryRow['identifier']] = $cacheEntryRow['identifier'];
-               }
-
-               return $cacheEntries;
-       }
-
-       /**
-        * 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) {
-               $cacheEntries = array();
-               $whereClause  = array();
-
-               foreach ($tags as $tag) {
-                       $whereClause[] = $this->getListQueryForTag($tag);
-               }
-
-               $cacheEntryRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
-                       'identifier',
-                       $this->cacheTable,
-                       implode(' AND ', $whereClause)
-               );
-
-               foreach ($cacheEntryRows as $cacheEntryRow) {
-                       $cacheEntries[$cacheEntryRow['identifier']] = $cacheEntryRow['identifier'];
-               }
-
-               return $cacheEntries;
-       }
-
-       /**
-        * Removes all cache entries of this cache.
-        *
-        * @return void
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       public function flush() {
-               $GLOBALS['TYPO3_DB']->sql_query('TRUNCATE ' . $this->cacheTable);
-       }
-
-       /**
-        * 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) {
-               foreach ($this->findEntriesByTag($tag) as $entryIdentifier) {
-                       $this->remove($entryIdentifier);
-               }
-       }
-
-       /**
-        * 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 ($this->findEntriesByTags($tags) as $entryIdentifier) {
-                       $this->remove($entryIdentifier);
-               }
-       }
-
-       protected function setCacheTable($cacheTable) {
-               $this->cacheTable = $cacheTable;
-       }
-
-       /**
-        * Gets the query to be used for selecting entries by a tag. The asterisk ("*")
-        * is allowed as a wildcard at the beginning and the end of a tag.
-        *
-        * @param string The tag to search for, the "*" wildcard is supported
-        * @return string the query to be used for selecting entries
-        * @author Oliver Hader <oliver@typo3.org>
-        */
-       protected function getListQueryForTag($tag) {
-               return str_replace('*', '%', $GLOBALS['TYPO3_DB']->listQuery('tags', $tag, $this->cacheTable));
-       }
-}
-
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_db.php'])   {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_db.php']);
-}
-
-?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php b/t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php
new file mode 100644 (file)
index 0000000..bf5ada8
--- /dev/null
@@ -0,0 +1,312 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2008 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 in files
+ *
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @version $Id$
+ */
+class t3lib_cache_backend_DbBackend extends t3lib_cache_backend_AbstractBackend {
+
+       protected $cacheTable;
+
+       /**
+        * 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 liftime.
+        * @return void
+        * @throws t3lib_cache_Exception if no cache frontend has been set.
+        * @throws t3lib_cache_exception_InvalidData if the data to be stored is not a string.
+        * @author Ingo Renner <ingo@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 via setCache() yet.',
+                               1236518288
+                       );
+               }
+
+               if (!is_string($data)) {
+                       throw new t3lib_cache_exception_InvalidData(
+                               'The specified data is of type "' . gettype($data) . '" but a string is expected.',
+                               1236518298
+                       );
+               }
+
+               if (is_null($lifetime)) {
+                       $lifetime = $this->defaultLifetime;
+               }
+
+               $this->remove($entryIdentifier);
+
+               $GLOBALS['TYPO3_DB']->exec_INSERTquery(
+                       $this->cacheTable,
+                       array(
+                               'identifier' => $entryIdentifier,
+                               'crdate'     => time(),
+                               'content'    => $data,
+                               'tags'       => implode(',', $tags),
+                               'lifetime'   => $lifetime
+                       )
+               );
+       }
+
+       /**
+        * Loads data from a cache file.
+        *
+        * @param string An identifier which describes the cache entry to load
+        * @return mixed The cache entry's data 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;
+
+               $caheEntries = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                       'content',
+                       $this->cacheTable,
+                       'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable) . ' '
+                               . 'AND ((crdate + lifetime) >= ' . time() . ' OR lifetime = 0)'
+               );
+
+               if (count($caheEntries) == 1) {
+                       $cacheEntry = $caheEntries[0]['content'];
+               }
+
+               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) {
+               $hasEntry = false;
+
+               $caheEntries = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                       'content',
+                       $this->cacheTable,
+                       'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable) . ' '
+                               . 'AND (crdate + lifetime) >= ' . time()
+               );
+
+               if (count($caheEntries) == 1) {
+                       $hasEntry = true;
+               }
+
+               return $hasEntry;
+       }
+
+       /**
+        * 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) {
+               $entryRemoved = false;
+
+               $res = $GLOBALS['TYPO3_DB']->exec_DELETEquery(
+                       $this->cacheTable,
+                       'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable)
+               );
+
+               if($GLOBALS['TYPO3_DB']->sql_affected_rows($res) == 1) {
+                       $entryRemoved = true;
+               }
+
+               return $entryRemoved;
+       }
+
+       /**
+        * Finds and returns all cache entries which are tagged by the specified tag.
+        *
+        * @param string The tag 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>
+        */
+       public function findIdentifiersByTag($tag) {
+               $cacheEntryIdentifiers = array();
+
+               $cacheEntryIdentifierRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                       'identifier',
+                       $this->cacheTable,
+                       $this->getListQueryForTag($tag) . ' AND ((crdate + lifetime) >= ' . time() . ' OR lifetime = 0)'
+               );
+
+               foreach ($cacheEntryIdentifierRows as $cacheEntryIdentifierRow) {
+                       $cacheEntryIdentifiers[$cacheEntryIdentifierRow['identifier']] = $cacheEntryIdentifierRow['identifier'];
+               }
+
+               return $cacheEntryIdentifiers;
+       }
+
+       /**
+        * Finds and returns all cache entry identifiers which are tagged by the
+        * specified tags.
+        *
+        * @param array 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>
+        */
+       public function findIdentifiersByTags(array $tags) {
+               $cacheEntryIdentifiers = array();
+               $whereClause  = array();
+
+               foreach ($tags as $tag) {
+                       $whereClause[] = $this->getListQueryForTag($tag);
+               }
+               $whereClause[] = '((crdate + lifetime) >= ' . time() . ' OR lifetime = 0)';
+
+               $cacheEntryIdentifierRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                       'identifier',
+                       $this->cacheTable,
+                       implode(' AND ', $whereClause)
+               );
+
+               foreach ($cacheEntryIdentifierRows as $cacheEntryIdentifierRow) {
+                       $cacheEntryIdentifiers[$cacheEntryIdentifierRow['identifier']] = $cacheEntryIdentifierRow['identifier'];
+               }
+
+               return $cacheEntryIdentifiers;
+       }
+
+       /**
+        * Removes all cache entries of this cache.
+        *
+        * @return void
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function flush() {
+               $GLOBALS['TYPO3_DB']->sql_query('TRUNCATE ' . $this->cacheTable);
+       }
+
+       /**
+        * 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) {
+               foreach ($this->findIdentifiersByTag($tag) as $entryIdentifier) {
+                       $this->remove($entryIdentifier);
+               }
+       }
+
+       /**
+        * 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 ($this->findIdentifiersByTags($tags) as $entryIdentifier) {
+                       $this->remove($entryIdentifier);
+               }
+       }
+
+       /**
+        * Does garbage collection
+        *
+        * @return void
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function collectGarbage() {
+               $GLOBALS['TYPO3_DB']->exec_DELETEquery(
+                       $this->cacheTable,
+                       '(crdate + lifetime) < ' . time()
+               );
+       }
+
+       /**
+        * Sets the table where the cache entries are stored. The specified table
+        * must exist already.
+        *
+        * @param       string  The table.
+        * @return      void
+        * @throws t3lib_cache_Exception if the table does not exist.
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function setCacheTable($cacheTable) {
+               $result = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                       'id',
+                       $cacheTable,
+                       '',
+                       '',
+                       '',
+                       1
+               );
+
+               if (!is_array($result)) {
+                       throw new t3lib_cache_Exception(
+                               'The table "' . $cacheTable . '" does not exist.',
+                               1236516444
+                       );
+               }
+
+               $this->cacheTable = $cacheTable;
+       }
+
+       /**
+        * Returns the table where the cache entries are stored.
+        *
+        * @return      string  The cache table.
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function getCacheTable() {
+               return $this->cacheTable;
+       }
+
+       /**
+        * Gets the query to be used for selecting entries by a tag. The asterisk ("*")
+        * is allowed as a wildcard at the beginning and the end of a tag.
+        *
+        * @param string The tag to search for, the "*" wildcard is supported
+        * @return string the query to be used for selecting entries
+        * @author Oliver Hader <oliver@typo3.org>
+        */
+       protected function getListQueryForTag($tag) {
+               return str_replace('*', '%', $GLOBALS['TYPO3_DB']->listQuery('tags', $tag, $this->cacheTable));
+       }
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php'])    {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_file.php b/t3lib/cache/backend/class.t3lib_cache_backend_file.php
deleted file mode 100644 (file)
index 0678186..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-<?php
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2008 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 in files
- *
- * This file is a backport from FLOW3
- *
- * @package TYPO3
- * @subpackage t3lib_cache
- * @version $Id$
- */
-class t3lib_cache_backend_File extends t3lib_cache_AbstractBackend {
-
-       /**
-        * @var string Directory where the files are stored
-        */
-       protected $cacheDirectory = '';
-
-       /**
-        * Constructs this backend
-        *
-        * @param mixed Configuration options - depends on the actual backend
-        */
-       public function __construct(array $options = array()) {
-               parent::__construct($options);
-
-               if (empty($this->cacheDirectory)) {
-                       $cacheDirectory = 'typo3temp/cache/';
-                       try {
-                               $this->setCacheDirectory($cacheDirectory);
-                       } catch(t3lib_cache_Exception $exception) {
-
-                       }
-               }
-       }
-
-       /**
-        * Sets the directory where the cache files are stored.
-        *
-        * @param string The directory
-        * @return void
-        * @throws t3lib_cache_Exception if the directory does not exist, is not writable or could not be created.
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function setCacheDirectory($cacheDirectory) {
-               $typo3DocumentRoot = t3lib_div::getIndpEnv('TYPO3_DOCUMENT_ROOT') . '/';
-
-               if ($cacheDirectory{strlen($cacheDirectory) - 1} !== '/') {
-                       $cacheDirectory .= '/';
-               }
-
-               if (!is_writable($typo3DocumentRoot . $cacheDirectory)) {
-                       t3lib_div::mkdir_deep(
-                               $typo3DocumentRoot,
-                               $cacheDirectory
-                       );
-               }
-
-               if (!is_dir($typo3DocumentRoot . $cacheDirectory)) {
-                       throw new t3lib_cache_Exception(
-                               'The directory "' . $cacheDirectory . '" does not exist.',
-                               1203965199
-                       );
-               }
-
-               if (!is_writable($typo3DocumentRoot . $cacheDirectory)) {
-                       throw new t3lib_cache_Exception(
-                               'The directory "' . $cacheDirectory . '" is not writable.',
-                               1203965200
-                       );
-               }
-
-               $tagsDirectory = $cacheDirectory . 'tags/';
-
-               if (!is_writable($tagsDirectory)) {
-                       t3lib_div::mkdir_deep(
-                               $typo3DocumentRoot,
-                               $tagsDirectory
-                       );
-               }
-
-               $this->cacheDirectory = $typo3DocumentRoot . $cacheDirectory;
-       }
-
-       /**
-        * Returns the directory where the cache files are stored
-        *
-        * @return string Full path of the cache directory
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function getCacheDirectory() {
-               return $this->cacheDirectory;
-       }
-
-       /**
-        * 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 liftime.
-        * @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 Robert Lemke <robert@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.',
-                               1207139693
-                       );
-               }
-
-               if (!is_object($this->cache)) {
-                       throw new t3lib_cache_Exception(
-                               'No cache frontend has been set yet via setCache().',
-                               1204111375
-                       );
-               }
-
-               if (!is_string($data)) {
-                       throw new t3lib_cache_Exception_InvalidData(
-                               'The specified data is of type "' . gettype($data) . '" but a string is expected.',
-                               1204481674
-                       );
-               }
-
-               foreach ($tags as $tag) {
-                       if (!self::isValidTag($tag)) {
-                               throw new InvalidArgumentException(
-                                       '"' . $tag . '" is not a valid tag for a cache entry.',
-                                       1213105438
-                               );
-                       }
-               }
-
-               if (is_null($lifetime)) {
-                       $lifetime = $this->defaultLifetime;
-               }
-
-               $expiryTime          = new DateTime(
-                       'now +' . $lifetime . ' seconds',
-                       new DateTimeZone('UTC')
-               );
-               $entryIdentifierHash = sha1($entryIdentifier);
-               $cacheEntryPath      = $this->cacheDirectory
-                       . 'data/' . $this->cache->getIdentifier()
-                       . '/' . $entryIdentifierHash{0} . '/' . $entryIdentifierHash {1} . '/';
-               $filename            = $this->renderCacheFilename($entryIdentifier, $expiryTime);
-
-               if (!is_writable($cacheEntryPath)) {
-                       try {
-                               t3lib_div::mkdir_deep(
-                                       '/',
-                                       $cacheEntryPath
-                               );
-                       } catch(Exception $exception) {
-
-                       }
-                       if (!is_writable($cacheEntryPath)) {
-                               throw new t3lib_cache_Exception(
-                                       'The cache directory "' . $cacheEntryPath . '" could not be created.',
-                                       1204026250
-                               );
-                       }
-               }
-
-               $this->remove($entryIdentifier);
-
-               $temporaryFilename = $filename . '.' . uniqid() . '.temp';
-               $result = file_put_contents($cacheEntryPath . $temporaryFilename, $data);
-               if ($result === FALSE) {
-                       throw new t3lib_cache_Exception(
-                               'The temporary cache file "' . $temporaryFilename . '" could not be written.',
-                               1204026251
-                       );
-               }
-
-               for ($i = 0; $i < 5; $i++) {
-                       $result = rename(
-                               $cacheEntryPath . $temporaryFilename,
-                               $cacheEntryPath . $filename
-                       );
-
-                       if ($result === TRUE) {
-                               break;
-                       }
-               }
-
-               foreach ($tags as $tag) {
-                       $tagPath = $this->cacheDirectory . 'tags/'
-                               . $this->cache->getIdentifier() . '/' . $tag . '/';
-
-                       if (!is_writable($tagPath)) {
-                               t3lib_div::mkdir_deep(
-                                       '/',
-                                       $tagPath
-                               );
-                       }
-
-                       touch($tagPath . $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 Robert Lemke <robert@typo3.org>
-        */
-       public function get($entryIdentifier) {
-               $pathsAndFilenames = $this->findCacheFilesByEntry($entryIdentifier);
-               $cacheEntry        = FALSE;
-
-               if ($pathsAndFilenames !== FALSE) {
-                       $cacheEntry = file_get_contents(array_pop($pathsAndFilenames));
-               }
-
-               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 Robert Lemke <robert@typo3.org>
-        */
-       public function has($entryIdentifier) {
-               return $this->findCacheFilesByEntry($entryIdentifier) !== FALSE;
-       }
-
-       /**
-        * 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 Robert Lemke <robert@typo3.org>
-        */
-       public function remove($entryIdentifier) {
-               $pathsAndFilenames = $this->findCacheFilesByEntry($entryIdentifier);
-
-               if ($pathsAndFilenames === FALSE) {
-                       return FALSE;
-               }
-
-               foreach ($pathsAndFilenames as $pathAndFilename) {
-                       $result = unlink($pathAndFilename);
-                       if ($result === FALSE) {
-                               return FALSE;
-                       }
-               }
-
-               $pathsAndFilenames = $this->findTagFilesByEntry($entryIdentifier);
-               if ($pathsAndFilenames === FALSE) {
-                       return FALSE;
-               }
-
-               foreach ($pathsAndFilenames as $pathAndFilename) {
-                       $result = unlink($pathAndFilename);
-                       if ($result === FALSE) {
-                               return FALSE;
-                       }
-               }
-
-               return TRUE;
-       }
-
-       /**
-        * 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 Robert Lemke <robert@typo3.org>
-        */
-       public function findEntriesByTag($tag) {
-               if (!is_object($this->cache)) {
-                       throw new t3lib_cache_Exception(
-                               'Yet no cache frontend has been set via setCache().',
-                               1204111376
-                       );
-               }
-
-               $path       = $this->cacheDirectory . 'tags/'
-                       . $this->cache->getIdentifier() . '/' . $tag . '/';
-               $pattern    = $path . '*';
-               $filesFound = glob($pattern);
-
-               if ($filesFound === FALSE || count($filesFound) == 0) {
-                       return array();
-               }
-
-               $cacheEntries = array();
-               foreach ($filesFound as $filename) {
-                       list(,$entryIdentifier) = explode('_', basename($filename));
-                       $cacheEntries[$entryIdentifier] = $entryIdentifier;
-               }
-
-               return array_values($cacheEntries);
-       }
-
-       /**
-        * 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 Robert Lemke <robert@typo3.org>
-        */
-       public function flush() {
-               if (!is_object($this->cache)) {
-                       throw new t3lib_cache_Exception(
-                               'Yet no cache frontend has been set via setCache().',
-                               1204111376
-                       );
-               }
-
-               $dataPath = $this->cacheDirectory . 'data/' . $this->cache->getIdentifier() . '/';
-               $tagsPath = $this->cacheDirectory . 'tags/' . $this->cache->getIdentifier() . '/';
-
-               t3lib_div::rmdir($dataPath, true);
-               t3lib_div::rmdir($tagsPath, true);
-       }
-
-       /**
-        * 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) {
-               $path       = $this->cacheDirectory . 'tags/'
-                       . $this->cache->getIdentifier() . '/' . $tag . '/';
-               $pattern    = $path . '*';
-               $filesFound = glob($pattern);
-
-               foreach ($filesFound as $file) {
-                       $pathAndFile = explode('/', $file);
-                       $identifier = $pathAndFile[count($pathAndFile) - 1];
-
-                       unlink($file);
-                       $this->remove($identifier);
-               }
-               rmdir($path);
-       }
-
-       /**
-        * 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);
-               }
-       }
-
-       /**
-        * 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('Y-m-d\TH\;i\;sO') . '_' . $identifier;
-
-               return $filename;
-       }
-
-       /**
-        * Tries to find the cache entry for the specified identifier.
-        * Usually only one cache entry should be found - if more than one exist, this
-        * is due to some error or crash.
-        *
-        * @param string The cache entry 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
-        */
-       protected function findCacheFilesByEntry($entryIdentifier) {
-               if (!is_object($this->cache)) {
-                       throw new t3lib_cache_Exception(
-                               'Yet no cache frontend has been set via setCache().',
-                               1204111376
-                       );
-               }
-
-               $path            = $this->cacheDirectory . 'data/' . $this->cache->getIdentifier() . '/';
-               $pattern         = $path . '*/*/????-??-?????;??;???????_' . $entryIdentifier;
-               $filesFound      = glob($pattern);
-               $validFilesFound = array();
-
-               if ($filesFound === FALSE || count($filesFound) == 0) {
-                       return FALSE;
-               }
-
-               foreach ($filesFound as $pathAndFilename) {
-                       $expiryTimeAndIdentifier = explode('/', $pathAndFilename);
-                       $expiryTime = substr(array_pop($expiryTimeAndIdentifier), 0, -(strlen($entryIdentifier) + 1));
-
-                       $expiryTimeParsed = strtotime(str_replace(';', ':', $expiryTime));
-
-                       $now = new DateTime(
-                               'now',
-                               new DateTimeZone('UTC')
-                       );
-                       $now = (int) $now->format('U');
-
-                       if ($expiryTimeParsed > $now) {
-                               $validFilesFound[] = $pathAndFilename;
-                       } else {
-                               unlink($pathAndFilename);
-                       }
-               }
-
-               if (count($validFilesFound) == 0) {
-                       return FALSE;
-               }
-
-               return $validFilesFound;
-       }
-
-
-       /**
-        * 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
-        * @author Robert Lemke <robert@typo3.org>
-        * @throws t3lib_cache_Exception if no frontend has been set
-        */
-       protected function findTagFilesByEntry($entryIdentifier) {
-               if (!is_object($this->cache)) {
-                       throw new t3lib_cache_Exception(
-                               'Yet no cache frontend has been set via setCache().',
-                               1204111376
-                       );
-               }
-
-               $path       = $this->cacheDirectory . 'tags/';
-               $pattern    = $path . '*/' . $this->cache->getIdentifier() . '_' . $entryIdentifier;
-               $filesFound = glob($pattern);
-
-               if ($filesFound === FALSE || count($filesFound) == 0) {
-                       return FALSE;
-               }
-
-               return $filesFound;
-       }
-}
-
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_file.php']) {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_file.php']);
-}
-
-?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_filebackend.php b/t3lib/cache/backend/class.t3lib_cache_backend_filebackend.php
new file mode 100644 (file)
index 0000000..ad480c2
--- /dev/null
@@ -0,0 +1,546 @@
+<?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 in files
+ *
+ * This file is a backport from FLOW3
+ *
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @version $Id$
+ */
+class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBackend {
+
+       const SEPARATOR = '-';
+
+       const FILENAME_EXPIRYTIME_FORMAT    = 'YmdHis';
+       const FILENAME_EXPIRYTIME_GLOB      = '??????????????';
+       const FILENAME_EXPIRYTIME_UNLIMITED = '99991231235959';
+
+       /**
+        * @var string Directory where the files are stored
+        */
+       protected $cacheDirectory = '';
+
+       /**
+        * Constructs this backend
+        *
+        * @param mixed Configuration options - depends on the actual backend
+        */
+       public function __construct(array $options = array()) {
+               parent::__construct($options);
+
+               if (empty($this->cacheDirectory)) {
+                       $cacheDirectory = 'typo3temp/cache/';
+                       try {
+                               $this->setCacheDirectory($cacheDirectory);
+                       } catch(t3lib_cache_Exception $exception) {
+
+                       }
+               }
+       }
+
+       /**
+        * Sets the directory where the cache files are stored. By default it is
+        * assumed that the directory is below the TYPO3_DOCUMENT_ROOT. However, an
+        * absolute path can be selected, too.
+        *
+        * @param string The directory. If a relative path is given, it's assumed it's in TYPO3_DOCUMENT_ROOT. If an absolute path is given it is taken as is.
+        * @return void
+        * @throws t3lib_cache_Exception if the directory does not exist, is not writable or could not be created.
+        * @author Robert Lemke <robert@typo3.org>
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function setCacheDirectory($cacheDirectory) {
+               $documentRoot = t3lib_div::getIndpEnv('TYPO3_DOCUMENT_ROOT') . '/';
+
+                       // resetting if an absolute path is given
+               if ($cacheDirectory{0} == '/') {
+                       $documentRoot = '/';
+               }
+
+               if ($cacheDirectory{strlen($cacheDirectory) - 1} !== '/') {
+                       $cacheDirectory .= '/';
+               }
+
+               if (!is_writable($documentRoot . $cacheDirectory)) {
+                       t3lib_div::mkdir_deep(
+                               $documentRoot,
+                               $cacheDirectory
+                       );
+               }
+
+               if (!is_dir($documentRoot . $cacheDirectory)) {
+                       throw new t3lib_cache_Exception(
+                               'The directory "' . $cacheDirectory . '" does not exist.',
+                               1203965199
+                       );
+               }
+
+               if (!is_writable($documentRoot . $cacheDirectory)) {
+                       throw new t3lib_cache_Exception(
+                               'The directory "' . $cacheDirectory . '" is not writable.',
+                               1203965200
+                       );
+               }
+
+               $tagsDirectory = $cacheDirectory . 'tags/';
+
+               if (!is_writable($tagsDirectory)) {
+                       t3lib_div::mkdir_deep(
+                               $documentRoot,
+                               $tagsDirectory
+                       );
+               }
+
+               $this->cacheDirectory = $documentRoot . $cacheDirectory;
+       }
+
+       /**
+        * Returns the directory where the cache files are stored
+        *
+        * @return string Full path of the cache directory
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function getCacheDirectory() {
+               return $this->cacheDirectory;
+       }
+
+       /**
+        * 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.
+        * @return void
+        * @throws t3lib_cache_Exception if the directory does not exist or is not writable, 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>
+        */
+       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().',
+                               1204111375
+                       );
+               }
+
+               if (!is_string($data)) {
+                       throw new t3lib_cache_Exception_InvalidData(
+                               'The specified data is of type "' . gettype($data) . '" but a string is expected.',
+                               1204481674
+                       );
+               }
+
+               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'));
+               }
+
+               $cacheEntryPath = $this->renderCacheEntryPath($entryIdentifier);
+               $filename       = $this->renderCacheFilename($entryIdentifier, $expiryTime);
+
+               if (!is_writable($cacheEntryPath)) {
+                       try {
+                               t3lib_div::mkdir_deep(
+                                       '/',
+                                       $cacheEntryPath
+                               );
+                       } catch(Exception $exception) {
+
+                       }
+                       if (!is_writable($cacheEntryPath)) {
+                               throw new t3lib_cache_Exception(
+                                       'The cache directory "' . $cacheEntryPath . '" could not be created.',
+                                       1204026250
+                               );
+                       }
+               }
+
+               $this->remove($entryIdentifier);
+
+               $temporaryFilename = $filename . '.' . uniqid() . '.temp';
+               $result = file_put_contents($cacheEntryPath . $temporaryFilename, $data);
+               if ($result === FALSE) {
+                       throw new t3lib_cache_Exception(
+                               'The temporary cache file "' . $temporaryFilename . '" could not be written.',
+                               1204026251
+                       );
+               }
+
+               for ($i = 0; $i < 5; $i++) {
+                       $result = rename(
+                               $cacheEntryPath . $temporaryFilename,
+                               $cacheEntryPath . $filename
+                       );
+
+                       if ($result === TRUE) {
+                               break;
+                       }
+               }
+
+               if ($result === FALSE) {
+                       throw new t3lib_cache_Exception(
+                               'The cache file "' . $filename . '" could not be written.',
+                               1222361632
+                       );
+               }
+
+               foreach ($tags as $tag) {
+                       $tagPath = $this->cacheDirectory . 'tags/' . $tag . '/';
+
+                       if (!is_writable($tagPath)) {
+                               t3lib_div::mkdir_deep(
+                                       '/',
+                                       $tagPath
+                               );
+                       }
+
+                       touch($tagPath
+                               . $this->cache->getIdentifier()
+                               . self::SEPARATOR
+                               . $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 Robert Lemke <robert@typo3.org>
+        * @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);
+       }
+
+       /**
+        * Checks if a cache entry with the specified identifier exists.
+        *
+        * @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));
+       }
+
+       /**
+        * 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 Robert Lemke <robert@typo3.org>
+        */
+       public function remove($entryIdentifier) {
+               $pathsAndFilenames = $this->findCacheFilesByIdentifier($entryIdentifier);
+
+               if ($pathsAndFilenames === FALSE) {
+                       return FALSE;
+               }
+
+               foreach ($pathsAndFilenames as $pathAndFilename) {
+                       $result = unlink($pathAndFilename);
+                       if ($result === FALSE) {
+                               return FALSE;
+                       }
+               }
+
+               $pathsAndFilenames = $this->findTagFilesByEntry($entryIdentifier);
+               if ($pathsAndFilenames === FALSE) {
+                       return FALSE;
+               }
+
+               foreach ($pathsAndFilenames as $pathAndFilename) {
+                       $result = unlink($pathAndFilename);
+                       if ($result === FALSE) {
+                               return FALSE;
+                       }
+               }
+
+               return TRUE;
+       }
+
+       /**
+        * Finds and returns all cache entry identifiers which are tagged by the
+        * specified tag.
+        *
+        * @param string 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>
+        */
+       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->cacheDirectory . 'tags/';
+               $pattern = $path . $tag . '/'
+                       . $this->cache->getIdentifier() . self::SEPARATOR . '*';
+               $filesFound = glob($pattern);
+
+               if ($filesFound === FALSE || count($filesFound) === 0) {
+                       return array();
+               }
+
+               $cacheEntries = array();
+               foreach ($filesFound as $filename) {
+                       list(,$entryIdentifier) = explode(self::SEPARATOR, basename($filename));
+                       if ($this->has($entryIdentifier)) {
+                               $cacheEntries[$entryIdentifier] = $entryIdentifier;
+                       }
+               }
+
+               return array_values($cacheEntries);
+       }
+
+       /**
+        * Finds and returns all cache entry identifiers which are tagged by the
+        * specified tags.
+        *
+        * @param array 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>
+        */
+       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) {
+                       if ($this->has($entryIdentifier)) {
+                               $foundEntries[$entryIdentifier] = $entryIdentifier;
+                       }
+               }
+
+               return $foundEntries;
+       }
+
+       /**
+        * Removes all cache entries of this cache.
+        *
+        * @return void
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       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->cacheDirectory . 'data/' . $this->cache->getIdentifier() . '/';
+               $tagsPath = $this->cacheDirectory . 'tags/' . $this->cache->getIdentifier() . '/';
+
+               t3lib_div::rmdir($dataPath, true);
+               t3lib_div::rmdir($tagsPath, true);
+       }
+
+       /**
+        * 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) {
+               $identifiers = $this->findIdentifiersByTag($tag);
+               if (count($identifiers) === 0) {
+                       return;
+               }
+
+               foreach ($identifiers as $entryIdentifier) {
+                       $this->remove($entryIdentifier);
+               }
+       }
+
+       /**
+        * 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);
+               }
+       }
+
+       /**
+        * Checks if the given cache entry files are still valid or if their
+        * lifetime has exceeded.
+        *
+        * @param       string  $cacheFilename
+        * @return      boolean
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       protected function isCacheFileExpired($cacheFilename) {
+               list($timestamp) = explode(self::SEPARATOR, basename($cacheFilename), 2);
+               return $timestamp < gmdate('YmdHis');
+       }
+
+       /**
+        * Does garbage collection for the given entry or all entries.
+        *
+        * @return void
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function collectGarbage() {
+               if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
+                       throw new t3lib_cache_Exception(
+                               'Yet no cache frontend has been set via setCache().',
+                               1222686150
+                       );
+               }
+
+               $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;
+       }
+
+       /**
+        * 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>
+        */
+       protected function renderCacheEntryPath($identifier) {
+               $identifierHash = sha1($identifier);
+               return $this->cacheDirectory . 'data/' . $this->cache->getIdentifier() . '/' . $identifierHash[0] . '/' . $identifierHash[1] . '/';
+       }
+
+       /**
+        * Tries to find the cache entry for the specified identifier.
+        * Usually only one cache entry should be found - if more than one exist, this
+        * is due to some error or crash.
+        *
+        * @param string The cache entry 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
+        */
+       protected function findCacheFilesByIdentifier($entryIdentifier) {
+               if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
+                       throw new t3lib_cache_Exception(
+                               'Yet no cache frontend has been set via setCache().',
+                               1204111376
+                       );
+               }
+
+               $pattern    = $this->renderCacheEntryPath($entryIdentifier) . self::FILENAME_EXPIRYTIME_GLOB . self::SEPARATOR . $entryIdentifier;
+               $filesFound = glob($pattern);
+
+               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
+        * @author Robert Lemke <robert@typo3.org>
+        * @throws t3lib_cache_Exception if no frontend has been set
+        */
+       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->cacheDirectory . 'tags/';
+               $pattern    = $path . '*/' . $this->cache->getIdentifier() . self::SEPARATOR . $entryIdentifier;
+               $filesFound = glob($pattern);
+
+               if ($filesFound === FALSE || count($filesFound) === 0) {
+                       return FALSE;
+               }
+
+               return $filesFound;
+       }
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_filebackend.php'])  {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_filebackend.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_globals.php b/t3lib/cache/backend/class.t3lib_cache_backend_globals.php
deleted file mode 100644 (file)
index 9f1b5b4..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-<?php
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2008 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_Globals extends t3lib_cache_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);
-               }
-       }
-}
-
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_globals.php'])      {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_globals.php']);
-}
-
-?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_globalsbackend.php b/t3lib/cache/backend/class.t3lib_cache_backend_globalsbackend.php
new file mode 100644 (file)
index 0000000..c65da63
--- /dev/null
@@ -0,0 +1,256 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2008 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
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_memcached.php b/t3lib/cache/backend/class.t3lib_cache_backend_memcached.php
deleted file mode 100644 (file)
index d22a6c3..0000000
+++ /dev/null
@@ -1,545 +0,0 @@
-<?php
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2008 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 by using Memcached.
- *
- * This backend uses the following types of Memcache keys:
- * - tag_xxx
- *   xxx is tag name, value is array of associated identifiers identifier. This
- *   is "forward" tag index. It is mainly used for obtaining content by tag
- *   (get identifier by tag -> get content by identifier)
- * - ident_xxx
- *   xxx is identifier, value is array of associated tags. This is "reverse" tag
- *   index. It provides quick access for all tags associated with this identifier
- *   and used when removing the identifier
- * - tagIndex
- *   Value is a List of all tags (array)
- * Each key is prepended with a prefix. By default prefix consists from two parts
- * separated by underscore character and ends in yet another underscore character:
- * - "TYPO3"
- * - Current site path obtained from the PATH_site constant
- * This prefix makes sure that keys from the different installations do not
- * conflict.
- *
- * This file is a backport from FLOW3 by Ingo Renner.
- *
- * @package TYPO3
- * @subpackage t3lib_cache
- * @version $Id$
- */
-class t3lib_cache_backend_Memcached extends t3lib_cache_AbstractBackend {
-
-       /**
-        * Instance of the PHP Memcache class
-        *
-        * @var Memcache
-        */
-       protected $memcache;
-
-       /**
-        * Array of Memcache server configurations
-        *
-        * @var array
-        */
-       protected $servers = array();
-
-       /**
-        * Indicates whether the memcache uses compression or not (requires zlib)
-        *
-        * @var boolean
-        */
-       protected $useCompressed;
-
-       /**
-        * A prefix to seperate stored data from other data possibly stored in the
-        * memcache. This prefix must be unique for each site in the tree. Default
-        * implementation uses MD5 of the current site path to make identifier prefix
-        * unique.
-        *
-        * @var string
-        */
-       protected $identifierPrefix;
-
-       /**
-        * Indicates whther the server is connected
-        *
-        * @var boolean
-        */
-       protected $serverConnected = false;
-
-       /**
-        * Constructs this backend
-        *
-        * @param mixed $options Configuration options - depends on the actual backend
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function __construct($options = array()) {
-               if (!extension_loaded('memcache')) {
-                       throw new t3lib_cache_Exception(
-                               'The PHP extension "memcached" must be installed and loaded in ' .
-                               'order to use the Memcached backend.',
-                               1213987706
-                       );
-               }
-
-               parent::__construct($options);
-
-               $this->memcache = new Memcache();
-               $this->identifierPrefix = $this->getIdentifierPrefix();
-
-               if (!count($this->servers)) {
-                       throw new t3lib_cache_Exception(
-                               'No servers were given to Memcache',
-                               1213115903
-                       );
-               }
-
-               foreach ($this->servers as $serverConf) {
-                       if (substr($serverConf, 0, 7) == 'unix://') {
-                               $host = $serverConf;
-                               $port = 0;
-                       } else {
-                               list($host, $port) = explode(':', $serverConf, 2);
-                       }
-
-                       if ($this->serverConnected) {
-                               $this->memcache->addserver($host, $port);
-                       } else {
-                                       // pconnect throws PHP warnings when it cannot connect!
-                               $this->serverConnected = @$this->memcache->pconnect($host, $port);
-                       }
-               }
-
-               if (!$this->serverConnected) {
-                       t3lib_div::sysLog('Unable to connect to any Memcached server', 'core', 3);
-               }
-       }
-
-       /**
-        * Sets servers property.
-        *
-        * @param       array   An array of servers to add (format: "host:port")
-        * @return      void
-        * @author      Christian Jul Jensen <julle@typo3.org>
-        */
-       protected function setServers(array $servers) {
-               $this->servers = $servers;
-       }
-
-       /**
-        * Sets for compression flag
-        *
-        * @param       boolean $enableCompression      New value of compression flag
-        * @return      void
-        * @author      Christian Jul Jensen <julle@typo3.org>
-        */
-       protected function setCompression($enableCompression) {
-               $this->useCompressed = $enableCompression;
-       }
-
-       /**
-        * Saves data in the cache.
-        *
-        * @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 liftime.
-        * @return void
-        * @throws t3lib_cache_Exception if no cache frontend has been set.
-        * @throws InvalidArgumentException if the identifier is not valid
-        * @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->serverConnected) {
-                       return;
-               }
-
-               if (!self::isValidEntryIdentifier($entryIdentifier)) {
-                       throw new InvalidArgumentException(
-                               '"' . $entryIdentifier . '" is not a valid cache entry identifier.',
-                               1207149191
-                       );
-               }
-
-               if (!$this->cache instanceof t3lib_cache_AbstractCache) {
-                       throw new t3lib_cache_Exception(
-                               'No cache frontend has been set yet via setCache().',
-                               1207149215
-                       );
-               }
-
-               if (!is_string($data)) {
-                       throw new t3lib_cache_Exception_InvalidData(
-                               'The specified data is of type "' . gettype($data) .
-                               '" but a string is expected.',
-                               1207149231
-                       );
-               }
-
-               foreach($tags as $tag) {
-                       if (!self::isValidTag($tag)) {
-                               throw new InvalidArgumentException(
-                                       '"' . $tag . '" is not a valid tag.',
-                                       1213120275
-                               );
-                       }
-               }
-
-               $expiration = $lifetime ? $lifetime : $this->defaultLifetime;
-               try {
-                       $this->remove($entryIdentifier);
-                       $success = $this->memcache->set(
-                               $this->identifierPrefix . $entryIdentifier,
-                               $data,
-                               $this->useCompressed,
-                               $expiration
-                       );
-
-                       if (!$success) {
-                               throw new t3lib_cache_Exception(
-                                       'Memcache was unable to connect to any server.',
-                                       1207165277
-                               );
-                       }
-
-                       $this->addTagsToTagIndex($tags);
-                       $this->addIdentifierToTags($entryIdentifier, $tags);
-               } catch(Exception $exception) {
-                       throw new t3lib_cache_Exception(
-                               'Memcache was unable to connect to any server. ' .
-                               $exception->getMessage(),
-                               1207208100
-                       );
-               }
-       }
-
-       /**
-        * Loads data from the cache.
-        *
-        * @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 Christian Jul Jensen <julle@typo3.org>
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        */
-       public function get($entryIdentifier) {
-               return !$this->serverConnected ? false : $this->memcache->get($this->identifierPrefix . $entryIdentifier);
-       }
-
-       /**
-        * Checks if a cache entry with the specified identifier exists.
-        *
-        * @param string An identifier specifying the cache entry
-        * @return boolean TRUE if such an entry exists, FALSE if not
-        * @author Christian Jul Jensen <julle@typo3.org>
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        */
-       public function has($entryIdentifier) {
-               return $this->serverConnected && $this->memcache->get($this->identifierPrefix . $entryIdentifier) !== false;
-       }
-
-       /**
-        * Removes all cache entries matching the specified identifier.
-        * Usually this only affects one entry but if - for what reason ever -
-        * old entries for the identifier still exist, they are removed as well.
-        *
-        * @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 Christian Jul Jensen <julle@typo3.org>
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        */
-       public function remove($entryIdentifier) {
-               $result = false;
-
-               if ($this->serverConnected) {
-                       $this->removeIdentifierFromAllTags($entryIdentifier);
-                       $this->memcache->delete($this->identifierPrefix . 'ident_' . $entryIdentifier);
-                       $result = $this->memcache->delete($this->identifierPrefix . $entryIdentifier);
-               }
-
-               return $result;
-       }
-
-       /**
-        * 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 of entries with all matching entries. An empty array if no entries matched
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        */
-       public function findEntriesByTag($tag) {
-               if (!self::isValidTag($tag)) {
-                       throw new InvalidArgumentException(
-                               '"' . $tag . '" is not a valid tag.',
-                               1213120307
-                       );
-               }
-
-               $entries = array();
-               $identifiers = $this->findIdentifiersTaggedWith($tag);
-               foreach($identifiers as $identifier) {
-                       $entries[] = $this->get($identifier);
-               }
-
-               return $entries;
-       }
-
-
-       /**
-        * 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.
-        *
-        * Beware that this flushes the complete memcached, not only the cache
-        * entries we stored there. We do this because:
-        *  it is expensive to keep track of all identifiers we put there
-        *  memcache is a cache, you should never rely on things being there
-        *
-        * @return void
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        */
-       public function flush() {
-               if ($this->serverConnected) {
-                       $this->memcache->flush();
-               }
-       }
-
-       /**
-        * 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 Karsten Dambekalns <karsten@typo3.org>
-        */
-       public function flushByTag($tag) {
-               $identifiers = $this->findIdentifiersTaggedWith($tag);
-               foreach($identifiers as $identifier) {
-                       $this->remove($identifier);
-               }
-       }
-
-
-       /**
-        * 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);
-               }
-       }
-
-       /**
-        * Returns an array with all known tags
-        *
-        * @return array
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        */
-       protected function getTagIndex() {
-               $tagIndex = $this->memcache->get($this->identifierPrefix . 'tagIndex');
-               return ($tagIndex == false ? array() : (array)$tagIndex);
-       }
-
-       /**
-        * Saves the tags known to the backend
-        *
-        * @param array Array of tags
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        */
-       protected function setTagIndex(array $tags) {
-               $this->memcache->set($this->identifierPrefix . 'tagIndex', array_unique($tags), 0, 0);
-       }
-
-       /**
-        * Adds the given tags to the tag index
-        *
-        * @param array Array of tags
-        * @return void
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        */
-       protected function addTagsToTagIndex(array $tags) {
-               if(count($tags)) {
-                       $this->setTagIndex(array_merge($tags, $this->getTagIndex()));
-               }
-       }
-
-       /**
-        * Removes the given tags from the tag index
-        *
-        * @param array $tags
-        * @return void
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        */
-       protected function removeTagsFromTagIndex(array $tags) {
-               if(count($tags)) {
-                       $this->setTagIndex(array_diff($this->getTagIndex(), $tags));
-               }
-       }
-
-       /**
-        * Associates the identifier with the given tags
-        *
-        * @param string $entryIdentifier
-        * @param array Array of tags
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        * @author      Dmitry Dulepov
-        */
-       protected function addIdentifierToTags($entryIdentifier, array $tags) {
-               if ($this->serverConnected) {
-                       foreach($tags as $tag) {
-                                       // Update tag-to-identifier index
-                               $identifiers = $this->findIdentifiersTaggedWith($tag);
-                               if (array_search($entryIdentifier, $identifiers) === false) {
-                                       $identifiers[] = $entryIdentifier;
-                                       $this->memcache->set($this->identifierPrefix . 'tag_' . $tag,
-                                               $identifiers);
-                               }
-
-                                       // Update identifier-to-tag index
-                               $existingTags = $this->findTagsForIdentifier($entryIdentifier);
-                               if (array_search($entryIdentifier, $existingTags) === false) {
-                                       $this->memcache->set($this->identifierPrefix . 'ident_' . $entryIdentifier,
-                                               array_merge($existingTags, $tags));
-                               }
-                       }
-               }
-       }
-
-       /**
-        * Removes association of the identifier with the given tags
-        *
-        * @param string $entryIdentifier
-        * @param array Array of tags
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        * @author      Dmitry Dulepov
-        */
-       protected function removeIdentifierFromAllTags($entryIdentifier) {
-               if ($this->serverConnected) {
-                               // Get tags for this identifier
-                       $tags = $this->findTagsForIdentifier($entryIdentifier);
-                               // Deassociate tags with this identifier
-                       foreach ($tags as $tag) {
-                               $identifiers = $this->findIdentifiersTaggedWith($tag);
-                                       // Formally array_search() below should never return false
-                                       // due to the behavior of findTagsForIdentifier(). But if
-                                       // reverse index is corrupted, we still can get 'false' from
-                                       // array_search(). This is not a problem because we are
-                                       // removing this identifier from anywhere.
-                               if (($key = array_search($entryIdentifier, $identifiers)) !== false) {
-                                       unset($identifiers[$key]);
-
-                                       if(count($identifiers)) {
-                                               $this->memcache->set(
-                                                       $this->identifierPrefix . 'tag_' . $tag,
-                                                       $identifiers
-                                               );
-                                       } else {
-                                               $this->removeTagsFromTagIndex(array($tag));
-                                               $this->memcache->delete($this->identifierPrefix . 'tag_' . $tag);
-                                       }
-                               }
-                       }
-
-                               // Clear reverse tag index for this identifier
-                       $this->memcache->delete($this->identifierPrefix . 'ident_' . $entryIdentifier);
-               }
-       }
-
-       /**
-        * Returns all identifiers associated with $tag
-        *
-        * @param string $tag
-        * @return array
-        * @author Karsten Dambekalns <karsten@typo3.org>
-        */
-       public function findIdentifiersTaggedWith($tag) {
-               $identifiers = !$this->serverConnected ? false : $this->memcache->get($this->identifierPrefix . 'tag_' . $tag);
-               return ($identifiers === false ? array() : $identifiers);
-       }
-
-       /**
-        * Finds all tags for the given identifier. This function uses reverse tag
-        * index to search for tags.
-        *
-        * @param       string  $identifier     Identifier to search tags for
-        * @return      array   Array with tags
-        */
-       protected function findTagsForIdentifier($identifier) {
-               $tags = !$this->serverConnected ? false : $this->memcache->get($this->identifierPrefix . 'ident_' . $identifier);
-               return ($tags == false ? array() : (array)$tags);
-       }
-
-       /**
-        * Returns idenfier prefix. Extensions can override this function to provide
-        * another identifier prefix if it is necessary for special purposes.
-        * Default identifier prefix is based on PATH_site only. In most cases
-        * it is enough because different installations use different paths and page
-        * IDs in the same installation never repeat.
-        *
-        * @return      string  Identifier prefix, ending with underscore
-        * @author      Dmitry Dulepov
-        */
-       protected function getIdentifierPrefix() {
-               return 'TYPO3_' . md5(PATH_site) . '_';
-       }
-}
-
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_memcached.php'])    {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_memcached.php']);
-}
-
-?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_memcachedbackend.php b/t3lib/cache/backend/class.t3lib_cache_backend_memcachedbackend.php
new file mode 100644 (file)
index 0000000..d99191d
--- /dev/null
@@ -0,0 +1,565 @@
+<?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 by using Memcached.
+ *
+ * This backend uses the following types of Memcache keys:
+ * - tag_xxx
+ *   xxx is tag name, value is array of associated identifiers identifier. This
+ *   is "forward" tag index. It is mainly used for obtaining content by tag
+ *   (get identifier by tag -> get content by identifier)
+ * - ident_xxx
+ *   xxx is identifier, value is array of associated tags. This is "reverse" tag
+ *   index. It provides quick access for all tags associated with this identifier
+ *   and used when removing the identifier
+ * - tagIndex
+ *   Value is a List of all tags (array)
+ * Each key is prepended with a prefix. By default prefix consists from two parts
+ * separated by underscore character and ends in yet another underscore character:
+ * - "TYPO3"
+ * - Current site path obtained from the PATH_site constant
+ * This prefix makes sure that keys from the different installations do not
+ * conflict.
+ *
+ * Note: When using the Memcached backend to store values of more than ~1 MB,
+ * the data will be split into chunks to make them fit into the memcached limits.
+ *
+ * This file is a backport from FLOW3 by Ingo Renner.
+ *
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @version $Id$
+ */
+class t3lib_cache_backend_MemcachedBackend extends t3lib_cache_backend_AbstractBackend {
+
+       /**
+        * Max bucket size, (1024*1024)-42 bytes
+        * @var int
+        */
+       const MAX_BUCKET_SIZE = 1048534;
+
+       /**
+        * Instance of the PHP Memcache class
+        *
+        * @var Memcache
+        */
+       protected $memcache;
+
+       /**
+        * Array of Memcache server configurations
+        *
+        * @var array
+        */
+       protected $servers = array();
+
+       /**
+        * Indicates whether the memcache uses compression or not (requires zlib),
+        * either 0 or MEMCACHE_COMPRESSED
+        *
+        * @var int
+        */
+       protected $flags;
+
+       /**
+        * A prefix to seperate stored data from other data possibly stored in the
+        * memcache. This prefix must be unique for each site in the tree. Default
+        * implementation uses MD5 of the current site path to make identifier prefix
+        * unique.
+        *
+        * @var string
+        */
+       protected $identifierPrefix;
+
+       /**
+        * Indicates whther the server is connected
+        *
+        * @var boolean
+        */
+       protected $serverConnected = false;
+
+       /**
+        * Constructs this backend
+        *
+        * @param mixed $options Configuration options - depends on the actual backend
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function __construct($options = array()) {
+               if (!extension_loaded('memcache')) {
+                       throw new t3lib_cache_Exception(
+                               'The PHP extension "memcached" must be installed and loaded in ' .
+                               'order to use the Memcached backend.',
+                               1213987706
+                       );
+               }
+
+               parent::__construct($options);
+
+               $this->memcache = new Memcache();
+               $this->identifierPrefix = $this->getIdentifierPrefix();
+               $defaultPort = ini_get('memcache.default_port');
+
+               if (!count($this->servers)) {
+                       throw new t3lib_cache_Exception(
+                               'No servers were given to Memcache',
+                               1213115903
+                       );
+               }
+
+               foreach ($this->servers as $serverConfiguration) {
+                       if (substr($serverConfiguration, 0, 7) == 'unix://') {
+                               $host = $serverConfiguration;
+                               $port = 0;
+                       } else {
+                               if (substr($serverConfiguration, 0, 6) === 'tcp://') {
+                                       $server = substr($serverConfiguration, 6);
+                               }
+                               if (strstr($serverConfiguration, ':') !== FALSE) {
+                                       list($host, $port) = explode(':', $serverConfiguration, 2);
+                               } else {
+                                       $host = $serverConfiguration;
+                                       $port = $defaultPort;
+                               }
+                       }
+
+                       if ($this->serverConnected) {
+                               $this->memcache->addserver($host, $port);
+                       } else {
+                                       // pconnect throws PHP warnings when it cannot connect!
+                               $this->serverConnected = @$this->memcache->pconnect($host, $port);
+                       }
+               }
+
+               if (!$this->serverConnected) {
+                       t3lib_div::sysLog('Unable to connect to any Memcached server', 'core', 3);
+               }
+       }
+
+       /**
+        * Setter for servers to be used. Expects an array,  the values are expected
+        * to be formatted like "<host>[:<port>]" or "unix://<path>"
+        *
+        * @param       array   An array of servers to add.
+        * @return      void
+        * @author Christian Jul Jensen <julle@typo3.org>
+        */
+       protected function setServers(array $servers) {
+               $this->servers = $servers;
+       }
+
+       /**
+        * Sets for compression flags bit
+        *
+        * @param       boolean New value of compression flag
+        * @return      void
+        * @author      Christian Jul Jensen <julle@typo3.org>
+        */
+       protected function setCompression($useCompression) {
+       if ($useCompression === TRUE) {
+                       $this->flags ^= MEMCACHE_COMPRESSED;
+               } else {
+                       $this->flags &= ~MEMCACHE_COMPRESSED;
+               }
+       }
+
+       /**
+        * Saves data in the cache.
+        *
+        * @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 liftime.
+        * @return void
+        * @throws t3lib_cache_Exception if no cache frontend has been set.
+        * @throws InvalidArgumentException if the identifier is not valid or the final memcached key is longer than 250 characters
+        * @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(
+                               'Could not set value. Key more than 250 characters (' . $this->identifierPrefix . $entryIdentifier . ').',
+                               1235839340
+                       );
+               }
+
+               if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
+                       throw new t3lib_cache_Exception(
+                               'No cache frontend has been set yet via setCache().',
+                               1207149215
+                       );
+               }
+
+               if (!is_string($data)) {
+                       throw new t3lib_cache_Exception_InvalidData(
+                               'The specified data is of type "' . gettype($data) .
+                               '" but a string is expected.',
+                               1207149231
+                       );
+               }
+
+               $tags[] = '%MEMCACHEBE%' . $this->cache->getIdentifier();
+               $expiration = $lifetime !== NULL ? $lifetime : $this->defaultLifetime;
+
+               try {
+                       if(strlen($data) > self::MAX_BUCKET_SIZE) {
+                               $data = str_split($data, 1024 * 1000);
+                               $success = TRUE;
+                               $chunkNumber = 1;
+
+                               foreach ($data as $chunk) {
+                                       $success &= $this->memcache->set(
+                                               $this->identifierPrefix . $entryIdentifier . '_chunk_' . $chunkNumber,
+                                               $chunk,
+                                               $this->flags,
+                                               $expiration
+                                       );
+                                       $chunkNumber++;
+                               }
+                               $success &= $this->memcache->set(
+                                       $this->identifierPrefix . $entryIdentifier,
+                                       'TYPO3*chunked:' . $chunkNumber,
+                                       $this->flags,
+                                       $expiration
+                               );
+                       } else {
+                               $success = $this->memcache->set(
+                                       $this->identifierPrefix . $entryIdentifier,
+                                       $data,
+                                       $this->flags,
+                                       $expiration
+                               );
+                       }
+
+                       if ($success === TRUE) {
+                               $this->removeIdentifierFromAllTags($entryIdentifier);
+                               $this->addTagsToTagIndex($tags);
+                               $this->addIdentifierToTags($entryIdentifier, $tags);
+                       }
+               } catch(Exception $exception) {
+                       throw new t3lib_cache_Exception(
+                               'Could not set value. ' .
+                               $exception->getMessage(),
+                               1207208100
+                       );
+               }
+       }
+
+       /**
+        * Loads data from the cache.
+        *
+        * @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 Christian Jul Jensen <julle@typo3.org>
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function get($entryIdentifier) {
+               $value = $this->memcache->get($this->identifierPrefix . $entryIdentifier);
+
+               if (substr($value, 0, 14) === 'TYPO3*chunked:') {
+                       list( , $chunkCount) = explode(':', $value);
+                       $value = '';
+
+                       for ($chunkNumber = 1 ; $chunkNumber < $chunkCount; $chunkNumber++) {
+                               $value .= $this->memcache->get($this->identifierPrefix . $entryIdentifier . '_chunk_' . $chunkNumber);
+                       }
+               }
+
+               return $value;
+       }
+
+       /**
+        * Checks if a cache entry with the specified identifier exists.
+        *
+        * @param string An identifier specifying the cache entry
+        * @return boolean TRUE if such an entry exists, FALSE if not
+        * @author Christian Jul Jensen <julle@typo3.org>
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function has($entryIdentifier) {
+               return $this->serverConnected && $this->memcache->get($this->identifierPrefix . $entryIdentifier) !== false;
+       }
+
+       /**
+        * Removes all cache entries matching the specified identifier.
+        * Usually this only affects one entry but if - for what reason ever -
+        * old entries for the identifier still exist, they are removed as well.
+        *
+        * @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 Christian Jul Jensen <julle@typo3.org>
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function remove($entryIdentifier) {
+               $this->removeIdentifierFromAllTags($entryIdentifier);
+               return $this->memcache->delete($this->identifierPrefix . $entryIdentifier);
+       }
+
+       /**
+        * Finds and returns all cache entry identifiers which are tagged by the
+        * specified tag.
+        *
+        * @param string The tag to search for
+        * @return array An array of entries with all matching entries. An empty array if no entries matched
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function findIdentifiersByTag($tag) {
+               $identifiers = $this->memcache->get($this->identifierPrefix . 'tag_' . $tag);
+
+               if ($identifiers !== FALSE) {
+                       return (array) $identifiers;
+               } else {
+                       return array();
+               }
+       }
+
+
+       /**
+        * Finds and returns all cache entry identifiers which are tagged by the
+        * specified tags.
+        *
+        * @param array 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>
+        */
+       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 Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function flush() {
+               if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
+                       throw new t3lib_cache_Exception('No cache frontend has been set via setCache() yet.', 1204111376);
+               }
+
+               $this->flushByTag('%MEMCACHEBE%' . $this->cache->getIdentifier());
+       }
+
+       /**
+        * 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 Karsten Dambekalns <karsten@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 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);
+               }
+       }
+
+       /**
+        * Returns an array with all known tags
+        *
+        * @return array
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function getTagIndex() {
+               $tagIndex = $this->memcache->get($this->identifierPrefix . 'tagIndex');
+               return ($tagIndex == false ? array() : (array)$tagIndex);
+       }
+
+       /**
+        * Saves the tags known to the backend
+        *
+        * @param array Array of tags
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function setTagIndex(array $tags) {
+               $this->memcache->set($this->identifierPrefix . 'tagIndex', array_unique($tags), 0, 0);
+       }
+
+       /**
+        * Adds the given tags to the tag index
+        *
+        * @param array Array of tags
+        * @return void
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function addTagsToTagIndex(array $tags) {
+               if(count($tags)) {
+                       $this->setTagIndex(array_merge($tags, $this->getTagIndex()));
+               }
+       }
+
+       /**
+        * Removes the given tags from the tag index
+        *
+        * @param array $tags
+        * @return void
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       protected function removeTagsFromTagIndex(array $tags) {
+               if(count($tags)) {
+                       $this->setTagIndex(array_diff($this->getTagIndex(), $tags));
+               }
+       }
+
+       /**
+        * Associates the identifier with the given tags
+        *
+        * @param string $entryIdentifier
+        * @param array Array of tags
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        * @author      Dmitry Dulepov
+        */
+       protected function addIdentifierToTags($entryIdentifier, array $tags) {
+               if ($this->serverConnected) {
+                       foreach($tags as $tag) {
+                                       // Update tag-to-identifier index
+                               $identifiers = $this->findIdentifiersByTag($tag);
+                               if (array_search($entryIdentifier, $identifiers) === false) {
+                                       $identifiers[] = $entryIdentifier;
+                                       $this->memcache->set($this->identifierPrefix . 'tag_' . $tag,
+                                               $identifiers);
+                               }
+
+                                       // Update identifier-to-tag index
+                               $existingTags = $this->findTagsByIdentifier($entryIdentifier);
+                               if (array_search($entryIdentifier, $existingTags) === false) {
+                                       $this->memcache->set($this->identifierPrefix . 'ident_' . $entryIdentifier,
+                                               array_merge($existingTags, $tags));
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Removes association of the identifier with the given tags
+        *
+        * @param string $entryIdentifier
+        * @param array Array of tags
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        * @author      Dmitry Dulepov
+        */
+       protected function removeIdentifierFromAllTags($entryIdentifier) {
+               if ($this->serverConnected) {
+                               // Get tags for this identifier
+                       $tags = $this->findTagsByIdentifier($entryIdentifier);
+                               // Deassociate tags with this identifier
+                       foreach ($tags as $tag) {
+                               $identifiers = $this->findIdentifiersByTag($tag);
+                                       // Formally array_search() below should never return false
+                                       // due to the behavior of findTagsForIdentifier(). But if
+                                       // reverse index is corrupted, we still can get 'false' from
+                                       // array_search(). This is not a problem because we are
+                                       // removing this identifier from anywhere.
+                               if (($key = array_search($entryIdentifier, $identifiers)) !== false) {
+                                       unset($identifiers[$key]);
+
+                                       if(count($identifiers)) {
+                                               $this->memcache->set(
+                                                       $this->identifierPrefix . 'tag_' . $tag,
+                                                       $identifiers
+                                               );
+                                       } else {
+                                               $this->removeTagsFromTagIndex(array($tag));
+                                               $this->memcache->delete($this->identifierPrefix . 'tag_' . $tag);
+                                       }
+                               }
+                       }
+
+                               // Clear reverse tag index for this identifier
+                       $this->memcache->delete($this->identifierPrefix . 'ident_' . $entryIdentifier);
+               }
+       }
+
+       /**
+        * Finds all tags for the given identifier. This function uses reverse tag
+        * index to search for tags.
+        *
+        * @param       string  Identifier to find tags by
+        * @return      array   Array with tags
+        * @author Dmitry Dulepov
+        */
+       protected function findTagsByIdentifier($identifier) {
+               $tags = $this->memcache->get($this->identifierPrefix . 'ident_' . $identifier);
+               return ($tags === FALSE ? array() : (array)$tags);
+       }
+
+       /**
+        * Returns idenfier prefix. Extensions can override this function to provide
+        * another identifier prefix if it is necessary for special purposes.
+        * Default identifier prefix is based on PATH_site only. In most cases
+        * it is enough because different installations use different paths and page
+        * IDs in the same installation never repeat.
+        *
+        * @return      string  Identifier prefix, ending with underscore
+        * @author      Dmitry Dulepov
+        */
+       protected function getIdentifierPrefix() {
+               return 'TYPO3_' . md5(PATH_site) . '_';
+       }
+
+       /**
+        * Does nothing, as memcached does GC itself
+        *
+        * @return void
+        */
+       public function collectGarbage() {
+       }
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_memcachedbackend.php'])     {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_memcachedbackend.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_null.php b/t3lib/cache/backend/class.t3lib_cache_backend_null.php
deleted file mode 100644 (file)
index 05389b8..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-<?php
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2008 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
- *
- * This file is a backport from FLOW3
- *
- * @package TYPO3
- * @subpackage t3lib_cache
- * @version $Id$
- */
-class t3lib_cache_backend_Null extends t3lib_cache_AbstractBackend {
-
-       /**
-        * Acts as if it would save data
-        *
-        * @param string ignored
-        * @param string ignored
-        * @param array ignored
-        * @param integer ignored
-        * @return void
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
-       }
-
-       /**
-        * Returns False
-        *
-        * @param string ignored
-        * @return boolean FALSE
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function get($entryIdentifier) {
-               return FALSE;
-       }
-
-       /**
-        * Returns False
-        *
-        * @param string ignored
-        * @return boolean FALSE
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function has($entryIdentifier) {
-               return FALSE;
-       }
-
-       /**
-        * Does nothing
-        *
-        * @param string ignored
-        * @return boolean FALSE
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function remove($entryIdentifier) {
-               return FALSE;
-       }
-
-       /**
-        * Returns an empty array
-        *
-        * @param string ignored
-        * @return array An empty array
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function findEntriesByTag($tag) {
-               return array();
-       }
-
-       /**
-        * Returns an empty array
-        *
-        * @param string ignored
-        * @return array An empty array
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       public function findEntriesByTags(array $tags) {
-               return array();
-       }
-
-       /**
-        * Does nothing
-        *
-        * @return void
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function flush() {
-       }
-
-       /**
-        * Does nothing
-        *
-        * @param string ignored
-        * @return void
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function flushByTag($tag) {
-       }
-
-       /**
-        * Does nothing
-        *
-        * @param array ignored
-        * @return void
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       public function flushByTags(array $tags) {
-       }
-}
-
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_null.php']) {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_null.php']);
-}
-
-?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_nullbackend.php b/t3lib/cache/backend/class.t3lib_cache_backend_nullbackend.php
new file mode 100644 (file)
index 0000000..ac68705
--- /dev/null
@@ -0,0 +1,149 @@
+<?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
+ *
+ * This file is a backport from FLOW3
+ *
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @version $Id$
+ */
+class t3lib_cache_backend_NullBackend extends t3lib_cache_backend_AbstractBackend {
+
+       /**
+        * Acts as if it would save data
+        *
+        * @param string ignored
+        * @param string ignored
+        * @param array ignored
+        * @param integer ignored
+        * @return void
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
+       }
+
+       /**
+        * Returns False
+        *
+        * @param string ignored
+        * @return boolean FALSE
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function get($entryIdentifier) {
+               return FALSE;
+       }
+
+       /**
+        * Returns False
+        *
+        * @param string ignored
+        * @return boolean FALSE
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function has($entryIdentifier) {
+               return FALSE;
+       }
+
+       /**
+        * Does nothing
+        *
+        * @param string ignored
+        * @return boolean FALSE
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function remove($entryIdentifier) {
+               return FALSE;
+       }
+
+       /**
+        * Returns an empty array
+        *
+        * @param string ignored
+        * @return array An empty array
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function findIdentifiersByTag($tag) {
+               return array();
+       }
+
+       /**
+        * Returns an empty array
+        *
+        * @param string ignored
+        * @return array An empty array
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function findIdentifiersByTags(array $tags) {
+               return array();
+       }
+
+       /**
+        * Does nothing
+        *
+        * @return void
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function flush() {
+       }
+
+       /**
+        * Does nothing
+        *
+        * @param string ignored
+        * @return void
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function flushByTag($tag) {
+       }
+
+       /**
+        * Does nothing
+        *
+        * @param array ignored
+        * @return void
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function flushByTags(array $tags) {
+       }
+
+       /**
+        * Does nothing
+        *
+        * @return void
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function collectGarbage() {
+       }
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_nullbackend.php'])  {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_nullbackend.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/cache/backend/interfaces/interface.t3lib_cache_backend_backend.php b/t3lib/cache/backend/interfaces/interface.t3lib_cache_backend_backend.php
new file mode 100644 (file)
index 0000000..e84c7f1
--- /dev/null
@@ -0,0 +1,141 @@
+<?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.
+*  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!
+***************************************************************/
+
+
+/**
+ * interface for a Cache Backend
+ *
+ * @author     Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+interface t3lib_cache_backend_Backend {
+
+       /**
+        * Sets a reference to the cache frontend which uses this backend
+        *
+        * @param t3lib_cache_frontend_Frontend $cache The frontend for this backend
+        * @return void
+        */
+       public function setCache(t3lib_cache_frontend_Frontend $cache);
+
+       /**
+        * Saves data in the cache.
+        *
+        * @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 liftime.
+        * @return void
+        * @throws t3lib_cache_Exception if no cache frontend has been set.
+        * @throws InvalidArgumentException if the identifier is not valid
+        * @throws t3lib_cache_Exception_InvalidData if the data is not a string
+        */
+       public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL);
+
+       /**
+        * 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
+        */
+       public function get($entryIdentifier);
+
+       /**
+        * 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
+        */
+       public function has($entryIdentifier);
+
+       /**
+        * Removes all cache entries matching the specified identifier.
+        * Usually this only affects one entry but if - for what reason ever -
+        * old entries for the identifier still exist, they are removed as well.
+        *
+        * @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
+        */
+       public function remove($entryIdentifier);
+
+       /**
+        * Removes all cache entries of this cache.
+        *
+        * @return void
+        */
+       public function flush();
+
+       /**
+        * 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
+        */
+       public function flushByTag($tag);
+
+       /**
+        * 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);
+
+       /**
+        * 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
+        */
+       public function findIdentifiersByTag($tag);
+
+       /**
+        * 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);
+
+       /**
+        * Does garbage collection
+        *
+        * @return void
+        */
+       public function collectGarbage();
+
+}
+
+
+?>
\ No newline at end of file
diff --git a/t3lib/cache/class.t3lib_cache_abstractbackend.php b/t3lib/cache/class.t3lib_cache_abstractbackend.php
deleted file mode 100644 (file)
index c2a9fbc..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-<?php
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2008 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!
-***************************************************************/
-
-/**
- * An abstract caching backend
- *
- * This file is a backport from FLOW3
- *
- * @author     Ingo Renner <ingo@typo3.org>
- * @package TYPO3
- * @subpackage t3lib_cache
- * @version $Id$
- */
-abstract class t3lib_cache_AbstractBackend {
-
-       /**
-        * Pattern an entry identifer must match.
-        */
-       const PATTERN_ENTRYIDENTIFIER = '/^[a-zA-Z0-9_%]{1,250}$/';
-
-       /**
-        * Pattern a tag identifer must match.
-        */
-       const PATTERN_TAG = '/^[a-zA-Z0-9_%]{1,250}$/';
-
-       /**
-        * @var t3lib_cache_AbstractCache Reference to the cache which uses this backend
-        */
-       protected $cache;
-
-       /**
-        * @var integer Default lifetime of a cache entry in seconds
-        */
-       protected $defaultLifetime = 3600;
-
-
-       /**
-        * Constructs this backend
-        *
-        * @param mixed Configuration options - depends on the actual backend
-        */
-       public function __construct(array $options = array()) {
-               if (is_array($options) || $options instanceof ArrayAccess) {
-                       foreach ($options as $optionKey => $optionValue) {
-                               $methodName = 'set' . ucfirst($optionKey);
-                               if (method_exists($this, $methodName)) {
-                                       $this->$methodName($optionValue);
-                               }
-                       }
-               }
-       }
-
-       /**
-        * Sets a reference to the cache which uses this backend
-        *
-        * @param t3lib_cache_AbstractCache The frontend for this backend
-        * @return void
-        */
-       public function setCache(t3lib_cache_AbstractCache $cache) {
-               $this->cache = $cache;
-       }
-
-       /**
-        * Saves data in the cache.
-        *
-        * @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 liftime.
-        * @return void
-        * @throws t3lib_cache_Exception if no cache frontend has been set.
-        * @throws InvalidArgumentException if the identifier is not valid
-        * @throws t3lib_cache_Exception_InvalidData if the data is not a string
-        */
-       abstract public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL);
-
-       /**
-        * Loads data from the cache.
-        *
-        * @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
-        */
-       abstract public function get($entryIdentifier);
-
-       /**
-        * Checks if a cache entry with the specified identifier exists.
-        *
-        * @param string An identifier specifying the cache entry
-        * @return boolean TRUE if such an entry exists, FALSE if not
-        */
-       abstract public function has($entryIdentifier);
-
-       /**
-        * Removes all cache entries matching the specified identifier.
-        * Usually this only affects one entry but if - for what reason ever -
-        * old entries for the identifier still exist, they are removed as well.
-        *
-        * @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
-        */
-       abstract public function remove($entryIdentifier);
-
-       /**
-        * Removes all cache entries of this cache.
-        *
-        * @return void
-        */
-       abstract public function flush();
-
-       /**
-        * Removes all cache entries of this cache which are tagged by the specified tag.
-        *
-        * @param string The tag the entries must have
-        * @return void
-        */
-       abstract public function flushByTag($tag);
-
-       /**
-        * Removes all cache entries of this cache which are tagged by the specified tags.
-        *
-        * @param       array   The tags the entries must have
-        * @return void
-        */
-       abstract public function flushByTags(array $tags);
-
-       /**
-        * Finds and returns all cache entry identifiers 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
-        */
-       abstract public function findEntriesByTag($tag);
-
-       /**
-        * 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
-        */
-       abstract public function findEntriesByTags(array $tags);
-
-       /**
-        * Checks the validity of an entry identifier. Returns true if it's valid.
-        *
-        * @param string An identifier to be checked for validity
-        * @return boolean
-        * @author Christian Jul Jensen <julle@typo3.org>
-        */
-       static public function isValidEntryIdentifier($identifier) {
-               return preg_match(self::PATTERN_ENTRYIDENTIFIER, $identifier) === 1;
-       }
-
-       /**
-        * Checks the validity of a tag. Returns true if it's valid.
-        *
-        * @param string An identifier to be checked for validity
-        * @return boolean
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       static public function isValidTag($tag) {
-               return preg_match(self::PATTERN_TAG, $tag) === 1;
-       }
-
-}
-
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_abstractbackend.php'])      {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_abstractbackend.php']);
-}
-
-?>
\ No newline at end of file
diff --git a/t3lib/cache/class.t3lib_cache_abstractcache.php b/t3lib/cache/class.t3lib_cache_abstractcache.php
deleted file mode 100644 (file)
index 4eb39c0..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-<?php
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2008 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!
-***************************************************************/
-
-
-/**
- * An abstract cache
- *
- * This file is a backport from FLOW3
- *
- * @package TYPO3
- * @subpackage t3lib_cache
- * @version $Id$
- */
-abstract class t3lib_cache_AbstractCache {
-
-       const PATTERN_IDENTIFIER = '/^[a-zA-Z0-9_%]{1,250}$/';
-
-       /**
-        * @var string Identifies this cache
-        */
-       protected $identifier;
-
-       /**
-        * @var t3lib_cache_AbstractBackend
-        */
-       protected $backend;
-
-       /**
-        * Constructs the cache
-        *
-        * @param string A identifier which describes this cache
-        * @param t3lib_cache_AbstractBackend Backend to be used for this cache
-        * @author Robert Lemke <robert@typo3.org>
-        * @throws InvalidArgumentException if the identifier doesn't match PATTERN_IDENTIFIER
-        */
-       public function __construct($identifier, t3lib_cache_AbstractBackend $backend) {
-               if (!preg_match(self::PATTERN_IDENTIFIER, $identifier)) {
-                       throw new InvalidArgumentException('"' . $identifier . '" is not a valid cache identifier.', 1203584729);
-               }
-
-               $this->identifier = $identifier;
-               $this->backend    = $backend;
-               $this->backend->setCache($this);
-       }
-
-       /**
-        * Returns this cache's identifier
-        *
-        * @return string The identifier for this cache
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function getIdentifier() {
-               return $this->identifier;
-       }
-
-       /**
-        * Returns the backend used by this cache
-        *
-        * @return t3lib_cache_AbstractBackend The backend used by this cache
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function getBackend() {
-               return $this->backend;
-       }
-
-       /**
-        * Saves data in the cache.
-        *
-        * @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
-        * @return void
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       abstract public function set($entryIdentifier, $data, array $tags = array(), $lifetime = null);
-
-       /**
-        * Loads data from the cache.
-        *
-        * @param string Something which identifies the cache entry - depends on concrete cache
-        * @return mixed
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       abstract public function get($entryIdentifier);
-
-       /**
-        * Finds, loads, 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 all matching entries. An empty array if no entries matched
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       public function getByTag($tag) {
-               $loadedEntries = array();
-               $foundEntries  = $this->findEntriesByTag($tag);
-
-               foreach($foundEntries as $foundEntryIdentifier) {
-                       $loadedEntries[$foundEntryIdentifier] = $this->get($foundEntryIdentifier);
-               }
-
-               return $loadedEntries;
-       }
-
-       /**
-        * 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 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
-        */
-       public function findEntriesByTag($tag) {
-               return $this->backend->findEntriesByTag($tag);
-       }
-
-       /**
-        * 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
-        */
-       public function findEntriesByTags(array $tags) {
-               return $this->backend->findEntriesByTags($tags);
-       }
-
-       /**
-        * Checks if a cache entry with the specified identifier exists.
-        *
-        * @param string An identifier specifying the cache entry
-        * @return boolean TRUE if such an entry exists, FALSE if not
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       abstract public function has($entryIdentifier);
-
-       /**
-        * Removes the given cache entry from the cache.
-        *
-        * @param string An identifier specifying the cache entry
-        * @return boolean TRUE if such an entry exists, FALSE if not
-        * @author Sebastian Kurfuerst <sebastian@typo3.org>
-        */
-       abstract public function remove($entryIdentifier);
-
-       /**
-        * Removes all cache entries of this cache.
-        *
-        * @return void
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function flush() {
-               $this->backend->flush();
-       }
-
-       /**
-        * 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) {
-               $this->backend->flushByTag($tag);
-       }
-
-       /**
-        * Removes all cache entries of this cache which are tagged by the specified tag.
-        *
-        * @param       array   Array of tags to search for and to remove the cache entries, the "*" wildcard is supported
-        * @return void
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       public function flushByTags(array $tags) {
-               $this->backend->flushByTags($tags);
-       }
-}
-
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_abstractcache.php'])        {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_abstractcache.php']);
-}
-
-?>
\ No newline at end of file
index 315f928..5e27487 100644 (file)
@@ -44,13 +44,15 @@ class t3lib_cache_Factory implements t3lib_Singleton {
        protected $cacheManager;
 
        /**
-        * Constructs this cache factory
+        * Injects the cache manager.
         *
-        * @param t3lib_cache_Manager A reference to the cache manager
+        * This is called by the cache manager itself
+        *
+        * @param t3lib_cache_Manager The cache manager
+        * @return void
         * @author Robert Lemke <robert@typo3.org>
-        * @author Ingo Renner <ingo@typo3.org>
         */
-       public function __construct(t3lib_cache_Manager $cacheManager) {
+       public function setCacheManager(t3lib_cache_Manager $cacheManager) {
                $this->cacheManager = $cacheManager;
        }
 
@@ -62,7 +64,7 @@ class t3lib_cache_Factory implements t3lib_Singleton {
         * @param string Name of the cache frontend
         * @param string Name of the cache backend
         * @param array (optional) Array of backend options
-        * @return t3lib_cache_AbstractCache The created cache frontend
+        * @return t3lib_cache_frontend_Frontend The created cache frontend
         * @author Robert Lemke <robert@typo3.org>
         */
        public function create($cacheIdentifier, $cacheName, $backendName, array $backendOptions = array()) {
@@ -78,10 +80,9 @@ class t3lib_cache_Factory implements t3lib_Singleton {
                        t3lib_div::requireOnce($backendRequireFile);
                }
 
-               $backendClassName = t3lib_div::makeInstanceClassName($backendClassReference);
-               $backend = new $backendClassName($backendOptions);
+               $backend = t3lib_div::makeInstance($backendClassReference, $backendOptions);
 
-               if (!$backend instanceof t3lib_cache_AbstractBackend) {
+               if (!$backend instanceof t3lib_cache_backend_Backend) {
                        throw new t3lib_cache_exception_InvalidCache(
                                '"' .$backendName . '" is not a valid cache backend.',
                                1216304301
@@ -99,11 +100,10 @@ class t3lib_cache_Factory implements t3lib_Singleton {
                        t3lib_div::requireOnce($cacheRequireFile);
                }
 
-               $cacheClassName = t3lib_div::makeInstanceClassName($cacheClassReference);
-               $cache = new $cacheClassName($cacheIdentifier, $backend);
+               $cache = t3lib_div::makeInstance($cacheClassReference, $cacheIdentifier, $backend);
 
 
-               if (!$cache instanceof t3lib_cache_AbstractCache) {
+               if (!$cache instanceof t3lib_cache_frontend_Frontend) {
                        throw new t3lib_cache_exception_InvalidCache(
                                '"' .$cacheName . '" is not a valid cache.',
                                1216304300
index ae0fa4c..49b0a37 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008 Ingo Renner <ingo@typo3.org>
+*  (c) 2009 Ingo Renner <ingo@typo3.org>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -37,25 +37,94 @@ class t3lib_cache_Manager implements t3lib_Singleton {
        /**
         * @const Cache Entry depends on the PHP code of the packages
         */
-       const TAG_PACKAGES_CODE = '%PACKAGES_CODE';
+       const TAG_PACKAGES_CODE = '%PACKAGES_CODE%';
+
+       /**
+        * @var t3lib_cache_Factory
+        */
+       protected $cacheFactory;
 
        /**
         * @var array Registered Caches
         */
        protected $caches = array();
 
+       protected $cacheConfigurations = array(
+               'default' => array(
+                       'frontend'       => 't3lib_cache_frontend_VariableFrontend',
+                       'backend'        =>  't3lib_cache_backend_FileBackend',
+                       'backendOptions' => array()
+               )
+       );
+
+       /**
+        * Sets configurations for caches. The key of each entry specifies the
+        * cache identifier and the value is an array of configuration options.
+        * Possible options are:
+        *
+        *   frontend
+        *   backend
+        *   backendOptions
+        *
+        * If one of the options is not specified, the default value is assumed.
+        * Existing cache configurations are preserved.
+        *
+        * @param       array   The cache configurations to set
+        * @return      void
+        * @author      Robert Lemke <robert@typo3.org>
+        */
+       public function setCacheConfigurations(array $cacheConfigurations) {
+               foreach ($cacheConfigurations as $identifier => $configuration) {
+                       if (!is_array($configuration)) {
+                               throw new InvalidArgumentException('The cache configuration for cache "' . $identifier . '" was not an array as expected.', 1235838075);
+                       }
+                       $this->cacheConfigurations[$identifier] = $configuration;
+               }
+       }
+
+       /**
+        * Injects the cache factory
+        *
+        * @param       t3lib_cache_Factory     The cache factory
+        * @return void
+        * @author Robert Lemke <robert@typo3.org>
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function setCacheFactory(t3lib_cache_Factory $cacheFactory) {
+               $this->cacheFactory = $cacheFactory;
+               $this->cacheFactory->setCacheManager($this);
+       }
+
+       /**
+        * Initializes the cache manager
+        *
+        * @return void
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function initialize() {
+               foreach ($this->cacheConfigurations as $identifier => $configuration) {
+                       if ($identifier !== 'default') {
+                               $frontend       = isset($configuration['frontend'])       ? $configuration['frontend']       : $this->cacheConfigurations['default']['frontend'];
+                               $backend        = isset($configuration['backend'])        ? $configuration['backend']        : $this->cacheConfigurations['default']['backend'];
+                               $backendOptions = isset($configuration['backendOptions']) ? $configuration['backendOptions'] : $this->cacheConfigurations['default']['backendOptions'];
+
+                               $cache = $this->cacheFactory->create($identifier, $frontend, $backend, $backendOptions);
+                       }
+               }
+       }
+
        /**
         * Registers a cache so it can be retrieved at a later point.
         *
-        * @param t3lib_cache_AbstractCache The cache to be registered
+        * @param t3lib_cache_frontend_Frontend The cache frontend to be registered
         * @return void
-        * @throws t3lib_cache_DuplicateIdentifier if a cache with the given identifier has already been registered.
+        * @throws t3lib_cache_exception_DuplicateIdentifier if a cache with the given identifier has already been registered.
         * @author Robert Lemke <robert@typo3.org>
         */
-       public function registerCache(t3lib_cache_AbstractCache $cache) {
+       public function registerCache(t3lib_cache_frontend_Frontend $cache) {
                $identifier = $cache->getIdentifier();
 
-               if (array_key_exists($identifier, $this->caches)) {
+               if (isset($this->caches[$identifier])) {
                        throw new t3lib_cache_exception_DuplicateIdentifier(
                                'A cache with identifier "' . $identifier . '" has already been registered.',
                                1203698223
@@ -69,11 +138,11 @@ class t3lib_cache_Manager implements t3lib_Singleton {
         * Returns the cache specified by $identifier
         *
         * @param string Identifies which cache to return
-        * @return t3lib_cache_AbstractCache The specified cache
-        * @throws t3lib_cache_Exception_NoSuchCache
+        * @return t3lib_cache_frontend_Cache The specified cache frontend
+        * @throws t3lib_cache_exception_NoSuchCache
         */
        public function getCache($identifier) {
-               if (!array_key_exists($identifier, $this->caches)) {
+               if (!isset($this->caches[$identifier])) {
                        throw new t3lib_cache_exception_NoSuchCache(
                                'A cache with identifier "' . $identifier . '" does not exist.',
                                1203699034
@@ -91,7 +160,7 @@ class t3lib_cache_Manager implements t3lib_Singleton {
         * @author Robert Lemke <robert@typo3.org>
         */
        public function hasCache($identifier) {
-               return array_key_exists($identifier, $this->caches);
+               return isset($this->caches[$identifier]);
        }
 
        /**
diff --git a/t3lib/cache/class.t3lib_cache_variablecache.php b/t3lib/cache/class.t3lib_cache_variablecache.php
deleted file mode 100644 (file)
index a137a07..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2008 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 cache for any kinds of PHP variables
- *
- * This file is a backport from FLOW3
- *
- * @package TYPO3
- * @subpackage t3lib_cache
- * @version $Id$
- */
-class t3lib_cache_VariableCache extends t3lib_cache_AbstractCache {
-
-       /**
-        * Saves the value of a PHP variable in the cache. Note that the variable
-        * will be serialized if necessary.
-        *
-        * @param string An identifier used for this cache entry
-        * @param mixed The variable to cache
-        * @param array Tags to associate with this cache entry
-        * @return void
-        * @author Robert Lemke <robert@typo3.org>
-        */
-       public function set($entryIdentifier, $variable, array $tags = array(), $lifetime = null) {
-               $this->backend->set($entryIdentifier, serialize($variable), $tags, $lifetime);
-       }
-
-       /**
-        * Loads a variable value from the cache.
-        *
-        * @param string Identifier of the cache entry to fetch
-        * @return mixed The value
-        * @author Robert Lemke <robert@typo3.org>
-        * @throws t3lib_cache_exception_ClassAlreadyLoaded if the class already exists
-        */
-       public function get($entryIdentifier) {
-               return unserialize($this->backend->get($entryIdentifier));
-       }
-
-       /**
-        * Checks if a cache entry with the specified identifier exists.
-        *
-        * @param string 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 $this->backend->has($entryIdentifier);
-       }
-
-       /**
-        * Removes the given cache entry from the cache.
-        *
-        * @param string An identifier specifying the cache entry
-        * @return boolean TRUE if such an entry exists, FALSE if not
-        * @author Sebastian Kurfuerst <sebastian@typo3.org>
-        */
-       public function remove($entryIdentifier) {
-               return $this->backend->remove($entryIdentifier);
-       }
-}
-
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_variablecache.php'])        {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_variablecache.php']);
-}
-
-?>
\ No newline at end of file
diff --git a/t3lib/cache/frontend/class.t3lib_cache_frontend_abstractfrontend.php b/t3lib/cache/frontend/class.t3lib_cache_frontend_abstractfrontend.php
new file mode 100644 (file)
index 0000000..cfd57d1
--- /dev/null
@@ -0,0 +1,218 @@
+<?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!
+***************************************************************/
+
+
+/**
+ * An abstract cache
+ *
+ * This file is a backport from FLOW3
+ *
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @version $Id$
+ */
+abstract class t3lib_cache_frontend_AbstractFrontend implements t3lib_cache_frontend_Frontend {
+
+       /**
+        * @var string Identifies this cache
+        */
+       protected $identifier;
+
+       /**
+        * @var t3lib_cache_backend_AbstractBackend
+        */
+       protected $backend;
+
+       /**
+        * Constructs the cache
+        *
+        * @param string A identifier which describes this cache
+        * @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
+        */
+       public function __construct($identifier, t3lib_cache_backend_Backend $backend) {
+               if (!preg_match(self::PATTERN_ENTRYIDENTIFIER, $identifier)) {
+                       throw new InvalidArgumentException('"' . $identifier . '" is not a valid cache identifier.', 1203584729);
+               }
+
+               $this->identifier = $identifier;
+               $this->backend    = $backend;
+               $this->backend->setCache($this);
+       }
+
+       /**
+        * Returns this cache's identifier
+        *
+        * @return string The identifier for this cache
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function getIdentifier() {
+               return $this->identifier;
+       }
+
+       /**
+        * Returns the backend used by this cache
+        *
+        * @return t3lib_cache_backend_Backend The backend used by this cache
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function getBackend() {
+               return $this->backend;
+       }
+
+       /**
+        * 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>
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function has($entryIdentifier) {
+               if (!$this->isValidEntryIdentifier($entryIdentifier)) {
+                       throw new InvalidArgumentException(
+                               '"' . $entryIdentifier . '" is not a valid cache entry identifier.',
+                               1233058486
+                       );
+               }
+
+               return $this->backend->has($entryIdentifier);
+       }
+
+       /**
+        * Removes the given cache entry from the cache.
+        *
+        * @param string $entryIdentifier An identifier specifying the cache entry
+        * @return boolean TRUE if such an entry exists, FALSE if not
+        * @author Sebastian Kurfuerst <sebastian@typo3.org>
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function remove($entryIdentifier) {
+               if (!$this->isValidEntryIdentifier($entryIdentifier)) {
+                       throw new InvalidArgumentException(
+                               '"' . $entryIdentifier . '" is not a valid cache entry identifier.',
+                               1233058495
+                       );
+               }
+
+               return $this->backend->remove($entryIdentifier);
+       }
+
+       /**
+        * Removes all cache entries of this cache.
+        *
+        * @return void
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function flush() {
+               $this->backend->flush();
+       }
+
+       /**
+        * 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>
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function flushByTag($tag) {
+               if (!$this->isValidTag($tag)) {
+                       throw new InvalidArgumentException(
+                               '"' . $tag . '" is not a valid tag for a cache entry.',
+                               1233057359
+                       );
+               }
+
+               $this->backend->flushByTag($tag);
+       }
+
+       /**
+        * Removes all cache entries of this cache which are tagged by the specified tag.
+        *
+        * @param       array   Array of tags to search for and to remove the cache entries, the "*" wildcard is supported
+        * @return void
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function flushByTags(array $tags) {
+               $this->backend->flushByTags($tags);
+       }
+
+       /**
+        * Does garbage collection
+        *
+        * @return void
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function collectGarbage() {
+               $this->backend->collectGarbage();
+       }
+
+       /**
+        * Renders a tag which can be used to mark a cache entry as "depends on this class".
+        * Whenever the specified class is modified, all cache entries tagged with the
+        * class are flushed.
+        *
+        * If an empty string is specified as class name, the returned tag means
+        * "depends on any class".
+        *
+        * @param string The class name
+        * @return string Class Tag
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function getClassTag($className = '') {
+               return ($className === '') ? self::TAG_CLASS : self::TAG_CLASS . str_replace('\\', '_', $className);
+       }
+
+       /**
+        * Checks the validity of an entry identifier. Returns true if it's valid.
+        *
+        * @param string An identifier to be checked for validity
+        * @return boolean
+        * @author Christian Jul Jensen <julle@typo3.org>
+        */
+       public function isValidEntryIdentifier($identifier) {
+               return preg_match(self::PATTERN_ENTRYIDENTIFIER, $identifier) === 1;
+       }
+
+       /**
+        * Checks the validity of a tag. Returns true if it's valid.
+        *
+        * @param string An identifier to be checked for validity
+        * @return boolean
+        * @author Robert Lemke <robert@typo3.org>
+        */
+       public function isValidTag($tag) {
+               return preg_match(self::PATTERN_TAG, $tag) === 1;
+       }
+
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/frontend/class.t3lib_cache_frontend_abstractfrontend.php'])   {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/frontend/class.t3lib_cache_frontend_abstractfrontend.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/cache/frontend/class.t3lib_cache_frontend_stringfrontend.php b/t3lib/cache/frontend/class.t3lib_cache_frontend_stringfrontend.php
new file mode 100644 (file)
index 0000000..9f3efa8
--- /dev/null
@@ -0,0 +1,124 @@
+<?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 cache frontend for strings. Nothing else.
+ *
+ * This file is a backport from FLOW3
+ *
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @version $Id$
+ */
+class t3lib_cache_frontend_StringFrontend extends t3lib_cache_frontend_AbstractFrontend {
+
+       /**
+        * Saves the value of a PHP variable in the cache. Note that the variable
+        * will be serialized if necessary.
+        *
+        * @param string An identifier used for this cache entry
+        * @param string The variable to cache
+        * @param array Tags to associate with this cache entry
+        * @return void
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function set($entryIdentifier, $string, $tags = array()) {
+               if (!$this->isValidEntryIdentifier($entryIdentifier)) {
+                       throw new InvalidArgumentException(
+                               '"' . $entryIdentifier . '" is not a valid cache entry identifier.',
+                               1233057566
+                       );
+               }
+
+               if (!is_string($string)) {
+                       throw new t3lib_cache_exception_InvalidData(
+                               'Only strings can be digested by the StringCache. Thanks.',
+                               1222808333
+                       );
+               }
+
+               foreach ($tags as $tag) {
+                       if (!$this->isValidTag($tag)) {
+                               throw new InvalidArgumentException(
+                                       '"' . $tag . '" is not a valid tag for a cache entry.',
+                                       1233057512
+                               );
+                       }
+               }
+
+               $this->backend->set($entryIdentifier, $string, $tags);
+       }
+
+       /**
+        * Loads a variable value from the cache.
+        *
+        * @param string Identifier of the cache entry to fetch
+        * @return string The value
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function get($entryIdentifier) {
+               if (!$this->isValidEntryIdentifier($entryIdentifier)) {
+                       throw new InvalidArgumentException(
+                               '"' . $entryIdentifier . '" is not a valid cache entry identifier.',
+                               1233057752
+                       );
+               }
+
+               return $this->backend->get($entryIdentifier);
+       }
+
+       /**
+        * Finds and returns all cache entries which are tagged by the specified tag.
+        *
+        * @param string $tag The tag to search for
+        * @return array An array with the content of all matching entries. An empty array if no entries matched
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function getByTag($tag) {
+               if (!$this->isValidTag($tag)) {
+                       throw new InvalidArgumentException(
+                               '"' . $tag . '" is not a valid tag for a cache entry.',
+                               1233057772
+                       );
+               }
+
+               $entries = array();
+               $identifiers = $this->backend->findIdentifiersByTag($tag);
+
+               foreach ($identifiers as $identifier) {
+                       $entries[] = $this->backend->get($identifier);
+               }
+
+               return $entries;
+       }
+
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_stringcache.php'])  {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_stringcache.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/cache/frontend/class.t3lib_cache_frontend_variablefrontend.php b/t3lib/cache/frontend/class.t3lib_cache_frontend_variablefrontend.php
new file mode 100644 (file)
index 0000000..3ad4865
--- /dev/null
@@ -0,0 +1,119 @@
+<?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 cache for any kinds of PHP variables
+ *
+ * This file is a backport from FLOW3
+ *
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ * @version $Id$
+ */
+class t3lib_cache_frontend_VariableFrontend extends t3lib_cache_frontend_AbstractFrontend {
+
+       /**
+        * Saves the value of a PHP variable in the cache. Note that the variable
+        * will be serialized if necessary.
+        *
+        * @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
+        * @return void
+        * @author Robert Lemke <robert@typo3.org>
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function set($entryIdentifier, $variable, $tags = array()) {
+               if (!$this->isValidEntryIdentifier($entryIdentifier)) {
+                       throw new InvalidArgumentException(
+                               '"' . $entryIdentifier . '" is not a valid cache entry identifier.',
+                               1233058264
+                       );
+               }
+
+               foreach ($tags as $tag) {
+                       if (!$this->isValidTag($tag)) {
+                               throw new InvalidArgumentException(
+                                       '"' . $tag . '" is not a valid tag for a cache entry.',
+                                       1233058269
+                               );
+                       }
+               }
+
+               $this->backend->set($entryIdentifier, serialize($variable), $tags);
+       }
+
+       /**
+        * Loads a variable value from the cache.
+        *
+        * @param string Identifier of the cache entry to fetch
+        * @return mixed The value
+        * @author Robert Lemke <robert@typo3.org>
+        * @throws t3lib_cache_exception_ClassAlreadyLoaded if the class already exists
+        */
+       public function get($entryIdentifier) {
+               if (!$this->isValidEntryIdentifier($entryIdentifier)) {
+                       throw new InvalidArgumentException(
+                               '"' . $entryIdentifier . '" is not a valid cache entry identifier.',
+                               1233058294
+                       );
+               }
+
+               return unserialize($this->backend->get($entryIdentifier));
+       }
+
+       /**
+        * Finds and returns all cache entries which are tagged by the specified tag.
+        *
+        * @param string $tag The tag to search for
+        * @return array An array with the content of all matching entries. An empty array if no entries matched
+        * @author Karsten Dambekalns <karsten@typo3.org>
+        */
+       public function getByTag($tag) {
+               if (!$this->isValidTag($tag)) {
+                       throw new InvalidArgumentException(
+                               '"' . $tag . '" is not a valid tag for a cache entry.',
+                               1233058312
+                       );
+               }
+
+               $entries = array();
+               $identifiers = $this->backend->findIdentifiersByTag($tag);
+
+               foreach ($identifiers as $identifier) {
+                       $entries[] = unserialize($this->backend->get($identifier));
+               }
+
+               return $entries;
+       }
+
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_variablecache.php'])        {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_variablecache.php']);
+}
+
+?>
\ No newline at end of file
diff --git a/t3lib/cache/frontend/interfaces/interface.t3lib_cache_frontend_frontend.php b/t3lib/cache/frontend/interfaces/interface.t3lib_cache_frontend_frontend.php
new file mode 100644 (file)
index 0000000..fae360a
--- /dev/null
@@ -0,0 +1,159 @@
+<?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.
+*  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!
+***************************************************************/
+
+
+/**
+ * interface for a Cache Frontend
+ *
+ * @author     Ingo Renner <ingo@typo3.org>
+ * @package TYPO3
+ * @subpackage t3lib_cache
+ */
+interface t3lib_cache_frontend_Frontend {
+
+       /**
+        * "Magic" tag for class-related entries
+        */
+       const TAG_CLASS = '%CLASS%';
+
+       /**
+        * Pattern an entry identifer must match.
+        */
+       const PATTERN_ENTRYIDENTIFIER = '/^[a-zA-Z0-9_%]{1,250}$/';
+
+       /**
+        * Pattern a tag must match.
+        */
+       const PATTERN_TAG = '/^[a-zA-Z0-9_%]{1,250}$/';
+
+       /**
+        * Returns this cache's identifier
+        *
+        * @return string The identifier for this cache
+        */
+       public function getIdentifier();
+
+       /**
+        * Returns the backend used by this cache
+        *
+        * @return t3lib_cache_backend_Backend The backend used by this cache
+        */
+       public function getBackend();
+
+       /**
+        * Saves data in the cache.
+        *
+        * @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
+        * @return      void
+        */
+       public function set($entryIdentifier, $data, $tags = array());
+
+       /**
+        * Finds and returns data from the cache.
+        *
+        * @param       string  Something which identifies the cache entry - depends on concrete cache
+        * @return      mixed
+        */
+       public function get($entryIdentifier);
+
+       /**
+        * Finds and returns all cache entries which are tagged by the specified tag.
+        *
+        * @param       string  The tag to search for
+        * @return      array   An array with the content of all matching entries. An empty array if no entries matched
+        */
+       public function getByTag($tag);
+
+       /**
+        * Checks if a cache entry with the specified identifier exists.
+        *
+        * @param       string  An identifier specifying the cache entry
+        * @return      boolean TRUE if such an entry exists, FALSE if not
+        */
+       public function has($entryIdentifier);
+
+       /**
+        * Removes the given cache entry from the cache.
+        *
+        * @param       string  An identifier specifying the cache entry
+        * @return      boolean TRUE if such an entry exists, FALSE if not
+        */
+       public function remove($entryIdentifier);
+
+       /**
+        * Removes all cache entries of this cache.
+        *
+        * @return      void
+        */
+       function flush();
+
+       /**
+        * Removes all cache entries of this cache which are tagged by the specified tag.
+        *
+        * @param       string  The tag the entries must have
+        * @return      void
+        */
+       public function flushByTag($tag);
+
+       /**
+        * Removes all cache entries of this cache which are tagged by the specified tag.
+        *
+        * @param       array   Array of tags to search for and to remove the cache entries, the "*" wildcard is supported
+        * @return      void
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function flushByTags(array $tags);
+
+       /**
+        * Does garbage collection
+        *
+        * @return      void
+        */
+       public function collectGarbage();
+
+       /**
+        * Checks the validity of an entry identifier. Returns true if it's valid.
+        *
+        * @param string An identifier to be checked for validity
+        * @return boolean
+        */
+       public function isValidEntryIdentifier($identifier);
+
+       /**
+        * Checks the validity of a tag. Returns true if it's valid.
+        *
+        * @param string A tag to be checked for validity
+        * @return boolean
+        */
+       public function isValidTag($tag);
+
+}
+
+
+?>
\ No newline at end of file
index 717fc6b..a6c8218 100644 (file)
@@ -43,9 +43,9 @@ class t3lib_cache {
                try {
                        $GLOBALS['typo3CacheFactory']->create(
                                'cache_pages',
-                               't3lib_cache_VariableCache',
-                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheBackendAssignments']['cache_pages']['backend'],
-                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheBackendAssignments']['cache_pages']['options']
+                               't3lib_cache_frontend_VariableFrontend',
+                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_pages']['backend'],
+                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_pages']['options']
                        );
                } catch(t3lib_cache_exception_DuplicateIdentifier $e) {
                                // do nothing, a cache_pages cache already exists
@@ -62,9 +62,9 @@ class t3lib_cache {
                try {
                        $GLOBALS['typo3CacheFactory']->create(
                                'cache_pagesection',
-                               't3lib_cache_VariableCache',
-                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheBackendAssignments']['cache_pagesection']['backend'],
-                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheBackendAssignments']['cache_pagesection']['options']
+                               't3lib_cache_frontend_VariableFrontend',
+                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_pagesection']['backend'],
+                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_pagesection']['options']
                        );
                } catch(t3lib_cache_exception_DuplicateIdentifier $e) {
                                // do nothing, a cache_pagesection cache already exists
@@ -81,9 +81,9 @@ class t3lib_cache {
                try {
                        $GLOBALS['typo3CacheFactory']->create(
                                'cache_hash',
-                               't3lib_cache_VariableCache',
-                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheBackendAssignments']['cache_hash']['backend'],
-                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheBackendAssignments']['cache_hash']['options']
+                               't3lib_cache_frontend_VariableFrontend',
+                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_hash']['backend'],
+                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_hash']['options']
                        );
                } catch(t3lib_cache_exception_DuplicateIdentifier $e) {
                                // do nothing, a cache_hash cache already exists
index e40979c..3fa2ba6 100755 (executable)
@@ -102,31 +102,35 @@ $TYPO3_CONF_VARS = Array(
                'reverseProxySSL' => '',                                // String: '*' or list of IP addresses of proxies that use SSL (https) for the connection to the client, but an unencrypted connection (http) to the server. If '*' all proxies defined in SYS[reverseProxyIP] use SSL.
                'reverseProxyPrefixSSL' => '',                          // String: prefix to be added to the internal URL (SCRIPT_NAME and REQUEST_URI) when accessing the server via an SSL proxy. This setting overrides SYS[reverseProxyPrefix].
                'caching' => array(
+                       'defaultFrontend' => 't3lib_cache_frontend_VariableFrontend',
+                       'defaultBackend'  => 't3lib_cache_backend_FileBackend',
                        'cacheFrontends' => array(
-                               't3lib_cache_VariableCache' => 't3lib/cache/class.t3lib_cache_variablecache.php:t3lib_cache_VariableCache'
+                               't3lib_cache_frontend_VariableFrontend' => 't3lib/cache/frontend/class.t3lib_cache_frontend_variablefrontend.php:t3lib_cache_frontend_VariableFrontend',
+                               't3lib_cache_frontend_StringFrontend'   => 't3lib/cache/frontend/class.t3lib_cache_frontend_stringfrontend.php:t3lib_cache_frontend_StringFrontend'
                        ),
                        'cacheBackends' => array(
-                               't3lib_cache_backend_Db'        => 't3lib/cache/backend/class.t3lib_cache_backend_db.php:t3lib_cache_backend_Db',
-                               't3lib_cache_backend_File'      => 't3lib/cache/backend/class.t3lib_cache_backend_file.php:t3lib_cache_backend_File',
-                               't3lib_cache_backend_Globals'   => 't3lib/cache/backend/class.t3lib_cache_backend_globals.php:t3lib_cache_backend_Globals',
-                               't3lib_cache_backend_Memcached' => 't3lib/cache/backend/class.t3lib_cache_backend_memcached.php:t3lib_cache_backend_Memcached',
-                               't3lib_cache_backend_Null'      => 't3lib/cache/backend/class.t3lib_cache_backend_null.php:t3lib_cache_backend_Null'
+                               't3lib_cache_backend_DbBackend'        => 't3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php:t3lib_cache_backend_DbBackend',
+                               't3lib_cache_backend_FileBackend'      => 't3lib/cache/backend/class.t3lib_cache_backend_filebackend.php:t3lib_cache_backend_FileBackend',
+                               't3lib_cache_backend_GlobalsBackend'   => 't3lib/cache/backend/class.t3lib_cache_backend_globalsbackend.php:t3lib_cache_backend_GlobalsBackend',
+                               't3lib_cache_backend_MemcachedBackend' => 't3lib/cache/backend/class.t3lib_cache_backend_memcachedbackend.php:t3lib_cache_backend_MemcachedBackend',
+                               't3lib_cache_backend_ApcBackend'       => 't3lib/cache/backend/class.t3lib_cache_backend_apcbackend.php:t3lib_cache_backend_ApcBackend',
+                               't3lib_cache_backend_NullBackend'      => 't3lib/cache/backend/class.t3lib_cache_backend_nullbackend.php:t3lib_cache_backend_NullBackend'
                        ),
-                       'cacheBackendAssignments' => array(
+                       'cacheConfigurations' => array(
                                'cache_hash' => array(
-                                       'backend' => 't3lib_cache_backend_Db',
+                                       'backend' => 't3lib_cache_backend_DbBackend',
                                        'options' => array(
                                                'cacheTable' => 'cache_hash'
                                        )
                                ),
                                'cache_pages' => array(
-                                       'backend' => 't3lib_cache_backend_Db',
+                                       'backend' => 't3lib_cache_backend_DbBackend',
                                        'options' => array(
                                                'cacheTable' => 'cache_pages'
                                        )
                                ),
                                'cache_pagesection' => array(
-                                       'backend' => 't3lib_cache_backend_Db',
+                                       'backend' => 't3lib_cache_backend_DbBackend',
                                        'options' => array(
                                                'cacheTable' => 'cache_pagesection'
                                        )
@@ -135,7 +139,7 @@ $TYPO3_CONF_VARS = Array(
                                 For memcached, use:
                                =============
                                'cache_pages' => array(
-                                       'backend' => 't3lib_cache_backend_Memcached',
+                                       'backend' => 't3lib_cache_backend_MemcachedBackend',
                                        'options' => array(
                                                'servers' => array('localhost:11211', 'otherhost:11211', 'thirdhost:11211'),    // port is mandatory!
                                        )
index ceeb4a0..54bf50d 100755 (executable)
@@ -124,7 +124,7 @@ CREATE TABLE cache_extensions (
 #
 CREATE TABLE cache_hash (
   id int(11) unsigned NOT NULL auto_increment,
-  identifier varchar(32) DEFAULT '' NOT NULL,
+  identifier varchar(250) DEFAULT '' NOT NULL,
   crdate int(11) unsigned DEFAULT '0' NOT NULL,
   content mediumtext,
   tags mediumtext,
index 25a9fbb..919e338 100755 (executable)
@@ -183,12 +183,15 @@ $PARSETIME_START = t3lib_div::milliseconds();             // Is set to the system time in m
        // 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/class.t3lib_cache_abstractbackend.php');
-require_once(PATH_t3lib . 'cache/class.t3lib_cache_abstractcache.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/class.t3lib_cache_variablecache.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');
@@ -198,7 +201,8 @@ require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_invalidda
 require_once(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_nosuchcache.php');
 
 $typo3CacheManager = t3lib_div::makeInstance('t3lib_cache_Manager');
-$typo3CacheFactory = t3lib_div::makeInstance('t3lib_cache_Factory', $typo3CacheManager);
+$typo3CacheFactory = t3lib_div::makeInstance('t3lib_cache_Factory');
+$typo3CacheFactory->setCacheManager($typo3CacheManager);
 
 t3lib_cache::initPageCache();
 t3lib_cache::initPageSectionCache();
@@ -263,9 +267,9 @@ if (!(defined('TYPO3_cliMode') && TYPO3_cliMode) && @is_file(PATH_typo3conf.'LOC
                } else {
                        die('Browser backend is locked for maintenance. Remove lock by removing the file "typo3conf/LOCK_BACKEND" or use CLI-scripts.'.chr(10).chr(10));
                }
-               exit;  
+               exit;
        }
-       
+
 }
 
 // **********************
index 2c763cb..6384425 100755 (executable)
@@ -8,7 +8,7 @@
 #
 CREATE TABLE cache_pages (
   id int(11) unsigned NOT NULL auto_increment,
-  identifier varchar(32) DEFAULT '' NOT NULL,
+  identifier varchar(250) DEFAULT '' NOT NULL,
   crdate int(11) unsigned DEFAULT '0' NOT NULL,
   content mediumtext,
   tags mediumtext,
@@ -23,7 +23,7 @@ CREATE TABLE cache_pages (
 #
 CREATE TABLE cache_pagesection (
   id int(11) unsigned NOT NULL auto_increment,
-  identifier varchar(32) DEFAULT '' NOT NULL,
+  identifier varchar(250) DEFAULT '' NOT NULL,
   crdate int(11) unsigned DEFAULT '0' NOT NULL,
   content mediumtext,
   tags mediumtext,
index a1e2045..300a35b 100755 (executable)
@@ -601,12 +601,15 @@ require_once (PATH_t3lib.'class.t3lib_lock.php');
 
                t3lib_div::requireOnce(PATH_t3lib . 'class.t3lib_cache.php');
 
-               t3lib_div::requireOnce(PATH_t3lib . 'cache/class.t3lib_cache_abstractbackend.php');
-               t3lib_div::requireOnce(PATH_t3lib . 'cache/class.t3lib_cache_abstractcache.php');
+               t3lib_div::requireOnce(PATH_t3lib . 'cache/backend/interfaces/interface.t3lib_cache_backend_backend.php');
+               t3lib_div::requireOnce(PATH_t3lib . 'cache/frontend/interfaces/interface.t3lib_cache_frontend_frontend.php');
+
+               t3lib_div::requireOnce(PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_abstractbackend.php');
+               t3lib_div::requireOnce(PATH_t3lib . 'cache/frontend/class.t3lib_cache_frontend_abstractfrontend.php');
                t3lib_div::requireOnce(PATH_t3lib . 'cache/class.t3lib_cache_exception.php');
                t3lib_div::requireOnce(PATH_t3lib . 'cache/class.t3lib_cache_factory.php');
                t3lib_div::requireOnce(PATH_t3lib . 'cache/class.t3lib_cache_manager.php');
-               t3lib_div::requireOnce(PATH_t3lib . 'cache/class.t3lib_cache_variablecache.php');
+               t3lib_div::requireOnce(PATH_t3lib . 'cache/frontend/class.t3lib_cache_frontend_variablefrontend.php');
 
                t3lib_div::requireOnce(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_classalreadyloaded.php');
                t3lib_div::requireOnce(PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_duplicateidentifier.php');
@@ -629,7 +632,8 @@ require_once (PATH_t3lib.'class.t3lib_lock.php');
                $GLOBALS['TT']->push('Initializing the Caching System','');
 
                $GLOBALS['typo3CacheManager'] = t3lib_div::makeInstance('t3lib_cache_Manager');
-               $GLOBALS['typo3CacheFactory'] = t3lib_div::makeInstance('t3lib_cache_Factory', $GLOBALS['typo3CacheManager']);
+               $GLOBALS['typo3CacheFactory'] = t3lib_div::makeInstance('t3lib_cache_Factory');
+               $GLOBALS['typo3CacheFactory']->setCacheManager($GLOBALS['typo3CacheManager']);
 
                try {
                        $this->pageCache = $GLOBALS['typo3CacheManager']->getCache(