1<?php 2/* 3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 * 15 * This software consists of voluntary contributions made by many individuals 16 * and is licensed under the MIT license. For more information, see 17 * <http://www.doctrine-project.org>. 18 */ 19 20namespace Doctrine\Common\Cache; 21 22/** 23 * Base class for cache provider implementations. 24 * 25 * @since 2.2 26 * @author Benjamin Eberlei <kontakt@beberlei.de> 27 * @author Guilherme Blanco <guilhermeblanco@hotmail.com> 28 * @author Jonathan Wage <jonwage@gmail.com> 29 * @author Roman Borschel <roman@code-factory.org> 30 * @author Fabio B. Silva <fabio.bat.silva@gmail.com> 31 */ 32abstract class CacheProvider implements Cache, FlushableCache, ClearableCache, MultiGetCache, MultiPutCache 33{ 34 const DOCTRINE_NAMESPACE_CACHEKEY = 'DoctrineNamespaceCacheKey[%s]'; 35 36 /** 37 * The namespace to prefix all cache ids with. 38 * 39 * @var string 40 */ 41 private $namespace = ''; 42 43 /** 44 * The namespace version. 45 * 46 * @var integer|null 47 */ 48 private $namespaceVersion; 49 50 /** 51 * Sets the namespace to prefix all cache ids with. 52 * 53 * @param string $namespace 54 * 55 * @return void 56 */ 57 public function setNamespace($namespace) 58 { 59 $this->namespace = (string) $namespace; 60 $this->namespaceVersion = null; 61 } 62 63 /** 64 * Retrieves the namespace that prefixes all cache ids. 65 * 66 * @return string 67 */ 68 public function getNamespace() 69 { 70 return $this->namespace; 71 } 72 73 /** 74 * {@inheritdoc} 75 */ 76 public function fetch($id) 77 { 78 return $this->doFetch($this->getNamespacedId($id)); 79 } 80 81 /** 82 * {@inheritdoc} 83 */ 84 public function fetchMultiple(array $keys) 85 { 86 if (empty($keys)) { 87 return array(); 88 } 89 90 // note: the array_combine() is in place to keep an association between our $keys and the $namespacedKeys 91 $namespacedKeys = array_combine($keys, array_map(array($this, 'getNamespacedId'), $keys)); 92 $items = $this->doFetchMultiple($namespacedKeys); 93 $foundItems = array(); 94 95 // no internal array function supports this sort of mapping: needs to be iterative 96 // this filters and combines keys in one pass 97 foreach ($namespacedKeys as $requestedKey => $namespacedKey) { 98 if (isset($items[$namespacedKey]) || array_key_exists($namespacedKey, $items)) { 99 $foundItems[$requestedKey] = $items[$namespacedKey]; 100 } 101 } 102 103 return $foundItems; 104 } 105 106 /** 107 * {@inheritdoc} 108 */ 109 public function saveMultiple(array $keysAndValues, $lifetime = 0) 110 { 111 $namespacedKeysAndValues = array(); 112 foreach ($keysAndValues as $key => $value) { 113 $namespacedKeysAndValues[$this->getNamespacedId($key)] = $value; 114 } 115 116 return $this->doSaveMultiple($namespacedKeysAndValues, $lifetime); 117 } 118 119 /** 120 * {@inheritdoc} 121 */ 122 public function contains($id) 123 { 124 return $this->doContains($this->getNamespacedId($id)); 125 } 126 127 /** 128 * {@inheritdoc} 129 */ 130 public function save($id, $data, $lifeTime = 0) 131 { 132 return $this->doSave($this->getNamespacedId($id), $data, $lifeTime); 133 } 134 135 /** 136 * {@inheritdoc} 137 */ 138 public function delete($id) 139 { 140 return $this->doDelete($this->getNamespacedId($id)); 141 } 142 143 /** 144 * {@inheritdoc} 145 */ 146 public function getStats() 147 { 148 return $this->doGetStats(); 149 } 150 151 /** 152 * {@inheritDoc} 153 */ 154 public function flushAll() 155 { 156 return $this->doFlush(); 157 } 158 159 /** 160 * {@inheritDoc} 161 */ 162 public function deleteAll() 163 { 164 $namespaceCacheKey = $this->getNamespaceCacheKey(); 165 $namespaceVersion = $this->getNamespaceVersion() + 1; 166 167 if ($this->doSave($namespaceCacheKey, $namespaceVersion)) { 168 $this->namespaceVersion = $namespaceVersion; 169 170 return true; 171 } 172 173 return false; 174 } 175 176 /** 177 * Prefixes the passed id with the configured namespace value. 178 * 179 * @param string $id The id to namespace. 180 * 181 * @return string The namespaced id. 182 */ 183 private function getNamespacedId($id) 184 { 185 $namespaceVersion = $this->getNamespaceVersion(); 186 187 return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion); 188 } 189 190 /** 191 * Returns the namespace cache key. 192 * 193 * @return string 194 */ 195 private function getNamespaceCacheKey() 196 { 197 return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace); 198 } 199 200 /** 201 * Returns the namespace version. 202 * 203 * @return integer 204 */ 205 private function getNamespaceVersion() 206 { 207 if (null !== $this->namespaceVersion) { 208 return $this->namespaceVersion; 209 } 210 211 $namespaceCacheKey = $this->getNamespaceCacheKey(); 212 $this->namespaceVersion = $this->doFetch($namespaceCacheKey) ?: 1; 213 214 return $this->namespaceVersion; 215 } 216 217 /** 218 * Default implementation of doFetchMultiple. Each driver that supports multi-get should owerwrite it. 219 * 220 * @param array $keys Array of keys to retrieve from cache 221 * @return array Array of values retrieved for the given keys. 222 */ 223 protected function doFetchMultiple(array $keys) 224 { 225 $returnValues = array(); 226 227 foreach ($keys as $key) { 228 if (false !== ($item = $this->doFetch($key)) || $this->doContains($key)) { 229 $returnValues[$key] = $item; 230 } 231 } 232 233 return $returnValues; 234 } 235 236 /** 237 * Fetches an entry from the cache. 238 * 239 * @param string $id The id of the cache entry to fetch. 240 * 241 * @return mixed|false The cached data or FALSE, if no cache entry exists for the given id. 242 */ 243 abstract protected function doFetch($id); 244 245 /** 246 * Tests if an entry exists in the cache. 247 * 248 * @param string $id The cache id of the entry to check for. 249 * 250 * @return bool TRUE if a cache entry exists for the given cache id, FALSE otherwise. 251 */ 252 abstract protected function doContains($id); 253 254 /** 255 * Default implementation of doSaveMultiple. Each driver that supports multi-put should override it. 256 * 257 * @param array $keysAndValues Array of keys and values to save in cache 258 * @param int $lifetime The lifetime. If != 0, sets a specific lifetime for these 259 * cache entries (0 => infinite lifeTime). 260 * 261 * @return bool TRUE if the operation was successful, FALSE if it wasn't. 262 */ 263 protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) 264 { 265 $success = true; 266 267 foreach ($keysAndValues as $key => $value) { 268 if (!$this->doSave($key, $value, $lifetime)) { 269 $success = false; 270 } 271 } 272 273 return $success; 274 } 275 276 /** 277 * Puts data into the cache. 278 * 279 * @param string $id The cache id. 280 * @param string $data The cache entry/data. 281 * @param int $lifeTime The lifetime. If != 0, sets a specific lifetime for this 282 * cache entry (0 => infinite lifeTime). 283 * 284 * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise. 285 */ 286 abstract protected function doSave($id, $data, $lifeTime = 0); 287 288 /** 289 * Deletes a cache entry. 290 * 291 * @param string $id The cache id. 292 * 293 * @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise. 294 */ 295 abstract protected function doDelete($id); 296 297 /** 298 * Flushes all cache entries. 299 * 300 * @return bool TRUE if the cache entries were successfully flushed, FALSE otherwise. 301 */ 302 abstract protected function doFlush(); 303 304 /** 305 * Retrieves cached information from the data store. 306 * 307 * @since 2.2 308 * 309 * @return array|null An associative array with server's statistics if available, NULL otherwise. 310 */ 311 abstract protected function doGetStats(); 312} 313