.coveralls.yml000064400000000140144760114440007337 0ustar00# for php-coveralls service_name: travis-ci src_dir: lib coverage_clover: build/logs/clover.xml .gitignore000064400000000050144760114440006534 0ustar00vendor/ build/ phpunit.xml composer.lock.travis.yml000064400000001460144760114440006663 0ustar00language: php php: - 5.3 - 5.4 - 5.5 - 5.6 - hhvm services: - riak - mongodb - memcached - redis-server before_install: - sh -c "if [ $TRAVIS_PHP_VERSION != 'hhvm' ]; then pecl install riak-beta; fi" - sh -c "if [[ $TRAVIS_PHP_VERSION != 'hhvm' && `php-config --vernum` -ge 50500 ]] ; then pecl config-set preferred_state beta; printf "yes\n" | pecl install apcu ; else echo 'extension="apc.so"' >> ./tests/travis/php.ini ;fi" - composer self-update - sh -c "if [ $TRAVIS_PHP_VERSION != 'hhvm' ]; then phpenv config-add ./tests/travis/php.ini; fi" install: - composer --prefer-source --dev install script: - ./vendor/bin/phpunit -c ./tests/travis/phpunit.travis.xml -v after_script: - php vendor/bin/coveralls -v matrix: allow_failures: - php: hhvm LICENSE000064400000002051144760114440005554 0ustar00Copyright (c) 2006-2012 Doctrine Project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. README.md000064400000001267144760114440006036 0ustar00# Doctrine Cache Master: [![Build Status](https://secure.travis-ci.org/doctrine/cache.png?branch=master)](http://travis-ci.org/doctrine/cache) [![Coverage Status](https://coveralls.io/repos/doctrine/cache/badge.png?branch=master)](https://coveralls.io/r/doctrine/cache?branch=master) [![Latest Stable Version](https://poser.pugx.org/doctrine/cache/v/stable.png)](https://packagist.org/packages/doctrine/cache) [![Total Downloads](https://poser.pugx.org/doctrine/cache/downloads.png)](https://packagist.org/packages/doctrine/cache) Cache component extracted from the Doctrine Common project. ## Changelog ### v1.2 * Added support for MongoDB as Cache Provider * Fix namespace version reset UPGRADE.md000064400000001326144760114440006164 0ustar00# Upgrade to 1.4 ## Minor BC Break: `Doctrine\Common\Cache\FileCache#$extension` is now `private`. If you need to override the value of `Doctrine\Common\Cache\FileCache#$extension`, then use the second parameter of `Doctrine\Common\Cache\FileCache#__construct()` instead of overriding the property in your own implementation. ## Minor BC Break: file based caches paths changed `Doctrine\Common\Cache\FileCache`, `Doctrine\Common\Cache\PhpFileCache` and `Doctrine\Common\Cache\FilesystemCache` are using a different cache paths structure. If you rely on warmed up caches for deployments, consider that caches generated with `doctrine/cache` `<1.4` are not compatible with the new directory structure, and will be ignored. build.properties000064400000000217144760114440007766 0ustar00# Version class and file project.version_class = Doctrine\\Common\\Cache\\Version project.version_file = lib/Doctrine/Common/Cache/Version.php build.xml000064400000010044144760114440006371 0ustar00 composer.json000064400000002075144760114440007277 0ustar00{ "name": "doctrine/cache", "type": "library", "description": "Caching library offering an object-oriented API for many cache backends", "keywords": ["cache", "caching"], "homepage": "http://www.doctrine-project.org", "license": "MIT", "authors": [ {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, {"name": "Roman Borschel", "email": "roman@code-factory.org"}, {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} ], "require": { "php": ">=5.3.2" }, "require-dev": { "phpunit/phpunit": ">=3.7", "satooshi/php-coveralls": "~0.6", "predis/predis": "~1.0" }, "conflict": { "doctrine/common": ">2.2,<2.4" }, "autoload": { "psr-0": { "Doctrine\\Common\\Cache\\": "lib/" } }, "extra": { "branch-alias": { "dev-master": "1.5.x-dev" } } } lib/Doctrine/Common/Cache/ApcCache.php000064400000006125144760114440013465 0ustar00. */ namespace Doctrine\Common\Cache; /** * APC cache provider. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author David Abdemoulaie */ class ApcCache extends CacheProvider { /** * {@inheritdoc} */ protected function doFetch($id) { return apc_fetch($id); } /** * {@inheritdoc} */ protected function doContains($id) { return apc_exists($id); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { return (bool) apc_store($id, $data, (int) $lifeTime); } /** * {@inheritdoc} */ protected function doDelete($id) { return apc_delete($id); } /** * {@inheritdoc} */ protected function doFlush() { return apc_clear_cache() && apc_clear_cache('user'); } /** * {@inheritdoc} */ protected function doFetchMultiple(array $keys) { return apc_fetch($keys); } /** * {@inheritdoc} */ protected function doGetStats() { $info = apc_cache_info('', true); $sma = apc_sma_info(); // @TODO - Temporary fix @see https://github.com/krakjoe/apcu/pull/42 if (PHP_VERSION_ID >= 50500) { $info['num_hits'] = isset($info['num_hits']) ? $info['num_hits'] : $info['nhits']; $info['num_misses'] = isset($info['num_misses']) ? $info['num_misses'] : $info['nmisses']; $info['start_time'] = isset($info['start_time']) ? $info['start_time'] : $info['stime']; } return array( Cache::STATS_HITS => $info['num_hits'], Cache::STATS_MISSES => $info['num_misses'], Cache::STATS_UPTIME => $info['start_time'], Cache::STATS_MEMORY_USAGE => $info['mem_size'], Cache::STATS_MEMORY_AVAILABLE => $sma['avail_mem'], ); } } lib/Doctrine/Common/Cache/ArrayCache.php000064400000004633144760114440014042 0ustar00. */ namespace Doctrine\Common\Cache; /** * Array cache driver. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author David Abdemoulaie */ class ArrayCache extends CacheProvider { /** * @var array $data */ private $data = array(); /** * {@inheritdoc} */ protected function doFetch($id) { return $this->doContains($id) ? $this->data[$id] : false; } /** * {@inheritdoc} */ protected function doContains($id) { // isset() is required for performance optimizations, to avoid unnecessary function calls to array_key_exists. return isset($this->data[$id]) || array_key_exists($id, $this->data); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { $this->data[$id] = $data; return true; } /** * {@inheritdoc} */ protected function doDelete($id) { unset($this->data[$id]); return true; } /** * {@inheritdoc} */ protected function doFlush() { $this->data = array(); return true; } /** * {@inheritdoc} */ protected function doGetStats() { return null; } } lib/Doctrine/Common/Cache/Cache.php000064400000007344144760114440013045 0ustar00. */ namespace Doctrine\Common\Cache; /** * Interface for cache drivers. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Fabio B. Silva * @author Kévin Dunglas */ interface Cache { const STATS_HITS = 'hits'; const STATS_MISSES = 'misses'; const STATS_UPTIME = 'uptime'; const STATS_MEMORY_USAGE = 'memory_usage'; const STATS_MEMORY_AVAILABLE = 'memory_available'; /** * Only for backward compatibility (may be removed in next major release) * * @deprecated */ const STATS_MEMORY_AVAILIABLE = 'memory_available'; /** * Fetches an entry from the cache. * * @param string $id The id of the cache entry to fetch. * * @return mixed The cached data or FALSE, if no cache entry exists for the given id. */ public function fetch($id); /** * Tests if an entry exists in the cache. * * @param string $id The cache id of the entry to check for. * * @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise. */ public function contains($id); /** * Puts data into the cache. * * @param string $id The cache id. * @param mixed $data The cache entry/data. * @param int $lifeTime The cache lifetime. * If != 0, sets a specific lifetime for this cache entry (0 => infinite lifeTime). * * @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise. */ public function save($id, $data, $lifeTime = 0); /** * Deletes a cache entry. * * @param string $id The cache id. * * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. */ public function delete($id); /** * Retrieves cached information from the data store. * * The server's statistics array has the following values: * * - hits * Number of keys that have been requested and found present. * * - misses * Number of items that have been requested and not found. * * - uptime * Time that the server is running. * * - memory_usage * Memory used by this server to store items. * * - memory_available * Memory allowed to use for storage. * * @since 2.2 * * @return array|null An associative array with server's statistics if available, NULL otherwise. */ public function getStats(); } lib/Doctrine/Common/Cache/CacheProvider.php000064400000017043144760114440014555 0ustar00. */ namespace Doctrine\Common\Cache; /** * Base class for cache provider implementations. * * @since 2.2 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Fabio B. Silva */ abstract class CacheProvider implements Cache, FlushableCache, ClearableCache, MultiGetCache { const DOCTRINE_NAMESPACE_CACHEKEY = 'DoctrineNamespaceCacheKey[%s]'; /** * The namespace to prefix all cache ids with. * * @var string */ private $namespace = ''; /** * The namespace version. * * @var integer|null */ private $namespaceVersion; /** * Sets the namespace to prefix all cache ids with. * * @param string $namespace * * @return void */ public function setNamespace($namespace) { $this->namespace = (string) $namespace; $this->namespaceVersion = null; } /** * Retrieves the namespace that prefixes all cache ids. * * @return string */ public function getNamespace() { return $this->namespace; } /** * {@inheritdoc} */ public function fetch($id) { return $this->doFetch($this->getNamespacedId($id)); } /** * {@inheritdoc} */ public function fetchMultiple(array $keys) { // note: the array_combine() is in place to keep an association between our $keys and the $namespacedKeys $namespacedKeys = array_combine($keys, array_map(array($this, 'getNamespacedId'), $keys)); $items = $this->doFetchMultiple($namespacedKeys); $foundItems = array(); // no internal array function supports this sort of mapping: needs to be iterative // this filters and combines keys in one pass foreach ($namespacedKeys as $requestedKey => $namespacedKey) { if (isset($items[$namespacedKey])) { $foundItems[$requestedKey] = $items[$namespacedKey]; } } return $foundItems; } /** * {@inheritdoc} */ public function contains($id) { return $this->doContains($this->getNamespacedId($id)); } /** * {@inheritdoc} */ public function save($id, $data, $lifeTime = 0) { return $this->doSave($this->getNamespacedId($id), $data, $lifeTime); } /** * {@inheritdoc} */ public function delete($id) { return $this->doDelete($this->getNamespacedId($id)); } /** * {@inheritdoc} */ public function getStats() { return $this->doGetStats(); } /** * {@inheritDoc} */ public function flushAll() { return $this->doFlush(); } /** * {@inheritDoc} */ public function deleteAll() { $namespaceCacheKey = $this->getNamespaceCacheKey(); $namespaceVersion = $this->getNamespaceVersion() + 1; $this->namespaceVersion = $namespaceVersion; return $this->doSave($namespaceCacheKey, $namespaceVersion); } /** * Prefixes the passed id with the configured namespace value. * * @param string $id The id to namespace. * * @return string The namespaced id. */ private function getNamespacedId($id) { $namespaceVersion = $this->getNamespaceVersion(); return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion); } /** * Returns the namespace cache key. * * @return string */ private function getNamespaceCacheKey() { return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace); } /** * Returns the namespace version. * * @return integer */ private function getNamespaceVersion() { if (null !== $this->namespaceVersion) { return $this->namespaceVersion; } $namespaceCacheKey = $this->getNamespaceCacheKey(); $namespaceVersion = $this->doFetch($namespaceCacheKey); if (false === $namespaceVersion) { $namespaceVersion = 1; $this->doSave($namespaceCacheKey, $namespaceVersion); } $this->namespaceVersion = $namespaceVersion; return $this->namespaceVersion; } /** * Default implementation of doFetchMultiple. Each driver that supports multi-get should owerwrite it. * * @param array $keys Array of keys to retrieve from cache * @return array Array of values retrieved for the given keys. */ protected function doFetchMultiple(array $keys) { $returnValues = array(); foreach ($keys as $index => $key) { if (false !== ($item = $this->doFetch($key))) { $returnValues[$key] = $item; } } return $returnValues; } /** * Fetches an entry from the cache. * * @param string $id The id of the cache entry to fetch. * * @return mixed|boolean The cached data or FALSE, if no cache entry exists for the given id. */ abstract protected function doFetch($id); /** * Tests if an entry exists in the cache. * * @param string $id The cache id of the entry to check for. * * @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise. */ abstract protected function doContains($id); /** * Puts data into the cache. * * @param string $id The cache id. * @param string $data The cache entry/data. * @param int $lifeTime The lifetime. If != 0, sets a specific lifetime for this * cache entry (0 => infinite lifeTime). * * @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise. */ abstract protected function doSave($id, $data, $lifeTime = 0); /** * Deletes a cache entry. * * @param string $id The cache id. * * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. */ abstract protected function doDelete($id); /** * Flushes all cache entries. * * @return boolean TRUE if the cache entries were successfully flushed, FALSE otherwise. */ abstract protected function doFlush(); /** * Retrieves cached information from the data store. * * @since 2.2 * * @return array|null An associative array with server's statistics if available, NULL otherwise. */ abstract protected function doGetStats(); } lib/Doctrine/Common/Cache/ChainCache.php000064400000007312144760114440014003 0ustar00. */ namespace Doctrine\Common\Cache; /** * Cache provider that allows to easily chain multiple cache providers * * @author Michaël Gallego */ class ChainCache extends CacheProvider { /** * @var CacheProvider[] */ private $cacheProviders = array(); /** * Constructor * * @param CacheProvider[] $cacheProviders */ public function __construct($cacheProviders = array()) { $this->cacheProviders = $cacheProviders; } /** * {@inheritDoc} */ public function setNamespace($namespace) { parent::setNamespace($namespace); foreach ($this->cacheProviders as $cacheProvider) { $cacheProvider->setNamespace($namespace); } } /** * {@inheritDoc} */ protected function doFetch($id) { foreach ($this->cacheProviders as $key => $cacheProvider) { if ($cacheProvider->doContains($id)) { $value = $cacheProvider->doFetch($id); // We populate all the previous cache layers (that are assumed to be faster) for ($subKey = $key - 1 ; $subKey >= 0 ; $subKey--) { $this->cacheProviders[$subKey]->doSave($id, $value); } return $value; } } return false; } /** * {@inheritDoc} */ protected function doContains($id) { foreach ($this->cacheProviders as $cacheProvider) { if ($cacheProvider->doContains($id)) { return true; } } return false; } /** * {@inheritDoc} */ protected function doSave($id, $data, $lifeTime = 0) { $stored = true; foreach ($this->cacheProviders as $cacheProvider) { $stored = $cacheProvider->doSave($id, $data, $lifeTime) && $stored; } return $stored; } /** * {@inheritDoc} */ protected function doDelete($id) { $deleted = true; foreach ($this->cacheProviders as $cacheProvider) { $deleted = $cacheProvider->doDelete($id) && $deleted; } return $deleted; } /** * {@inheritDoc} */ protected function doFlush() { $flushed = true; foreach ($this->cacheProviders as $cacheProvider) { $flushed = $cacheProvider->doFlush() && $flushed; } return $flushed; } /** * {@inheritDoc} */ protected function doGetStats() { // We return all the stats from all adapters $stats = array(); foreach ($this->cacheProviders as $cacheProvider) { $stats[] = $cacheProvider->doGetStats(); } return $stats; } } lib/Doctrine/Common/Cache/ClearableCache.php000064400000003006144760114440014627 0ustar00. */ namespace Doctrine\Common\Cache; /** * Interface for cache that can be flushed. * * Intended to be used for partial clearing of a cache namespace. For a more * global "flushing", see {@see FlushableCache}. * * @link www.doctrine-project.org * @since 1.4 * @author Adirelle */ interface ClearableCache { /** * Deletes all cache entries in the current cache namespace. * * @return boolean TRUE if the cache entries were successfully deleted, FALSE otherwise. */ public function deleteAll(); } lib/Doctrine/Common/Cache/CouchbaseCache.php000064400000006150144760114440014654 0ustar00. */ namespace Doctrine\Common\Cache; use \Couchbase; /** * Couchbase cache provider. * * @link www.doctrine-project.org * @since 2.4 * @author Michael Nitschinger */ class CouchbaseCache extends CacheProvider { /** * @var Couchbase|null */ private $couchbase; /** * Sets the Couchbase instance to use. * * @param Couchbase $couchbase * * @return void */ public function setCouchbase(Couchbase $couchbase) { $this->couchbase = $couchbase; } /** * Gets the Couchbase instance used by the cache. * * @return Couchbase|null */ public function getCouchbase() { return $this->couchbase; } /** * {@inheritdoc} */ protected function doFetch($id) { return $this->couchbase->get($id) ?: false; } /** * {@inheritdoc} */ protected function doContains($id) { return (null !== $this->couchbase->get($id)); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { if ($lifeTime > 30 * 24 * 3600) { $lifeTime = time() + $lifeTime; } return $this->couchbase->set($id, $data, (int) $lifeTime); } /** * {@inheritdoc} */ protected function doDelete($id) { return $this->couchbase->delete($id); } /** * {@inheritdoc} */ protected function doFlush() { return $this->couchbase->flush(); } /** * {@inheritdoc} */ protected function doGetStats() { $stats = $this->couchbase->getStats(); $servers = $this->couchbase->getServers(); $server = explode(":", $servers[0]); $key = $server[0] . ":" . "11210"; $stats = $stats[$key]; return array( Cache::STATS_HITS => $stats['get_hits'], Cache::STATS_MISSES => $stats['get_misses'], Cache::STATS_UPTIME => $stats['uptime'], Cache::STATS_MEMORY_USAGE => $stats['bytes'], Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], ); } } lib/Doctrine/Common/Cache/FileCache.php000064400000014505144760114440013642 0ustar00. */ namespace Doctrine\Common\Cache; /** * Base file cache driver. * * @since 2.3 * @author Fabio B. Silva */ abstract class FileCache extends CacheProvider { /** * The cache directory. * * @var string */ protected $directory; /** * The cache file extension. * * @var string */ private $extension; /** * @var string[] regular expressions for replacing disallowed characters in file name */ private $disallowedCharacterPatterns = array( '/\-/', // replaced to disambiguate original `-` and `-` derived from replacements '/[^a-zA-Z0-9\-_\[\]]/' // also excludes non-ascii chars (not supported, depending on FS) ); /** * @var string[] replacements for disallowed file characters */ private $replacementCharacters = array('__', '-'); /** * @var int */ private $umask; /** * Constructor. * * @param string $directory The cache directory. * @param string $extension The cache file extension. * * @throws \InvalidArgumentException */ public function __construct($directory, $extension = '', $umask = 0002) { // YES, this needs to be *before* createPathIfNeeded() if ( ! is_int($umask)) { throw new \InvalidArgumentException(sprintf( 'The umask parameter is required to be integer, was: %s', gettype($umask) )); } $this->umask = $umask; if ( ! $this->createPathIfNeeded($directory)) { throw new \InvalidArgumentException(sprintf( 'The directory "%s" does not exist and could not be created.', $directory )); } if ( ! is_writable($directory)) { throw new \InvalidArgumentException(sprintf( 'The directory "%s" is not writable.', $directory )); } // YES, this needs to be *after* createPathIfNeeded() $this->directory = realpath($directory); $this->extension = (string) $extension; } /** * Gets the cache directory. * * @return string */ public function getDirectory() { return $this->directory; } /** * Gets the cache file extension. * * @return string|null */ public function getExtension() { return $this->extension; } /** * @param string $id * * @return string */ protected function getFilename($id) { return $this->directory . DIRECTORY_SEPARATOR . implode(str_split(hash('sha256', $id), 2), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . preg_replace($this->disallowedCharacterPatterns, $this->replacementCharacters, $id) . $this->extension; } /** * {@inheritdoc} */ protected function doDelete($id) { return @unlink($this->getFilename($id)); } /** * {@inheritdoc} */ protected function doFlush() { foreach ($this->getIterator() as $name => $file) { @unlink($name); } return true; } /** * {@inheritdoc} */ protected function doGetStats() { $usage = 0; foreach ($this->getIterator() as $file) { $usage += $file->getSize(); } $free = disk_free_space($this->directory); return array( Cache::STATS_HITS => null, Cache::STATS_MISSES => null, Cache::STATS_UPTIME => null, Cache::STATS_MEMORY_USAGE => $usage, Cache::STATS_MEMORY_AVAILABLE => $free, ); } /** * Create path if needed. * * @param string $path * @return bool TRUE on success or if path already exists, FALSE if path cannot be created. */ private function createPathIfNeeded($path) { if ( ! is_dir($path)) { if (false === @mkdir($path, 0777 & (~$this->umask), true) && !is_dir($path)) { return false; } } return true; } /** * Writes a string content to file in an atomic way. * * @param string $filename Path to the file where to write the data. * @param string $content The content to write * * @return bool TRUE on success, FALSE if path cannot be created, if path is not writable or an any other error. */ protected function writeFile($filename, $content) { $filepath = pathinfo($filename, PATHINFO_DIRNAME); if ( ! $this->createPathIfNeeded($filepath)) { return false; } if ( ! is_writable($filepath)) { return false; } $tmpFile = tempnam($filepath, 'swap'); @chmod($tmpFile, 0666 & (~$this->umask)); if (file_put_contents($tmpFile, $content) !== false) { if (@rename($tmpFile, $filename)) { return true; } @unlink($tmpFile); } return false; } /** * @return \Iterator */ private function getIterator() { return new \RegexIterator( new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory)), '/^.+' . preg_quote($this->extension, '/') . '$/i' ); } } lib/Doctrine/Common/Cache/FilesystemCache.php000064400000005542144760114440015110 0ustar00. */ namespace Doctrine\Common\Cache; /** * Filesystem cache driver. * * @since 2.3 * @author Fabio B. Silva */ class FilesystemCache extends FileCache { const EXTENSION = '.doctrinecache.data'; /** * {@inheritdoc} */ public function __construct($directory, $extension = self::EXTENSION, $umask = 0002) { parent::__construct($directory, $extension, $umask); } /** * {@inheritdoc} */ protected function doFetch($id) { $data = ''; $lifetime = -1; $filename = $this->getFilename($id); if ( ! is_file($filename)) { return false; } $resource = fopen($filename, "r"); if (false !== ($line = fgets($resource))) { $lifetime = (integer) $line; } if ($lifetime !== 0 && $lifetime < time()) { fclose($resource); return false; } while (false !== ($line = fgets($resource))) { $data .= $line; } fclose($resource); return unserialize($data); } /** * {@inheritdoc} */ protected function doContains($id) { $lifetime = -1; $filename = $this->getFilename($id); if ( ! is_file($filename)) { return false; } $resource = fopen($filename, "r"); if (false !== ($line = fgets($resource))) { $lifetime = (integer) $line; } fclose($resource); return $lifetime === 0 || $lifetime > time(); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { if ($lifeTime > 0) { $lifeTime = time() + $lifeTime; } $data = serialize($data); $filename = $this->getFilename($id); return $this->writeFile($filename, $lifeTime . PHP_EOL . $data); } } lib/Doctrine/Common/Cache/FlushableCache.php000064400000002557144760114440014674 0ustar00. */ namespace Doctrine\Common\Cache; /** * Interface for cache that can be flushed. * * @link www.doctrine-project.org * @since 1.4 * @author Adirelle */ interface FlushableCache { /** * Flushes all cache entries, globally. * * @return boolean TRUE if the cache entries were successfully flushed, FALSE otherwise. */ public function flushAll(); } lib/Doctrine/Common/Cache/MemcacheCache.php000064400000006347144760114440014472 0ustar00. */ namespace Doctrine\Common\Cache; use \Memcache; /** * Memcache cache provider. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author David Abdemoulaie */ class MemcacheCache extends CacheProvider { /** * @var Memcache|null */ private $memcache; /** * Sets the memcache instance to use. * * @param Memcache $memcache * * @return void */ public function setMemcache(Memcache $memcache) { $this->memcache = $memcache; } /** * Gets the memcache instance used by the cache. * * @return Memcache|null */ public function getMemcache() { return $this->memcache; } /** * {@inheritdoc} */ protected function doFetch($id) { return $this->memcache->get($id); } /** * {@inheritdoc} */ protected function doContains($id) { $flags = null; $this->memcache->get($id, $flags); //if memcache has changed the value of "flags", it means the value exists return ($flags !== null); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { if ($lifeTime > 30 * 24 * 3600) { $lifeTime = time() + $lifeTime; } return $this->memcache->set($id, $data, 0, (int) $lifeTime); } /** * {@inheritdoc} */ protected function doDelete($id) { return $this->memcache->delete($id); } /** * {@inheritdoc} */ protected function doFlush() { return $this->memcache->flush(); } /** * {@inheritdoc} */ protected function doGetStats() { $stats = $this->memcache->getStats(); return array( Cache::STATS_HITS => $stats['get_hits'], Cache::STATS_MISSES => $stats['get_misses'], Cache::STATS_UPTIME => $stats['uptime'], Cache::STATS_MEMORY_USAGE => $stats['bytes'], Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], ); } } lib/Doctrine/Common/Cache/MemcachedCache.php000064400000006646144760114440014640 0ustar00. */ namespace Doctrine\Common\Cache; use \Memcached; /** * Memcached cache provider. * * @link www.doctrine-project.org * @since 2.2 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author David Abdemoulaie */ class MemcachedCache extends CacheProvider { /** * @var Memcached|null */ private $memcached; /** * Sets the memcache instance to use. * * @param Memcached $memcached * * @return void */ public function setMemcached(Memcached $memcached) { $this->memcached = $memcached; } /** * Gets the memcached instance used by the cache. * * @return Memcached|null */ public function getMemcached() { return $this->memcached; } /** * {@inheritdoc} */ protected function doFetch($id) { return $this->memcached->get($id); } /** * {@inheritdoc} */ protected function doFetchMultiple(array $keys) { return $this->memcached->getMulti($keys); } /** * {@inheritdoc} */ protected function doContains($id) { return (false !== $this->memcached->get($id)); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { if ($lifeTime > 30 * 24 * 3600) { $lifeTime = time() + $lifeTime; } return $this->memcached->set($id, $data, (int) $lifeTime); } /** * {@inheritdoc} */ protected function doDelete($id) { return $this->memcached->delete($id); } /** * {@inheritdoc} */ protected function doFlush() { return $this->memcached->flush(); } /** * {@inheritdoc} */ protected function doGetStats() { $stats = $this->memcached->getStats(); $servers = $this->memcached->getServerList(); $key = $servers[0]['host'] . ':' . $servers[0]['port']; $stats = $stats[$key]; return array( Cache::STATS_HITS => $stats['get_hits'], Cache::STATS_MISSES => $stats['get_misses'], Cache::STATS_UPTIME => $stats['uptime'], Cache::STATS_MEMORY_USAGE => $stats['bytes'], Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], ); } } lib/Doctrine/Common/Cache/MongoDBCache.php000064400000013406144760114440014247 0ustar00. */ namespace Doctrine\Common\Cache; use MongoBinData; use MongoCollection; use MongoDate; /** * MongoDB cache provider. * * @since 1.1 * @author Jeremy Mikola */ class MongoDBCache extends CacheProvider { /** * The data field will store the serialized PHP value. */ const DATA_FIELD = 'd'; /** * The expiration field will store a MongoDate value indicating when the * cache entry should expire. * * With MongoDB 2.2+, entries can be automatically deleted by MongoDB by * indexing this field wit the "expireAfterSeconds" option equal to zero. * This will direct MongoDB to regularly query for and delete any entries * whose date is older than the current time. Entries without a date value * in this field will be ignored. * * The cache provider will also check dates on its own, in case expired * entries are fetched before MongoDB's TTLMonitor pass can expire them. * * @see http://docs.mongodb.org/manual/tutorial/expire-data/ */ const EXPIRATION_FIELD = 'e'; /** * @var MongoCollection */ private $collection; /** * Constructor. * * This provider will default to the write concern and read preference * options set on the MongoCollection instance (or inherited from MongoDB or * MongoClient). Using an unacknowledged write concern (< 1) may make the * return values of delete() and save() unreliable. Reading from secondaries * may make contain() and fetch() unreliable. * * @see http://www.php.net/manual/en/mongo.readpreferences.php * @see http://www.php.net/manual/en/mongo.writeconcerns.php * @param MongoCollection $collection */ public function __construct(MongoCollection $collection) { $this->collection = $collection; } /** * {@inheritdoc} */ protected function doFetch($id) { $document = $this->collection->findOne(array('_id' => $id), array(self::DATA_FIELD, self::EXPIRATION_FIELD)); if ($document === null) { return false; } if ($this->isExpired($document)) { $this->doDelete($id); return false; } return unserialize($document[self::DATA_FIELD]->bin); } /** * {@inheritdoc} */ protected function doContains($id) { $document = $this->collection->findOne(array('_id' => $id), array(self::EXPIRATION_FIELD)); if ($document === null) { return false; } if ($this->isExpired($document)) { $this->doDelete($id); return false; } return true; } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { $result = $this->collection->update( array('_id' => $id), array('$set' => array( self::EXPIRATION_FIELD => ($lifeTime > 0 ? new MongoDate(time() + $lifeTime) : null), self::DATA_FIELD => new MongoBinData(serialize($data), MongoBinData::BYTE_ARRAY), )), array('upsert' => true, 'multiple' => false) ); return isset($result['ok']) ? $result['ok'] == 1 : true; } /** * {@inheritdoc} */ protected function doDelete($id) { $result = $this->collection->remove(array('_id' => $id)); return isset($result['n']) ? $result['n'] == 1 : true; } /** * {@inheritdoc} */ protected function doFlush() { // Use remove() in lieu of drop() to maintain any collection indexes $result = $this->collection->remove(); return isset($result['ok']) ? $result['ok'] == 1 : true; } /** * {@inheritdoc} */ protected function doGetStats() { $serverStatus = $this->collection->db->command(array( 'serverStatus' => 1, 'locks' => 0, 'metrics' => 0, 'recordStats' => 0, 'repl' => 0, )); $collStats = $this->collection->db->command(array('collStats' => 1)); return array( Cache::STATS_HITS => null, Cache::STATS_MISSES => null, Cache::STATS_UPTIME => (isset($serverStatus['uptime']) ? (integer) $serverStatus['uptime'] : null), Cache::STATS_MEMORY_USAGE => (isset($collStats['size']) ? (integer) $collStats['size'] : null), Cache::STATS_MEMORY_AVAILABLE => null, ); } /** * Check if the document is expired. * * @param array $document * @return boolean */ private function isExpired(array $document) { return isset($document[self::EXPIRATION_FIELD]) && $document[self::EXPIRATION_FIELD] instanceof MongoDate && $document[self::EXPIRATION_FIELD]->sec < time(); } } lib/Doctrine/Common/Cache/MultiGetCache.php000064400000003103144760114440014505 0ustar00. */ namespace Doctrine\Common\Cache; /** * Interface for cache drivers that allows to get many items at once. * * @link www.doctrine-project.org * @since 1.4 * @author Asmir Mustafic */ interface MultiGetCache { /** * Returns an associative array of values for keys is found in cache. * * @param string[] $keys Array of keys to retrieve from cache * @return mixed[] Array of retrieved values, indexed by the specified keys. * Values that couldn't be retrieved are not contained in this array. */ function fetchMultiple(array $keys); } lib/Doctrine/Common/Cache/PhpFileCache.php000064400000006432144760114440014312 0ustar00. */ namespace Doctrine\Common\Cache; /** * Php file cache driver. * * @since 2.3 * @author Fabio B. Silva */ class PhpFileCache extends FileCache { const EXTENSION = '.doctrinecache.php'; /** * {@inheritdoc} */ public function __construct($directory, $extension = self::EXTENSION, $umask = 0002) { parent::__construct($directory, $extension, $umask); } /** * {@inheritdoc} */ protected function doFetch($id) { $value = $this->includeFileForId($id); if (! $value) { return false; } if ($value['lifetime'] !== 0 && $value['lifetime'] < time()) { return false; } return $value['data']; } /** * {@inheritdoc} */ protected function doContains($id) { $value = $this->includeFileForId($id); if (! $value) { return false; } return $value['lifetime'] === 0 || $value['lifetime'] > time(); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { if ($lifeTime > 0) { $lifeTime = time() + $lifeTime; } if (is_object($data) && ! method_exists($data, '__set_state')) { throw new \InvalidArgumentException( "Invalid argument given, PhpFileCache only allows objects that implement __set_state() " . "and fully support var_export(). You can use the FilesystemCache to save arbitrary object " . "graphs using serialize()/deserialize()." ); } $filename = $this->getFilename($id); $value = array( 'lifetime' => $lifeTime, 'data' => $data ); $value = var_export($value, true); $code = sprintf('writeFile($filename, $code); } /** * @param string $id * * @return array|false */ private function includeFileForId($id) { $fileName = $this->getFilename($id); // note: error suppression is still faster than `file_exists`, `is_file` and `is_readable` $value = @include $fileName; if (! isset($value['lifetime'])) { return false; } return $value; } } lib/Doctrine/Common/Cache/PredisCache.php000064400000004345144760114440014212 0ustar00 */ class PredisCache extends CacheProvider { /** * @var Client */ private $client; /** * @param Client $client * * @return void */ public function __construct(Client $client) { $this->client = $client; } /** * {@inheritdoc} */ protected function doFetch($id) { $result = $this->client->get($id); if (null === $result) { return false; } return unserialize($result); } /** * {@inheritdoc} */ protected function doFetchMultiple(array $keys) { $fetchedItems = call_user_func_array(array($this->client, 'mget'), $keys); return array_filter(array_combine($keys, array_map('unserialize', $fetchedItems))); } /** * {@inheritdoc} */ protected function doContains($id) { return $this->client->exists($id); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { $data = serialize($data); if ($lifeTime > 0) { $response = $this->client->setex($id, $lifeTime, $data); } else { $response = $this->client->set($id, $data); } return $response === true || $response == 'OK'; } /** * {@inheritdoc} */ protected function doDelete($id) { return $this->client->del($id) > 0; } /** * {@inheritdoc} */ protected function doFlush() { $response = $this->client->flushdb(); return $response === true || $response == 'OK'; } /** * {@inheritdoc} */ protected function doGetStats() { $info = $this->client->info(); return array( Cache::STATS_HITS => $info['Stats']['keyspace_hits'], Cache::STATS_MISSES => $info['Stats']['keyspace_misses'], Cache::STATS_UPTIME => $info['Server']['uptime_in_seconds'], Cache::STATS_MEMORY_USAGE => $info['Memory']['used_memory'], Cache::STATS_MEMORY_AVAILABLE => false ); } } lib/Doctrine/Common/Cache/RedisCache.php000064400000007067144760114440014036 0ustar00. */ namespace Doctrine\Common\Cache; use Redis; /** * Redis cache provider. * * @link www.doctrine-project.org * @since 2.2 * @author Osman Ungur */ class RedisCache extends CacheProvider { /** * @var Redis|null */ private $redis; /** * Sets the redis instance to use. * * @param Redis $redis * * @return void */ public function setRedis(Redis $redis) { $redis->setOption(Redis::OPT_SERIALIZER, $this->getSerializerValue()); $this->redis = $redis; } /** * Gets the redis instance used by the cache. * * @return Redis|null */ public function getRedis() { return $this->redis; } /** * {@inheritdoc} */ protected function doFetch($id) { return $this->redis->get($id); } /** * {@inheritdoc} */ protected function doFetchMultiple(array $keys) { return array_filter(array_combine($keys, $this->redis->mget($keys))); } /** * {@inheritdoc} */ protected function doContains($id) { return $this->redis->exists($id); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { if ($lifeTime > 0) { return $this->redis->setex($id, $lifeTime, $data); } return $this->redis->set($id, $data); } /** * {@inheritdoc} */ protected function doDelete($id) { return $this->redis->delete($id) > 0; } /** * {@inheritdoc} */ protected function doFlush() { return $this->redis->flushDB(); } /** * {@inheritdoc} */ protected function doGetStats() { $info = $this->redis->info(); return array( Cache::STATS_HITS => $info['keyspace_hits'], Cache::STATS_MISSES => $info['keyspace_misses'], Cache::STATS_UPTIME => $info['uptime_in_seconds'], Cache::STATS_MEMORY_USAGE => $info['used_memory'], Cache::STATS_MEMORY_AVAILABLE => false ); } /** * Returns the serializer constant to use. If Redis is compiled with * igbinary support, that is used. Otherwise the default PHP serializer is * used. * * @return integer One of the Redis::SERIALIZER_* constants */ protected function getSerializerValue() { if (defined('HHVM_VERSION')) { return Redis::SERIALIZER_PHP; } return defined('Redis::SERIALIZER_IGBINARY') ? Redis::SERIALIZER_IGBINARY : Redis::SERIALIZER_PHP; } } lib/Doctrine/Common/Cache/RiakCache.php000064400000015232144760114440013647 0ustar00. */ namespace Doctrine\Common\Cache; use Riak\Bucket; use Riak\Connection; use Riak\Input; use Riak\Exception; use Riak\Object; /** * Riak cache provider. * * @link www.doctrine-project.org * @since 1.1 * @author Guilherme Blanco */ class RiakCache extends CacheProvider { const EXPIRES_HEADER = 'X-Riak-Meta-Expires'; /** * @var \Riak\Bucket */ private $bucket; /** * Sets the riak bucket instance to use. * * @param \Riak\Bucket $bucket */ public function __construct(Bucket $bucket) { $this->bucket = $bucket; } /** * {@inheritdoc} */ protected function doFetch($id) { try { $response = $this->bucket->get($id); // No objects found if ( ! $response->hasObject()) { return false; } // Check for attempted siblings $object = ($response->hasSiblings()) ? $this->resolveConflict($id, $response->getVClock(), $response->getObjectList()) : $response->getFirstObject(); // Check for expired object if ($this->isExpired($object)) { $this->bucket->delete($object); return false; } return unserialize($object->getContent()); } catch (Exception\RiakException $e) { // Covers: // - Riak\ConnectionException // - Riak\CommunicationException // - Riak\UnexpectedResponseException // - Riak\NotFoundException } return false; } /** * {@inheritdoc} */ protected function doContains($id) { try { // We only need the HEAD, not the entire object $input = new Input\GetInput(); $input->setReturnHead(true); $response = $this->bucket->get($id, $input); // No objects found if ( ! $response->hasObject()) { return false; } $object = $response->getFirstObject(); // Check for expired object if ($this->isExpired($object)) { $this->bucket->delete($object); return false; } return true; } catch (Exception\RiakException $e) { // Do nothing } return false; } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { try { $object = new Object($id); $object->setContent(serialize($data)); if ($lifeTime > 0) { $object->addMetadata(self::EXPIRES_HEADER, (string) (time() + $lifeTime)); } $this->bucket->put($object); return true; } catch (Exception\RiakException $e) { // Do nothing } return false; } /** * {@inheritdoc} */ protected function doDelete($id) { try { $this->bucket->delete($id); return true; } catch (Exception\BadArgumentsException $e) { // Key did not exist on cluster already } catch (Exception\RiakException $e) { // Covers: // - Riak\Exception\ConnectionException // - Riak\Exception\CommunicationException // - Riak\Exception\UnexpectedResponseException } return false; } /** * {@inheritdoc} */ protected function doFlush() { try { $keyList = $this->bucket->getKeyList(); foreach ($keyList as $key) { $this->bucket->delete($key); } return true; } catch (Exception\RiakException $e) { // Do nothing } return false; } /** * {@inheritdoc} */ protected function doGetStats() { // Only exposed through HTTP stats API, not Protocol Buffers API return null; } /** * Check if a given Riak Object have expired. * * @param \Riak\Object $object * * @return boolean */ private function isExpired(Object $object) { $metadataMap = $object->getMetadataMap(); return isset($metadataMap[self::EXPIRES_HEADER]) && $metadataMap[self::EXPIRES_HEADER] < time(); } /** * On-read conflict resolution. Applied approach here is last write wins. * Specific needs may override this method to apply alternate conflict resolutions. * * {@internal Riak does not attempt to resolve a write conflict, and store * it as sibling of conflicted one. By following this approach, it is up to * the next read to resolve the conflict. When this happens, your fetched * object will have a list of siblings (read as a list of objects). * In our specific case, we do not care about the intermediate ones since * they are all the same read from storage, and we do apply a last sibling * (last write) wins logic. * If by any means our resolution generates another conflict, it'll up to * next read to properly solve it.} * * @param string $id * @param string $vClock * @param array $objectList * * @return \Riak\Object */ protected function resolveConflict($id, $vClock, array $objectList) { // Our approach here is last-write wins $winner = $objectList[count($objectList)]; $putInput = new Input\PutInput(); $putInput->setVClock($vClock); $mergedObject = new Object($id); $mergedObject->setContent($winner->getContent()); $this->bucket->put($mergedObject, $putInput); return $mergedObject; } } lib/Doctrine/Common/Cache/SQLite3Cache.php000064400000012452144760114440014206 0ustar00. */ namespace Doctrine\Common\Cache; use SQLite3; use SQLite3Result; /** * SQLite3 cache provider. * * @since 1.4 * @author Jake Bell */ class SQLite3Cache extends CacheProvider { /** * The ID field will store the cache key. */ const ID_FIELD = 'k'; /** * The data field will store the serialized PHP value. */ const DATA_FIELD = 'd'; /** * The expiration field will store a date value indicating when the * cache entry should expire. */ const EXPIRATION_FIELD = 'e'; /** * @var SQLite3 */ private $sqlite; /** * @var string */ private $table; /** * Constructor. * * Calling the constructor will ensure that the database file and table * exist and will create both if they don't. * * @param SQLite3 $sqlite * @param string $table */ public function __construct(SQLite3 $sqlite, $table) { $this->sqlite = $sqlite; $this->table = (string) $table; list($id, $data, $exp) = $this->getFields(); return $this->sqlite->exec(sprintf( 'CREATE TABLE IF NOT EXISTS %s(%s TEXT PRIMARY KEY NOT NULL, %s BLOB, %s INTEGER)', $table, $id, $data, $exp )); } /** * {@inheritdoc} */ protected function doFetch($id) { if ($item = $this->findById($id)) { return unserialize($item[self::DATA_FIELD]); } return false; } /** * {@inheritdoc} */ protected function doContains($id) { return (boolean) $this->findById($id, false); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { $statement = $this->sqlite->prepare(sprintf( 'INSERT OR REPLACE INTO %s (%s) VALUES (:id, :data, :expire)', $this->table, implode(',', $this->getFields()) )); $statement->bindValue(':id', $id); $statement->bindValue(':data', serialize($data), SQLITE3_BLOB); $statement->bindValue(':expire', $lifeTime > 0 ? time() + $lifeTime : null); return $statement->execute() instanceof SQLite3Result; } /** * {@inheritdoc} */ protected function doDelete($id) { list($idField) = $this->getFields(); $statement = $this->sqlite->prepare(sprintf( 'DELETE FROM %s WHERE %s = :id', $this->table, $idField )); $statement->bindValue(':id', $id); return $statement->execute() instanceof SQLite3Result; } /** * {@inheritdoc} */ protected function doFlush() { return $this->sqlite->exec(sprintf('DELETE FROM %s', $this->table)); } /** * {@inheritdoc} */ protected function doGetStats() { // no-op. } /** * Find a single row by ID. * * @param mixed $id * @param boolean $includeData * * @return array|null */ private function findById($id, $includeData = true) { list($idField) = $fields = $this->getFields(); if (!$includeData) { $key = array_search(static::DATA_FIELD, $fields); unset($fields[$key]); } $statement = $this->sqlite->prepare(sprintf( 'SELECT %s FROM %s WHERE %s = :id LIMIT 1', implode(',', $fields), $this->table, $idField )); $statement->bindValue(':id', $id, SQLITE3_TEXT); $item = $statement->execute()->fetchArray(SQLITE3_ASSOC); if ($item === false) { return null; } if ($this->isExpired($item)) { $this->doDelete($id); return null; } return $item; } /** * Gets an array of the fields in our table. * * @return array */ private function getFields() { return array(static::ID_FIELD, static::DATA_FIELD, static::EXPIRATION_FIELD); } /** * Check if the item is expired. * * @param array $item * @return boolean */ private function isExpired(array $item) { return isset($item[static::EXPIRATION_FIELD]) && $item[self::EXPIRATION_FIELD] !== null && $item[self::EXPIRATION_FIELD] < time(); } } lib/Doctrine/Common/Cache/Version.php000064400000002062144760114440013457 0ustar00. */ namespace Doctrine\Common\Cache; class Version { const VERSION = '1.4.0-DEV'; } lib/Doctrine/Common/Cache/VoidCache.php000064400000003621144760114440013661 0ustar00. */ namespace Doctrine\Common\Cache; /** * Void cache driver. The cache could be of use in tests where you don`t need to cache anything. * * @link www.doctrine-project.org * @since 1.5 * @author Kotlyar Maksim */ class VoidCache extends CacheProvider { /** * {@inheritDoc} */ protected function doFetch($id) { return false; } /** * {@inheritDoc} */ protected function doContains($id) { return false; } /** * {@inheritDoc} */ protected function doSave($id, $data, $lifeTime = 0) { return true; } /** * {@inheritDoc} */ protected function doDelete($id) { return true; } /** * {@inheritDoc} */ protected function doFlush() { return true; } /** * {@inheritDoc} */ protected function doGetStats() { return; } } lib/Doctrine/Common/Cache/WinCacheCache.php000064400000005157144760114440014447 0ustar00. */ namespace Doctrine\Common\Cache; /** * WinCache cache provider. * * @link www.doctrine-project.org * @since 2.2 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author David Abdemoulaie */ class WinCacheCache extends CacheProvider { /** * {@inheritdoc} */ protected function doFetch($id) { return wincache_ucache_get($id); } /** * {@inheritdoc} */ protected function doContains($id) { return wincache_ucache_exists($id); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { return (bool) wincache_ucache_set($id, $data, (int) $lifeTime); } /** * {@inheritdoc} */ protected function doDelete($id) { return wincache_ucache_delete($id); } /** * {@inheritdoc} */ protected function doFlush() { return wincache_ucache_clear(); } /** * {@inheritdoc} */ protected function doGetStats() { $info = wincache_ucache_info(); $meminfo = wincache_ucache_meminfo(); return array( Cache::STATS_HITS => $info['total_hit_count'], Cache::STATS_MISSES => $info['total_miss_count'], Cache::STATS_UPTIME => $info['total_cache_uptime'], Cache::STATS_MEMORY_USAGE => $meminfo['memory_total'], Cache::STATS_MEMORY_AVAILABLE => $meminfo['memory_free'], ); } } lib/Doctrine/Common/Cache/XcacheCache.php000064400000006131144760114440014152 0ustar00. */ namespace Doctrine\Common\Cache; /** * Xcache cache driver. * * @link www.doctrine-project.org * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author David Abdemoulaie */ class XcacheCache extends CacheProvider { /** * {@inheritdoc} */ protected function doFetch($id) { return $this->doContains($id) ? unserialize(xcache_get($id)) : false; } /** * {@inheritdoc} */ protected function doContains($id) { return xcache_isset($id); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { return xcache_set($id, serialize($data), (int) $lifeTime); } /** * {@inheritdoc} */ protected function doDelete($id) { return xcache_unset($id); } /** * {@inheritdoc} */ protected function doFlush() { $this->checkAuthorization(); xcache_clear_cache(XC_TYPE_VAR); return true; } /** * Checks that xcache.admin.enable_auth is Off. * * @return void * * @throws \BadMethodCallException When xcache.admin.enable_auth is On. */ protected function checkAuthorization() { if (ini_get('xcache.admin.enable_auth')) { throw new \BadMethodCallException( 'To use all features of \Doctrine\Common\Cache\XcacheCache, ' . 'you must set "xcache.admin.enable_auth" to "Off" in your php.ini.' ); } } /** * {@inheritdoc} */ protected function doGetStats() { $this->checkAuthorization(); $info = xcache_info(XC_TYPE_VAR, 0); return array( Cache::STATS_HITS => $info['hits'], Cache::STATS_MISSES => $info['misses'], Cache::STATS_UPTIME => null, Cache::STATS_MEMORY_USAGE => $info['size'], Cache::STATS_MEMORY_AVAILABLE => $info['avail'], ); } } lib/Doctrine/Common/Cache/ZendDataCache.php000064400000004244144760114440014454 0ustar00. */ namespace Doctrine\Common\Cache; /** * Zend Data Cache cache driver. * * @link www.doctrine-project.org * @since 2.0 * @author Ralph Schindler * @author Guilherme Blanco */ class ZendDataCache extends CacheProvider { /** * {@inheritdoc} */ protected function doFetch($id) { return zend_shm_cache_fetch($id); } /** * {@inheritdoc} */ protected function doContains($id) { return (false !== zend_shm_cache_fetch($id)); } /** * {@inheritdoc} */ protected function doSave($id, $data, $lifeTime = 0) { return zend_shm_cache_store($id, $data, $lifeTime); } /** * {@inheritdoc} */ protected function doDelete($id) { return zend_shm_cache_delete($id); } /** * {@inheritdoc} */ protected function doFlush() { $namespace = $this->getNamespace(); if (empty($namespace)) { return zend_shm_cache_clear(); } return zend_shm_cache_clear($namespace); } /** * {@inheritdoc} */ protected function doGetStats() { return null; } } phpunit.xml.dist000064400000001305144760114440007723 0ustar00 ./tests/Doctrine/ ./lib/Doctrine/ tests/Doctrine/Tests/Common/Cache/ApcCacheTest.php000064400000000640144760114440016017 0ustar00markTestSkipped('The ' . __CLASS__ .' requires the use of APC'); } } protected function _getCacheDriver() { return new ApcCache(); } }tests/Doctrine/Tests/Common/Cache/ArrayCacheTest.php000064400000000706144760114440016375 0ustar00_getCacheDriver(); $stats = $cache->getStats(); $this->assertNull($stats); } protected function isSharedStorage() { return false; } }tests/Doctrine/Tests/Common/Cache/BaseFileCacheTest.php000064400000001660144760114440016771 0ustar00directory = sys_get_temp_dir() . '/doctrine_cache_'. uniqid(); } while (file_exists($this->directory)); } public function tearDown() { if ( ! is_dir($this->directory)) { return; } $iterator = new RecursiveDirectoryIterator($this->directory); foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST) as $file) { if ($file->isFile()) { @unlink($file->getRealPath()); } elseif ($file->isDir()) { @rmdir($file->getRealPath()); } } } protected function isSharedStorage() { return false; } } tests/Doctrine/Tests/Common/Cache/CacheTest.php000064400000030145144760114440015376 0ustar00_getCacheDriver(); // Test saving a value, checking if it exists, and fetching it back $this->assertTrue($cache->save('key', 'value')); $this->assertTrue($cache->contains('key')); $this->assertEquals('value', $cache->fetch('key')); // Test updating the value of a cache entry $this->assertTrue($cache->save('key', 'value-changed')); $this->assertTrue($cache->contains('key')); $this->assertEquals('value-changed', $cache->fetch('key')); // Test deleting a value $this->assertTrue($cache->delete('key')); $this->assertFalse($cache->contains('key')); } public function testFetchMulti() { $cache = $this->_getCacheDriver(); $cache->deleteAll(); // Test saving some values, checking if it exists, and fetching it back with multiGet $this->assertTrue($cache->save('key1', 'value1')); $this->assertTrue($cache->save('key2', 'value2')); $this->assertEquals( array('key1' => 'value1', 'key2' => 'value2'), $cache->fetchMultiple(array('key1', 'key2')) ); $this->assertEquals( array('key1' => 'value1', 'key2' => 'value2'), $cache->fetchMultiple(array('key1', 'key3', 'key2')) ); $this->assertEquals( array('key1' => 'value1', 'key2' => 'value2'), $cache->fetchMultiple(array('key1', 'key2', 'key3')) ); } public function testFetchMultiWillFilterNonRequestedKeys() { /* @var $cache \Doctrine\Common\Cache\CacheProvider|\PHPUnit_Framework_MockObject_MockObject */ $cache = $this->getMockForAbstractClass( 'Doctrine\Common\Cache\CacheProvider', array(), '', true, true, true, array('doFetchMultiple') ); $cache ->expects($this->once()) ->method('doFetchMultiple') ->will($this->returnValue(array( '[foo][]' => 'bar', '[bar][]' => 'baz', '[baz][]' => 'tab', ))); $this->assertEquals( array('foo' => 'bar', 'bar' => 'baz'), $cache->fetchMultiple(array('foo', 'bar')) ); } public function provideCrudValues() { return array( 'array' => array(array('one', 2, 3.0)), 'string' => array('value'), 'integer' => array(1), 'float' => array(1.5), 'object' => array(new ArrayObject()), 'null' => array(null), ); } public function testDeleteAll() { $cache = $this->_getCacheDriver(); $this->assertTrue($cache->save('key1', 1)); $this->assertTrue($cache->save('key2', 2)); $this->assertTrue($cache->deleteAll()); $this->assertFalse($cache->contains('key1')); $this->assertFalse($cache->contains('key2')); } public function testDeleteAllAndNamespaceVersioningBetweenCaches() { if ( ! $this->isSharedStorage()) { $this->markTestSkipped('The ' . __CLASS__ .' does not use shared storage'); } $cache1 = $this->_getCacheDriver(); $cache2 = $this->_getCacheDriver(); $this->assertTrue($cache1->save('key1', 1)); $this->assertTrue($cache2->save('key2', 2)); /* Both providers are initialized with the same namespace version, so * they can see entries set by each other. */ $this->assertTrue($cache1->contains('key1')); $this->assertTrue($cache1->contains('key2')); $this->assertTrue($cache2->contains('key1')); $this->assertTrue($cache2->contains('key2')); /* Deleting all entries through one provider will only increment the * namespace version on that object (and in the cache itself, which new * instances will use to initialize). The second provider will retain * its original version and still see stale data. */ $this->assertTrue($cache1->deleteAll()); $this->assertFalse($cache1->contains('key1')); $this->assertFalse($cache1->contains('key2')); $this->assertTrue($cache2->contains('key1')); $this->assertTrue($cache2->contains('key2')); /* A new cache provider should not see the deleted entries, since its * namespace version will be initialized. */ $cache3 = $this->_getCacheDriver(); $this->assertFalse($cache3->contains('key1')); $this->assertFalse($cache3->contains('key2')); } public function testFlushAll() { $cache = $this->_getCacheDriver(); $this->assertTrue($cache->save('key1', 1)); $this->assertTrue($cache->save('key2', 2)); $this->assertTrue($cache->flushAll()); $this->assertFalse($cache->contains('key1')); $this->assertFalse($cache->contains('key2')); } public function testFlushAllAndNamespaceVersioningBetweenCaches() { if ( ! $this->isSharedStorage()) { $this->markTestSkipped('The ' . __CLASS__ .' does not use shared storage'); } $cache1 = $this->_getCacheDriver(); $cache2 = $this->_getCacheDriver(); /* Deleting all elements from the first provider should increment its * namespace version before saving the first entry. */ $cache1->deleteAll(); $this->assertTrue($cache1->save('key1', 1)); /* The second provider will be initialized with the same namespace * version upon its first save operation. */ $this->assertTrue($cache2->save('key2', 2)); /* Both providers have the same namespace version and can see entires * set by each other. */ $this->assertTrue($cache1->contains('key1')); $this->assertTrue($cache1->contains('key2')); $this->assertTrue($cache2->contains('key1')); $this->assertTrue($cache2->contains('key2')); /* Flushing all entries through one cache will remove all entries from * the cache but leave their namespace version as-is. */ $this->assertTrue($cache1->flushAll()); $this->assertFalse($cache1->contains('key1')); $this->assertFalse($cache1->contains('key2')); $this->assertFalse($cache2->contains('key1')); $this->assertFalse($cache2->contains('key2')); /* Inserting a new entry will use the same, incremented namespace * version, and it will be visible to both providers. */ $this->assertTrue($cache1->save('key1', 1)); $this->assertTrue($cache1->contains('key1')); $this->assertTrue($cache2->contains('key1')); /* A new cache provider will be initialized with the original namespace * version and not share any visibility with the first two providers. */ $cache3 = $this->_getCacheDriver(); $this->assertFalse($cache3->contains('key1')); $this->assertFalse($cache3->contains('key2')); $this->assertTrue($cache3->save('key3', 3)); $this->assertTrue($cache3->contains('key3')); } public function testNamespace() { $cache = $this->_getCacheDriver(); $cache->setNamespace('ns1_'); $this->assertTrue($cache->save('key1', 1)); $this->assertTrue($cache->contains('key1')); $cache->setNamespace('ns2_'); $this->assertFalse($cache->contains('key1')); } public function testDeleteAllNamespace() { $cache = $this->_getCacheDriver(); $cache->setNamespace('ns1'); $this->assertFalse($cache->contains('key1')); $cache->save('key1', 'test'); $this->assertTrue($cache->contains('key1')); $cache->setNamespace('ns2'); $this->assertFalse($cache->contains('key1')); $cache->save('key1', 'test'); $this->assertTrue($cache->contains('key1')); $cache->setNamespace('ns1'); $this->assertTrue($cache->contains('key1')); $cache->deleteAll(); $this->assertFalse($cache->contains('key1')); $cache->setNamespace('ns2'); $this->assertTrue($cache->contains('key1')); $cache->deleteAll(); $this->assertFalse($cache->contains('key1')); } /** * @group DCOM-43 */ public function testGetStats() { $cache = $this->_getCacheDriver(); $stats = $cache->getStats(); $this->assertArrayHasKey(Cache::STATS_HITS, $stats); $this->assertArrayHasKey(Cache::STATS_MISSES, $stats); $this->assertArrayHasKey(Cache::STATS_UPTIME, $stats); $this->assertArrayHasKey(Cache::STATS_MEMORY_USAGE, $stats); $this->assertArrayHasKey(Cache::STATS_MEMORY_AVAILABLE, $stats); } public function testFetchMissShouldReturnFalse() { $cache = $this->_getCacheDriver(); /* Ensure that caches return boolean false instead of null on a fetch * miss to be compatible with ORM integration. */ $result = $cache->fetch('nonexistent_key'); $this->assertFalse($result); $this->assertNotNull($result); } /** * Check to see that, even if the user saves a value that can be interpreted as false, * the cache adapter will still recognize its existence there. * * @dataProvider falseCastedValuesProvider */ public function testFalseCastedValues($value) { $cache = $this->_getCacheDriver(); $this->assertTrue($cache->save('key', $value)); $this->assertTrue($cache->contains('key')); $this->assertEquals($value, $cache->fetch('key')); } /** * The following values get converted to FALSE if you cast them to a boolean. * @see http://php.net/manual/en/types.comparisons.php */ public function falseCastedValuesProvider() { return array( array(false), array(null), array(array()), array('0'), array(0), array(0.0), array('') ); } /** * Check to see that objects are correctly serialized and unserialized by the cache * provider. */ public function testCachedObject() { $cache = $this->_getCacheDriver(); $cache->deleteAll(); $obj = new \stdClass(); $obj->foo = "bar"; $obj2 = new \stdClass(); $obj2->bar = "foo"; $obj2->obj = $obj; $obj->obj2 = $obj2; $cache->save("obj", $obj); $fetched = $cache->fetch("obj"); $this->assertInstanceOf("stdClass", $obj); $this->assertInstanceOf("stdClass", $obj->obj2); $this->assertInstanceOf("stdClass", $obj->obj2->obj); $this->assertEquals("bar", $fetched->foo); $this->assertEquals("foo", $fetched->obj2->bar); } /** * Check to see that objects fetched via fetchMultiple are properly unserialized */ public function testFetchMultipleObjects() { $cache = $this->_getCacheDriver(); $cache->deleteAll(); $obj1 = new \stdClass(); $obj1->foo = "bar"; $cache->save("obj1", $obj1); $obj2 = new \stdClass(); $obj2->bar = "baz"; $cache->save("obj2", $obj2); $fetched = $cache->fetchMultiple(array("obj1", "obj2")); $this->assertInstanceOf("stdClass", $fetched["obj1"]); $this->assertInstanceOf("stdClass", $fetched["obj2"]); $this->assertEquals("bar", $fetched["obj1"]->foo); $this->assertEquals("baz", $fetched["obj2"]->bar); } /** * Return whether multiple cache providers share the same storage. * * This is used for skipping certain tests for shared storage behavior. * * @return boolean */ protected function isSharedStorage() { return true; } /** * @return \Doctrine\Common\Cache\CacheProvider */ abstract protected function _getCacheDriver(); } tests/Doctrine/Tests/Common/Cache/ChainCacheTest.php000064400000005235144760114440016343 0ustar00_getCacheDriver(); $stats = $cache->getStats(); $this->assertInternalType('array', $stats); } public function testOnlyFetchFirstOne() { $cache1 = new ArrayCache(); $cache2 = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider'); $cache2->expects($this->never())->method('doFetch'); $chainCache = new ChainCache(array($cache1, $cache2)); $chainCache->save('id', 'bar'); $this->assertEquals('bar', $chainCache->fetch('id')); } public function testFetchPropagateToFastestCache() { $cache1 = new ArrayCache(); $cache2 = new ArrayCache(); $cache2->save('bar', 'value'); $chainCache = new ChainCache(array($cache1, $cache2)); $this->assertFalse($cache1->contains('bar')); $result = $chainCache->fetch('bar'); $this->assertEquals('value', $result); $this->assertTrue($cache2->contains('bar')); } public function testNamespaceIsPropagatedToAllProviders() { $cache1 = new ArrayCache(); $cache2 = new ArrayCache(); $chainCache = new ChainCache(array($cache1, $cache2)); $chainCache->setNamespace('bar'); $this->assertEquals('bar', $cache1->getNamespace()); $this->assertEquals('bar', $cache2->getNamespace()); } public function testDeleteToAllProviders() { $cache1 = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider'); $cache2 = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider'); $cache1->expects($this->once())->method('doDelete'); $cache2->expects($this->once())->method('doDelete'); $chainCache = new ChainCache(array($cache1, $cache2)); $chainCache->delete('bar'); } public function testFlushToAllProviders() { $cache1 = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider'); $cache2 = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider'); $cache1->expects($this->once())->method('doFlush'); $cache2->expects($this->once())->method('doFlush'); $chainCache = new ChainCache(array($cache1, $cache2)); $chainCache->flushAll(); } protected function isSharedStorage() { return false; } }tests/Doctrine/Tests/Common/Cache/CouchbaseCacheTest.php000064400000002514144760114440017212 0ustar00couchbase = new Couchbase('127.0.0.1', 'Administrator', 'password', 'default'); } catch(Exception $ex) { $this->markTestSkipped('Could not instantiate the Couchbase cache because of: ' . $ex); } } else { $this->markTestSkipped('The ' . __CLASS__ .' requires the use of the couchbase extension'); } } public function testNoExpire() { $cache = $this->_getCacheDriver(); $cache->save('noexpire', 'value', 0); sleep(1); $this->assertTrue($cache->contains('noexpire'), 'Couchbase provider should support no-expire'); } public function testLongLifetime() { $cache = $this->_getCacheDriver(); $cache->save('key', 'value', 30 * 24 * 3600 + 1); $this->assertTrue($cache->contains('key'), 'Couchbase provider should support TTL > 30 days'); } protected function _getCacheDriver() { $driver = new CouchbaseCache(); $driver->setCouchbase($this->couchbase); return $driver; } }tests/Doctrine/Tests/Common/Cache/FileCacheTest.php000064400000011352144760114440016175 0ustar00driver = $this->getMock( 'Doctrine\Common\Cache\FileCache', array('doFetch', 'doContains', 'doSave'), array(), '', false ); } public function getProviderFileName() { return array( //The characters :\/<>"*?| are not valid in Windows filenames. array('key:1', 'key-1'), array('key\2', 'key-2'), array('key/3', 'key-3'), array('key<4', 'key-4'), array('key>5', 'key-5'), array('key"6', 'key-6'), array('key*7', 'key-7'), array('key?8', 'key-8'), array('key|9', 'key-9'), array('key[10]', 'key[10]'), array('keyä11', 'key--11'), array('../key12', '---key12'), array('key-13', 'key__13'), ); } /** * @dataProvider getProviderFileName */ public function testInvalidFilename($key, $expected) { $cache = $this->driver; $method = new \ReflectionMethod($cache, 'getFilename'); $method->setAccessible(true); $value = $method->invoke($cache, $key); $actual = pathinfo($value, PATHINFO_FILENAME); $this->assertEquals($expected, $actual); } public function testFilenameCollision() { $data = array( 'key:0' => 'key-0', 'key\0' => 'key-0', 'key/0' => 'key-0', 'key<0' => 'key-0', 'key>0' => 'key-0', 'key"0' => 'key-0', 'key*0' => 'key-0', 'key?0' => 'key-0', 'key|0' => 'key-0', 'key-0' => 'key__0', 'keyä0' => 'key--0', ); $paths = array(); $cache = $this->driver; $method = new \ReflectionMethod($cache, 'getFilename'); $method->setAccessible(true); foreach ($data as $key => $expected) { $path = $method->invoke($cache, $key); $actual = pathinfo($path, PATHINFO_FILENAME); $this->assertNotContains($path, $paths); $this->assertEquals($expected, $actual); $paths[] = $path; } } public function testFilenameShouldCreateThePathWithFourSubDirectories() { $cache = $this->driver; $method = new \ReflectionMethod($cache, 'getFilename'); $key = 'item-key'; $expectedDir = array( '84', 'e0', 'e2', 'e8', '93', 'fe', 'bb', '73', '7a', '0f', 'ee', '0c', '89', 'd5', '3f', '4b', 'b7', 'fc', 'b4', '4c', '57', 'cd', 'f3', 'd3', '2c', 'e7', '36', '3f', '5d', '59', '77', '60' ); $expectedDir = implode(DIRECTORY_SEPARATOR, $expectedDir); $method->setAccessible(true); $path = $method->invoke($cache, $key); $filename = pathinfo($path, PATHINFO_FILENAME); $dirname = pathinfo($path, PATHINFO_DIRNAME); $this->assertEquals('item__key', $filename); $this->assertEquals(DIRECTORY_SEPARATOR . $expectedDir, $dirname); $this->assertEquals(DIRECTORY_SEPARATOR . $expectedDir . DIRECTORY_SEPARATOR . 'item__key', $path); } public function testFileExtensionCorrectlyEscaped() { $driver1 = $this->getMock( 'Doctrine\Common\Cache\FileCache', array('doFetch', 'doContains', 'doSave'), array(__DIR__, '.*') ); $driver2 = $this->getMock( 'Doctrine\Common\Cache\FileCache', array('doFetch', 'doContains', 'doSave'), array(__DIR__, '.php') ); $doGetStats = new \ReflectionMethod($driver1, 'doGetStats'); $doGetStats->setAccessible(true); $stats1 = $doGetStats->invoke($driver1); $stats2 = $doGetStats->invoke($driver2); $this->assertSame(0, $stats1[Cache::STATS_MEMORY_USAGE]); $this->assertGreaterThan(0, $stats2[Cache::STATS_MEMORY_USAGE]); } /** * @group DCOM-266 */ public function testFileExtensionSlashCorrectlyEscaped() { $driver = $this->getMock( 'Doctrine\Common\Cache\FileCache', array('doFetch', 'doContains', 'doSave'), array(__DIR__ . '/../', '/' . basename(__FILE__)) ); $doGetStats = new \ReflectionMethod($driver, 'doGetStats'); $doGetStats->setAccessible(true); $stats = $doGetStats->invoke($driver); $this->assertGreaterThan(0, $stats[Cache::STATS_MEMORY_USAGE]); } } tests/Doctrine/Tests/Common/Cache/FilesystemCacheTest.php000064400000004225144760114440017443 0ustar00_getCacheDriver(); // Test save $cache->save('test_key', 'testing this out', 10); // Test contains to test that save() worked $this->assertTrue($cache->contains('test_key')); // Test fetch $this->assertEquals('testing this out', $cache->fetch('test_key')); // access private methods $getFilename = new \ReflectionMethod($cache, 'getFilename'); $getNamespacedId = new \ReflectionMethod($cache, 'getNamespacedId'); $getFilename->setAccessible(true); $getNamespacedId->setAccessible(true); $id = $getNamespacedId->invoke($cache, 'test_key'); $filename = $getFilename->invoke($cache, $id); $data = ''; $lifetime = 0; $resource = fopen($filename, "r"); if (false !== ($line = fgets($resource))) { $lifetime = (integer) $line; } while (false !== ($line = fgets($resource))) { $data .= $line; } $this->assertNotEquals(0, $lifetime, "previous lifetime could not be loaded"); // update lifetime $lifetime = $lifetime - 20; file_put_contents($filename, $lifetime . PHP_EOL . $data); // test expired data $this->assertFalse($cache->contains('test_key')); $this->assertFalse($cache->fetch('test_key')); } public function testGetStats() { $cache = $this->_getCacheDriver(); $stats = $cache->getStats(); $this->assertNull($stats[Cache::STATS_HITS]); $this->assertNull($stats[Cache::STATS_MISSES]); $this->assertNull($stats[Cache::STATS_UPTIME]); $this->assertEquals(0, $stats[Cache::STATS_MEMORY_USAGE]); $this->assertGreaterThan(0, $stats[Cache::STATS_MEMORY_AVAILABLE]); } protected function _getCacheDriver() { return new FilesystemCache($this->directory); } } tests/Doctrine/Tests/Common/Cache/MemcacheCacheTest.php000064400000002623144760114440017021 0ustar00markTestSkipped('The ' . __CLASS__ .' requires the use of memcache'); } $this->memcache = new Memcache(); if (@$this->memcache->connect('localhost', 11211) === false) { unset($this->memcache); $this->markTestSkipped('The ' . __CLASS__ .' cannot connect to memcache'); } } public function tearDown() { if ($this->memcache instanceof Memcache) { $this->memcache->flush(); } } public function testNoExpire() { $cache = $this->_getCacheDriver(); $cache->save('noexpire', 'value', 0); sleep(1); $this->assertTrue($cache->contains('noexpire'), 'Memcache provider should support no-expire'); } public function testLongLifetime() { $cache = $this->_getCacheDriver(); $cache->save('key', 'value', 30 * 24 * 3600 + 1); $this->assertTrue($cache->contains('key'), 'Memcache provider should support TTL > 30 days'); } protected function _getCacheDriver() { $driver = new MemcacheCache(); $driver->setMemcache($this->memcache); return $driver; } } tests/Doctrine/Tests/Common/Cache/MemcachedCacheTest.php000064400000003557144760114440017174 0ustar00markTestSkipped('The ' . __CLASS__ .' requires the use of memcached'); } $this->memcached = new Memcached(); $this->memcached->setOption(Memcached::OPT_COMPRESSION, false); $this->memcached->addServer('127.0.0.1', 11211); if (@fsockopen('127.0.0.1', 11211) === false) { unset($this->memcached); $this->markTestSkipped('The ' . __CLASS__ .' cannot connect to memcache'); } } public function tearDown() { if ($this->memcached instanceof Memcached) { $this->memcached->flush(); } } public function testNoExpire() { $cache = $this->_getCacheDriver(); $cache->save('noexpire', 'value', 0); sleep(1); $this->assertTrue($cache->contains('noexpire'), 'Memcache provider should support no-expire'); } public function testLongLifetime() { $cache = $this->_getCacheDriver(); $cache->save('key', 'value', 30 * 24 * 3600 + 1); $this->assertTrue($cache->contains('key'), 'Memcache provider should support TTL > 30 days'); } protected function _getCacheDriver() { $driver = new MemcachedCache(); $driver->setMemcached($this->memcached); return $driver; } /** * {@inheritDoc} * * @dataProvider falseCastedValuesProvider */ public function testFalseCastedValues($value) { if (false === $value) { $this->markTestIncomplete('Memcached currently doesn\'t support saving `false` values. '); } parent::testFalseCastedValues($value); } } tests/Doctrine/Tests/Common/Cache/MongoDBCacheTest.php000064400000003071144760114440016602 0ustar00=')) { $this->markTestSkipped('The ' . __CLASS__ .' requires the use of mongo >= 1.3.0'); } $mongo = new MongoClient(); $this->collection = $mongo->selectCollection('doctrine_common_cache', 'test'); } public function tearDown() { if ($this->collection instanceof MongoCollection) { $this->collection->drop(); } } public function testSaveWithNonUtf8String() { // Invalid 2-octet sequence $data = "\xc3\x28"; $cache = $this->_getCacheDriver(); $this->assertTrue($cache->save('key', $data)); $this->assertEquals($data, $cache->fetch('key')); } public function testGetStats() { $cache = $this->_getCacheDriver(); $stats = $cache->getStats(); $this->assertNull($stats[Cache::STATS_HITS]); $this->assertNull($stats[Cache::STATS_MISSES]); $this->assertGreaterThan(0, $stats[Cache::STATS_UPTIME]); $this->assertEquals(0, $stats[Cache::STATS_MEMORY_USAGE]); $this->assertNull($stats[Cache::STATS_MEMORY_AVAILABLE]); } protected function _getCacheDriver() { return new MongoDBCache($this->collection); } } tests/Doctrine/Tests/Common/Cache/PhpFileCacheTest.php000064400000006755144760114440016660 0ustar00_getCacheDriver(); // Test save $cache->save('test_key', 'testing this out', 10); // Test contains to test that save() worked $this->assertTrue($cache->contains('test_key')); // Test fetch $this->assertEquals('testing this out', $cache->fetch('test_key')); // access private methods $getFilename = new \ReflectionMethod($cache, 'getFilename'); $getNamespacedId = new \ReflectionMethod($cache, 'getNamespacedId'); $getFilename->setAccessible(true); $getNamespacedId->setAccessible(true); $id = $getNamespacedId->invoke($cache, 'test_key'); $path = $getFilename->invoke($cache, $id); $value = include $path; // update lifetime $value['lifetime'] = $value['lifetime'] - 20; file_put_contents($path, 'assertFalse($cache->contains('test_key')); $this->assertFalse($cache->fetch('test_key')); } public function testImplementsSetState() { $cache = $this->_getCacheDriver(); // Test save $cache->save('test_set_state', new SetStateClass(array(1,2,3))); //Test __set_state call $this->assertCount(0, SetStateClass::$values); // Test fetch $value = $cache->fetch('test_set_state'); $this->assertInstanceOf('Doctrine\Tests\Common\Cache\SetStateClass', $value); $this->assertEquals(array(1,2,3), $value->getValue()); //Test __set_state call $this->assertCount(1, SetStateClass::$values); // Test contains $this->assertTrue($cache->contains('test_set_state')); } public function testNotImplementsSetState() { $cache = $this->_getCacheDriver(); $this->setExpectedException('InvalidArgumentException'); $cache->save('test_not_set_state', new NotSetStateClass(array(1,2,3))); } public function testGetStats() { $cache = $this->_getCacheDriver(); $stats = $cache->getStats(); $this->assertNull($stats[Cache::STATS_HITS]); $this->assertNull($stats[Cache::STATS_MISSES]); $this->assertNull($stats[Cache::STATS_UPTIME]); $this->assertEquals(0, $stats[Cache::STATS_MEMORY_USAGE]); $this->assertGreaterThan(0, $stats[Cache::STATS_MEMORY_AVAILABLE]); } public function testCachedObject() { $this->markTestSkipped("PhpFileCache cannot handle objects that don't implement __set_state."); } public function testFetchMultipleObjects() { $this->markTestSkipped("PhpFileCache cannot handle objects that don't implement __set_state."); } protected function _getCacheDriver() { return new PhpFileCache($this->directory); } } class NotSetStateClass { private $value; public function __construct($value) { $this->value = $value; } public function getValue() { return $this->value; } } class SetStateClass extends NotSetStateClass { public static $values = array(); public static function __set_state($data) { self::$values = $data; return new self($data['value']); } } tests/Doctrine/Tests/Common/Cache/PredisCacheTest.php000064400000003021144760114440016536 0ustar00markTestSkipped('Predis\Client is missing. Make sure to "composer install" to have all dev dependencies.'); } $this->client = new Client(); try { $this->client->connect(); } catch (ConnectionException $e) { $this->markTestSkipped('The ' . __CLASS__ .' requires the use of redis'); } } public function testHitMissesStatsAreProvided() { $cache = $this->_getCacheDriver(); $stats = $cache->getStats(); $this->assertNotNull($stats[Cache::STATS_HITS]); $this->assertNotNull($stats[Cache::STATS_MISSES]); } /** * @return PredisCache */ protected function _getCacheDriver() { return new PredisCache($this->client); } /** * {@inheritDoc} * * @dataProvider falseCastedValuesProvider */ public function testFalseCastedValues($value) { if (array() === $value) { $this->markTestIncomplete( 'Predis currently doesn\'t support saving empty array values. ' . 'See https://github.com/nrk/predis/issues/241' ); } parent::testFalseCastedValues($value); } } tests/Doctrine/Tests/Common/Cache/RedisCacheTest.php000064400000001776144760114440016375 0ustar00_redis = new \Redis(); $ok = @$this->_redis->connect('127.0.0.1'); if (!$ok) { $this->markTestSkipped('The ' . __CLASS__ .' requires the use of redis'); } } else { $this->markTestSkipped('The ' . __CLASS__ .' requires the use of redis'); } } public function testHitMissesStatsAreProvided() { $cache = $this->_getCacheDriver(); $stats = $cache->getStats(); $this->assertNotNull($stats[Cache::STATS_HITS]); $this->assertNotNull($stats[Cache::STATS_MISSES]); } protected function _getCacheDriver() { $driver = new RedisCache(); $driver->setRedis($this->_redis); return $driver; } } tests/Doctrine/Tests/Common/Cache/RiakCacheTest.php000064400000002400144760114440016176 0ustar00markTestSkipped('The ' . __CLASS__ .' requires the use of Riak'); } try { $this->connection = new Connection('127.0.0.1', 8087); $this->bucket = new Bucket($this->connection, 'test'); } catch (Exception\RiakException $e) { $this->markTestSkipped('The ' . __CLASS__ .' requires the use of Riak'); } } /** * {@inheritdoc} */ public function testGetStats() { $cache = $this->_getCacheDriver(); $stats = $cache->getStats(); $this->assertNull($stats); } /** * Retrieve RiakCache instance. * * @return \Doctrine\Common\Cache\RiakCache */ protected function _getCacheDriver() { return new RiakCache($this->bucket); } } tests/Doctrine/Tests/Common/Cache/SQLite3CacheTest.php000064400000002062144760114440016540 0ustar00file = tempnam(null, 'doctrine-cache-test-'); unlink($this->file); $this->sqlite = new SQLite3($this->file); } protected function tearDown() { $this->sqlite = null; // DB must be closed before unlink($this->file); } public function testGetStats() { $this->assertNull($this->_getCacheDriver()->getStats()); } public function testFetchSingle() { $id = uniqid('sqlite3_id_'); $data = "\0"; // produces null bytes in serialized format $this->_getCacheDriver()->save($id, $data, 30); $this->assertEquals($data, $this->_getCacheDriver()->fetch($id)); } protected function _getCacheDriver() { return new SQLite3Cache($this->sqlite, 'test_table'); } } tests/Doctrine/Tests/Common/Cache/VoidCacheTest.php000064400000002271144760114440016217 0ustar00assertFalse($cache->contains('foo')); $this->assertFalse($cache->contains('bar')); } public function testShouldAlwaysReturnFalseOnFetch() { $cache = new VoidCache(); $this->assertFalse($cache->fetch('foo')); $this->assertFalse($cache->fetch('bar')); } public function testShouldAlwaysReturnTrueOnSaveButNotStoreAnything() { $cache = new VoidCache(); $this->assertTrue($cache->save('foo', 'fooVal')); $this->assertFalse($cache->contains('foo')); $this->assertFalse($cache->fetch('foo')); } public function testShouldAlwaysReturnTrueOnDelete() { $cache = new VoidCache(); $this->assertTrue($cache->delete('foo')); } public function testShouldAlwaysReturnNullOnGetStatus() { $cache = new VoidCache(); $this->assertNull($cache->getStats()); } } tests/Doctrine/Tests/Common/Cache/WinCacheCacheTest.php000064400000000707144760114440017001 0ustar00markTestSkipped('The ' . __CLASS__ .' requires the use of Wincache'); } } protected function _getCacheDriver() { return new WincacheCache(); } }tests/Doctrine/Tests/Common/Cache/XcacheCacheTest.php000064400000000620144760114440016505 0ustar00markTestSkipped('The ' . __CLASS__ .' requires the use of xcache'); } } protected function _getCacheDriver() { return new XcacheCache(); } }tests/Doctrine/Tests/Common/Cache/ZendDataCacheTest.php000064400000001237144760114440017011 0ustar00markTestSkipped('The ' . __CLASS__ .' requires the use of Zend Data Cache which only works in apache2handler SAPI'); } } public function testGetStats() { $cache = $this->_getCacheDriver(); $stats = $cache->getStats(); $this->assertNull($stats); } protected function _getCacheDriver() { return new ZendDataCache(); } }tests/Doctrine/Tests/DoctrineTestCase.php000064400000000244144760114440014500 0ustar00add('Doctrine\\Tests\\', __DIR__ . '/../../'); unset($classLoader); tests/travis/php.ini000064400000000173144760114440010514 0ustar00extension="mongo.so" extension="memcache.so" extension="memcached.so" extension="redis.so" apc.enabled=1 apc.enable_cli=1 tests/travis/phpunit.travis.xml000064400000001613144760114440012744 0ustar00 ../Doctrine/ ../../lib/Doctrine/ performance