/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcCache.php |
@@ -0,0 +1,118 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
/** |
* APC cache provider. |
* |
* @link www.doctrine-project.org |
* @deprecated since version 1.6, use ApcuCache instead |
* @since 2.0 |
* @author Benjamin Eberlei <kontakt@beberlei.de> |
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> |
* @author Jonathan Wage <jonwage@gmail.com> |
* @author Roman Borschel <roman@code-factory.org> |
* @author David Abdemoulaie <dave@hobodave.com> |
*/ |
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 apc_store($id, $data, $lifeTime); |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doDelete($id) |
{ |
// apc_delete returns false if the id does not exist |
return apc_delete($id) || ! apc_exists($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 doSaveMultiple(array $keysAndValues, $lifetime = 0) |
{ |
$result = apc_store($keysAndValues, null, $lifetime); |
|
return empty($result); |
} |
|
/** |
* {@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'], |
); |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php |
@@ -0,0 +1,116 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
/** |
* Interface for cache drivers. |
* |
* @link www.doctrine-project.org |
* @since 2.0 |
* @author Benjamin Eberlei <kontakt@beberlei.de> |
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> |
* @author Jonathan Wage <jonwage@gmail.com> |
* @author Roman Borschel <roman@code-factory.org> |
* @author Fabio B. Silva <fabio.bat.silva@gmail.com> |
* @author Kévin Dunglas <dunglas@gmail.com> |
*/ |
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 bool TRUE if a cache entry exists for the given cache id, FALSE otherwise. |
*/ |
public function contains($id); |
|
/** |
* Puts data into the cache. |
* |
* If a cache entry with the given id already exists, its data will be replaced. |
* |
* @param string $id The cache id. |
* @param mixed $data The cache entry/data. |
* @param int $lifeTime The lifetime in number of seconds for this cache entry. |
* If zero (the default), the entry never expires (although it may be deleted from the cache |
* to make place for other entries). |
* |
* @return bool 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 bool TRUE if the cache entry was successfully deleted, FALSE otherwise. |
* Deleting a non-existing entry is considered successful. |
*/ |
public function delete($id); |
|
/** |
* Retrieves cached information from the data store. |
* |
* The server's statistics array has the following values: |
* |
* - <b>hits</b> |
* Number of keys that have been requested and found present. |
* |
* - <b>misses</b> |
* Number of items that have been requested and not found. |
* |
* - <b>uptime</b> |
* Time that the server is running. |
* |
* - <b>memory_usage</b> |
* Memory used by this server to store items. |
* |
* - <b>memory_available</b> |
* 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(); |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php |
@@ -0,0 +1,312 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
/** |
* Base class for cache provider implementations. |
* |
* @since 2.2 |
* @author Benjamin Eberlei <kontakt@beberlei.de> |
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> |
* @author Jonathan Wage <jonwage@gmail.com> |
* @author Roman Borschel <roman@code-factory.org> |
* @author Fabio B. Silva <fabio.bat.silva@gmail.com> |
*/ |
abstract class CacheProvider implements Cache, FlushableCache, ClearableCache, MultiGetCache, MultiPutCache |
{ |
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) |
{ |
if (empty($keys)) { |
return array(); |
} |
|
// 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]) || array_key_exists($namespacedKey, $items)) { |
$foundItems[$requestedKey] = $items[$namespacedKey]; |
} |
} |
|
return $foundItems; |
} |
|
/** |
* {@inheritdoc} |
*/ |
public function saveMultiple(array $keysAndValues, $lifetime = 0) |
{ |
$namespacedKeysAndValues = array(); |
foreach ($keysAndValues as $key => $value) { |
$namespacedKeysAndValues[$this->getNamespacedId($key)] = $value; |
} |
|
return $this->doSaveMultiple($namespacedKeysAndValues, $lifetime); |
} |
|
/** |
* {@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; |
|
if ($this->doSave($namespaceCacheKey, $namespaceVersion)) { |
$this->namespaceVersion = $namespaceVersion; |
|
return true; |
} |
|
return false; |
} |
|
/** |
* 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(); |
$this->namespaceVersion = $this->doFetch($namespaceCacheKey) ?: 1; |
|
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 $key) { |
if (false !== ($item = $this->doFetch($key)) || $this->doContains($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|false 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 bool TRUE if a cache entry exists for the given cache id, FALSE otherwise. |
*/ |
abstract protected function doContains($id); |
|
/** |
* Default implementation of doSaveMultiple. Each driver that supports multi-put should override it. |
* |
* @param array $keysAndValues Array of keys and values to save in cache |
* @param int $lifetime The lifetime. If != 0, sets a specific lifetime for these |
* cache entries (0 => infinite lifeTime). |
* |
* @return bool TRUE if the operation was successful, FALSE if it wasn't. |
*/ |
protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) |
{ |
$success = true; |
|
foreach ($keysAndValues as $key => $value) { |
if (!$this->doSave($key, $value, $lifetime)) { |
$success = false; |
} |
} |
|
return $success; |
} |
|
/** |
* 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 bool 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 bool TRUE if the cache entry was successfully deleted, FALSE otherwise. |
*/ |
abstract protected function doDelete($id); |
|
/** |
* Flushes all cache entries. |
* |
* @return bool 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(); |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ChainCache.php |
@@ -0,0 +1,147 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
/** |
* Cache provider that allows to easily chain multiple cache providers |
* |
* @author Michaël Gallego <mic.gallego@gmail.com> |
*/ |
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; |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseCache.php |
@@ -0,0 +1,121 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
use \Couchbase; |
|
/** |
* Couchbase cache provider. |
* |
* @link www.doctrine-project.org |
* @since 2.4 |
* @author Michael Nitschinger <michael@nitschinger.at> |
*/ |
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'], |
); |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php |
@@ -0,0 +1,286 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
/** |
* Base file cache driver. |
* |
* @since 2.3 |
* @author Fabio B. Silva <fabio.bat.silva@gmail.com> |
* @author Tobias Schultze <http://tobion.de> |
*/ |
abstract class FileCache extends CacheProvider |
{ |
/** |
* The cache directory. |
* |
* @var string |
*/ |
protected $directory; |
|
/** |
* The cache file extension. |
* |
* @var string |
*/ |
private $extension; |
|
/** |
* @var int |
*/ |
private $umask; |
|
/** |
* @var int |
*/ |
private $directoryStringLength; |
|
/** |
* @var int |
*/ |
private $extensionStringLength; |
|
/** |
* @var bool |
*/ |
private $isRunningOnWindows; |
|
/** |
* 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; |
|
$this->directoryStringLength = strlen($this->directory); |
$this->extensionStringLength = strlen($this->extension); |
$this->isRunningOnWindows = defined('PHP_WINDOWS_VERSION_BUILD'); |
} |
|
/** |
* Gets the cache directory. |
* |
* @return string |
*/ |
public function getDirectory() |
{ |
return $this->directory; |
} |
|
/** |
* Gets the cache file extension. |
* |
* @return string |
*/ |
public function getExtension() |
{ |
return $this->extension; |
} |
|
/** |
* @param string $id |
* |
* @return string |
*/ |
protected function getFilename($id) |
{ |
$hash = hash('sha256', $id); |
|
// This ensures that the filename is unique and that there are no invalid chars in it. |
if ( |
'' === $id |
|| ((strlen($id) * 2 + $this->extensionStringLength) > 255) |
|| ($this->isRunningOnWindows && ($this->directoryStringLength + 4 + strlen($id) * 2 + $this->extensionStringLength) > 258) |
) { |
// Most filesystems have a limit of 255 chars for each path component. On Windows the the whole path is limited |
// to 260 chars (including terminating null char). Using long UNC ("\\?\" prefix) does not work with the PHP API. |
// And there is a bug in PHP (https://bugs.php.net/bug.php?id=70943) with path lengths of 259. |
// So if the id in hex representation would surpass the limit, we use the hash instead. The prefix prevents |
// collisions between the hash and bin2hex. |
$filename = '_' . $hash; |
} else { |
$filename = bin2hex($id); |
} |
|
return $this->directory |
. DIRECTORY_SEPARATOR |
. substr($hash, 0, 2) |
. DIRECTORY_SEPARATOR |
. $filename |
. $this->extension; |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doDelete($id) |
{ |
$filename = $this->getFilename($id); |
|
return @unlink($filename) || ! file_exists($filename); |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doFlush() |
{ |
foreach ($this->getIterator() as $name => $file) { |
if ($file->isDir()) { |
// Remove the intermediate directories which have been created to balance the tree. It only takes effect |
// if the directory is empty. If several caches share the same directory but with different file extensions, |
// the other ones are not removed. |
@rmdir($name); |
} elseif ($this->isFilenameEndingWithExtension($name)) { |
// If an extension is set, only remove files which end with the given extension. |
// If no extension is set, we have no other choice than removing everything. |
@unlink($name); |
} |
} |
|
return true; |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doGetStats() |
{ |
$usage = 0; |
foreach ($this->getIterator() as $name => $file) { |
if (! $file->isDir() && $this->isFilenameEndingWithExtension($name)) { |
$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 \RecursiveIteratorIterator( |
new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), |
\RecursiveIteratorIterator::CHILD_FIRST |
); |
} |
|
/** |
* @param string $name The filename |
* |
* @return bool |
*/ |
private function isFilenameEndingWithExtension($name) |
{ |
return '' === $this->extension |
|| strrpos($name, $this->extension) === (strlen($name) - $this->extensionStringLength); |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcacheCache.php |
@@ -0,0 +1,126 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
use \Memcache; |
|
/** |
* Memcache cache provider. |
* |
* @link www.doctrine-project.org |
* @since 2.0 |
* @author Benjamin Eberlei <kontakt@beberlei.de> |
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> |
* @author Jonathan Wage <jonwage@gmail.com> |
* @author Roman Borschel <roman@code-factory.org> |
* @author David Abdemoulaie <dave@hobodave.com> |
*/ |
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) |
{ |
// Memcache::delete() returns false if entry does not exist |
return $this->memcache->delete($id) || ! $this->doContains($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'], |
); |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcachedCache.php |
@@ -0,0 +1,146 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
use \Memcached; |
|
/** |
* Memcached cache provider. |
* |
* @link www.doctrine-project.org |
* @since 2.2 |
* @author Benjamin Eberlei <kontakt@beberlei.de> |
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> |
* @author Jonathan Wage <jonwage@gmail.com> |
* @author Roman Borschel <roman@code-factory.org> |
* @author David Abdemoulaie <dave@hobodave.com> |
*/ |
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 doSaveMultiple(array $keysAndValues, $lifetime = 0) |
{ |
if ($lifetime > 30 * 24 * 3600) { |
$lifetime = time() + $lifetime; |
} |
|
return $this->memcached->setMulti($keysAndValues, $lifetime); |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doContains($id) |
{ |
return false !== $this->memcached->get($id) |
|| $this->memcached->getResultCode() !== Memcached::RES_NOTFOUND; |
} |
|
/** |
* {@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) |
|| $this->memcached->getResultCode() === Memcached::RES_NOTFOUND; |
} |
|
/** |
* {@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'], |
); |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MongoDBCache.php |
@@ -0,0 +1,197 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
use MongoBinData; |
use MongoCollection; |
use MongoCursorException; |
use MongoDate; |
|
/** |
* MongoDB cache provider. |
* |
* @since 1.1 |
* @author Jeremy Mikola <jmikola@gmail.com> |
*/ |
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 with 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) |
{ |
try { |
$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) |
); |
} catch (MongoCursorException $e) { |
return false; |
} |
|
return isset($result['ok']) ? $result['ok'] == 1 : true; |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doDelete($id) |
{ |
$result = $this->collection->remove(array('_id' => $id)); |
|
return isset($result['ok']) ? $result['ok'] == 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']) ? (int) $serverStatus['uptime'] : null), |
Cache::STATS_MEMORY_USAGE => (isset($collStats['size']) ? (int) $collStats['size'] : null), |
Cache::STATS_MEMORY_AVAILABLE => null, |
); |
} |
|
/** |
* Check if the document is expired. |
* |
* @param array $document |
* |
* @return bool |
*/ |
private function isExpired(array $document) |
{ |
return isset($document[self::EXPIRATION_FIELD]) && |
$document[self::EXPIRATION_FIELD] instanceof MongoDate && |
$document[self::EXPIRATION_FIELD]->sec < time(); |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/RedisCache.php |
@@ -0,0 +1,180 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
use Redis; |
|
/** |
* Redis cache provider. |
* |
* @link www.doctrine-project.org |
* @since 2.2 |
* @author Osman Ungur <osmanungur@gmail.com> |
*/ |
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) |
{ |
$fetchedItems = array_combine($keys, $this->redis->mget($keys)); |
|
// Redis mget returns false for keys that do not exist. So we need to filter those out unless it's the real data. |
$foundItems = array(); |
|
foreach ($fetchedItems as $key => $value) { |
if (false !== $value || $this->redis->exists($key)) { |
$foundItems[$key] = $value; |
} |
} |
|
return $foundItems; |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) |
{ |
if ($lifetime) { |
$success = true; |
|
// Keys have lifetime, use SETEX for each of them |
foreach ($keysAndValues as $key => $value) { |
if (!$this->redis->setex($key, $lifetime, $value)) { |
$success = false; |
} |
} |
|
return $success; |
} |
|
// No lifetime, use MSET |
return (bool) $this->redis->mset($keysAndValues); |
} |
|
/** |
* {@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; |
} |
|
if (defined('Redis::SERIALIZER_IGBINARY') && extension_loaded('igbinary')) { |
return Redis::SERIALIZER_IGBINARY; |
} |
|
return Redis::SERIALIZER_PHP; |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/RiakCache.php |
@@ -0,0 +1,250 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
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 <guilhermeblanco@hotmail.com> |
*/ |
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 bool |
*/ |
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; |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/SQLite3Cache.php |
@@ -0,0 +1,220 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
use SQLite3; |
use SQLite3Result; |
|
/** |
* SQLite3 cache provider. |
* |
* @since 1.4 |
* @author Jake Bell <jake@theunraveler.com> |
*/ |
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 null !== $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 bool $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 bool |
*/ |
private function isExpired(array $item) |
{ |
return isset($item[static::EXPIRATION_FIELD]) && |
$item[self::EXPIRATION_FIELD] !== null && |
$item[self::EXPIRATION_FIELD] < time(); |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/WinCacheCache.php |
@@ -0,0 +1,109 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
/** |
* WinCache cache provider. |
* |
* @link www.doctrine-project.org |
* @since 2.2 |
* @author Benjamin Eberlei <kontakt@beberlei.de> |
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> |
* @author Jonathan Wage <jonwage@gmail.com> |
* @author Roman Borschel <roman@code-factory.org> |
* @author David Abdemoulaie <dave@hobodave.com> |
*/ |
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 wincache_ucache_set($id, $data, $lifeTime); |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doDelete($id) |
{ |
return wincache_ucache_delete($id); |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doFlush() |
{ |
return wincache_ucache_clear(); |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doFetchMultiple(array $keys) |
{ |
return wincache_ucache_get($keys); |
} |
|
/** |
* {@inheritdoc} |
*/ |
protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) |
{ |
$result = wincache_ucache_set($keysAndValues, null, $lifetime); |
|
return empty($result); |
} |
|
/** |
* {@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'], |
); |
} |
} |
/vendor/doctrine/cache/lib/Doctrine/Common/Cache/XcacheCache.php |
@@ -0,0 +1,112 @@ |
<?php |
/* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* This software consists of voluntary contributions made by many individuals |
* and is licensed under the MIT license. For more information, see |
* <http://www.doctrine-project.org>. |
*/ |
|
namespace Doctrine\Common\Cache; |
|
/** |
* Xcache cache driver. |
* |
* @link www.doctrine-project.org |
* @since 2.0 |
* @author Benjamin Eberlei <kontakt@beberlei.de> |
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> |
* @author Jonathan Wage <jonwage@gmail.com> |
* @author Roman Borschel <roman@code-factory.org> |
* @author David Abdemoulaie <dave@hobodave.com> |
*/ |
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'], |
); |
} |
} |
/vendor/doctrine/cache/tests/Doctrine/Tests/Common/Cache/BaseFileCacheTest.php |
@@ -0,0 +1,155 @@ |
<?php |
|
namespace Doctrine\Tests\Common\Cache; |
|
use Doctrine\Common\Cache\FileCache; |
use RecursiveDirectoryIterator; |
use RecursiveIteratorIterator; |
|
abstract class BaseFileCacheTest extends CacheTest |
{ |
protected $directory; |
|
protected function setUp() |
{ |
do { |
$this->directory = sys_get_temp_dir() . '/doctrine_cache_'. uniqid(); |
} while (file_exists($this->directory)); |
} |
|
protected 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()); |
} |
} |
|
@rmdir($this->directory); |
} |
|
public function testFlushAllRemovesBalancingDirectories() |
{ |
$cache = $this->_getCacheDriver(); |
|
$this->assertTrue($cache->save('key1', 1)); |
$this->assertTrue($cache->save('key2', 2)); |
$this->assertTrue($cache->flushAll()); |
|
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST); |
|
$this->assertCount(0, $iterator); |
} |
|
protected function isSharedStorage() |
{ |
return false; |
} |
|
public function getPathLengthsToTest() |
{ |
// Windows officially supports 260 bytes including null terminator |
// 258 bytes available to use due to php bug #70943 |
// Windows officially supports 260 bytes including null terminator |
// 259 characters is too large due to PHP bug (https://bugs.php.net/bug.php?id=70943) |
// 260 characters is too large - null terminator is included in allowable length |
return array( |
array(257, false), |
array(258, false), |
array(259, true), |
array(260, true) |
); |
} |
|
private static function getBasePathForWindowsPathLengthTests($pathLength) |
{ |
return FileCacheTest::getBasePathForWindowsPathLengthTests($pathLength); |
} |
|
/** |
* @param int $length |
* @param string $basePath |
* |
* @return array |
*/ |
private static function getKeyAndPathFittingLength($length, $basePath) |
{ |
$baseDirLength = strlen($basePath); |
$extensionLength = strlen('.doctrine.cache'); |
$directoryLength = strlen(DIRECTORY_SEPARATOR . 'aa' . DIRECTORY_SEPARATOR); |
$namespaceAndBracketLength = strlen(bin2hex("[][1]")); |
$keyLength = $length |
- ($baseDirLength |
+ $extensionLength |
+ $directoryLength |
+ $namespaceAndBracketLength); |
|
$key = str_repeat('a', floor($keyLength / 2)); |
$namespacedKey = '[' . $key . '][1]'; |
|
$keyHash = hash('sha256', $namespacedKey); |
|
$keyPath = $basePath |
. DIRECTORY_SEPARATOR |
. substr($keyHash, 0, 2) |
. DIRECTORY_SEPARATOR |
. bin2hex($namespacedKey) |
. '.doctrine.cache'; |
|
$hashedKeyPath = $basePath |
. DIRECTORY_SEPARATOR |
. substr($keyHash, 0, 2) |
. DIRECTORY_SEPARATOR |
. '_' . $keyHash |
. '.doctrine.cache'; |
|
return array($key, $keyPath, $hashedKeyPath); |
} |
|
/** |
* @dataProvider getPathLengthsToTest |
* |
* @param int $length |
* @param bool $pathShouldBeHashed |
*/ |
public function testWindowsPathLengthLimitIsCorrectlyHandled($length, $pathShouldBeHashed) |
{ |
$this->directory = self::getBasePathForWindowsPathLengthTests($length); |
|
list($key, $keyPath, $hashedKeyPath) = self::getKeyAndPathFittingLength($length, $this->directory); |
|
$this->assertEquals($length, strlen($keyPath), 'Unhashed path should be of correct length.'); |
|
$cacheClass = get_class($this->_getCacheDriver()); |
/* @var $cache \Doctrine\Common\Cache\FileCache */ |
$cache = new $cacheClass($this->directory, '.doctrine.cache'); |
|
// Trick it into thinking this is windows. |
$reflClass = new \ReflectionClass(FileCache::class); |
$reflProp = $reflClass->getProperty('isRunningOnWindows'); |
$reflProp->setAccessible(true); |
$reflProp->setValue($cache, true); |
$reflProp->setAccessible(false); |
|
$value = uniqid('value', true); |
|
$cache->save($key, $value); |
$this->assertEquals($value, $cache->fetch($key)); |
|
if ($pathShouldBeHashed) { |
$this->assertFileExists($hashedKeyPath, 'Path generated for key should be hashed.'); |
unlink($hashedKeyPath); |
} else { |
$this->assertFileExists($keyPath, 'Path generated for key should not be hashed.'); |
unlink($keyPath); |
} |
} |
} |
/vendor/doctrine/cache/tests/Doctrine/Tests/Common/Cache/CacheTest.php |
@@ -0,0 +1,463 @@ |
<?php |
|
namespace Doctrine\Tests\Common\Cache; |
|
use Doctrine\Common\Cache\Cache; |
use ArrayObject; |
|
abstract class CacheTest extends \Doctrine\Tests\DoctrineTestCase |
{ |
/** |
* @dataProvider provideDataToCache |
*/ |
public function testSetContainsFetchDelete($value) |
{ |
$cache = $this->_getCacheDriver(); |
|
// Test saving a value, checking if it exists, and fetching it back |
$this->assertTrue($cache->save('key', $value)); |
$this->assertTrue($cache->contains('key')); |
if (is_object($value)) { |
$this->assertEquals($value, $cache->fetch('key'), 'Objects retrieved from the cache must be equal but not necessarily the same reference'); |
} else { |
$this->assertSame($value, $cache->fetch('key'), 'Scalar and array data retrieved from the cache must be the same as the original, e.g. same type'); |
} |
|
// Test deleting a value |
$this->assertTrue($cache->delete('key')); |
$this->assertFalse($cache->contains('key')); |
$this->assertFalse($cache->fetch('key')); |
} |
|
/** |
* @dataProvider provideDataToCache |
*/ |
public function testUpdateExistingEntry($value) |
{ |
$cache = $this->_getCacheDriver(); |
|
$this->assertTrue($cache->save('key', 'old-value')); |
$this->assertTrue($cache->contains('key')); |
|
$this->assertTrue($cache->save('key', $value)); |
$this->assertTrue($cache->contains('key')); |
if (is_object($value)) { |
$this->assertEquals($value, $cache->fetch('key'), 'Objects retrieved from the cache must be equal but not necessarily the same reference'); |
} else { |
$this->assertSame($value, $cache->fetch('key'), 'Scalar and array data retrieved from the cache must be the same as the original, e.g. same type'); |
} |
} |
|
public function testCacheKeyIsCaseSensitive() |
{ |
$cache = $this->_getCacheDriver(); |
|
$this->assertTrue($cache->save('key', 'value')); |
$this->assertTrue($cache->contains('key')); |
$this->assertSame('value', $cache->fetch('key')); |
|
$this->assertFalse($cache->contains('KEY')); |
$this->assertFalse($cache->fetch('KEY')); |
|
$cache->delete('KEY'); |
$this->assertTrue($cache->contains('key', 'Deleting cache item with different case must not affect other cache item')); |
} |
|
public function testFetchMultiple() |
{ |
$cache = $this->_getCacheDriver(); |
$values = $this->provideDataToCache(); |
$saved = array(); |
|
foreach ($values as $key => $value) { |
$cache->save($key, $value[0]); |
|
$saved[$key] = $value[0]; |
} |
|
$keys = array_keys($saved); |
|
$this->assertEquals( |
$saved, |
$cache->fetchMultiple($keys), |
'Testing fetchMultiple with different data types' |
); |
$this->assertEquals( |
array_slice($saved, 0, 1), |
$cache->fetchMultiple(array_slice($keys, 0, 1)), |
'Testing fetchMultiple with a single key' |
); |
|
$keysWithNonExisting = array(); |
$keysWithNonExisting[] = 'non_existing1'; |
$keysWithNonExisting[] = $keys[0]; |
$keysWithNonExisting[] = 'non_existing2'; |
$keysWithNonExisting[] = $keys[1]; |
$keysWithNonExisting[] = 'non_existing3'; |
|
$this->assertEquals( |
array_slice($saved, 0, 2), |
$cache->fetchMultiple($keysWithNonExisting), |
'Testing fetchMultiple with a subset of keys and mixed with non-existing ones' |
); |
} |
|
public function testFetchMultipleWithNoKeys() |
{ |
$cache = $this->_getCacheDriver(); |
|
$this->assertSame(array(), $cache->fetchMultiple(array())); |
} |
|
public function testSaveMultiple() |
{ |
$cache = $this->_getCacheDriver(); |
$cache->deleteAll(); |
|
$data = array_map(function ($value) { |
return $value[0]; |
}, $this->provideDataToCache()); |
|
$this->assertTrue($cache->saveMultiple($data)); |
|
$keys = array_keys($data); |
|
$this->assertEquals($data, $cache->fetchMultiple($keys)); |
} |
|
public function provideDataToCache() |
{ |
$obj = new \stdClass(); |
$obj->foo = 'bar'; |
$obj2 = new \stdClass(); |
$obj2->bar = 'foo'; |
$obj2->obj = $obj; |
$obj->obj2 = $obj2; |
|
return array( |
'array' => array(array('one', 2, 3.01)), |
'string' => array('value'), |
'string_invalid_utf8' => array("\xc3\x28"), |
'string_null_byte' => array('with'."\0".'null char'), |
'integer' => array(1), |
'float' => array(1.5), |
'object' => array(new ArrayObject(array('one', 2, 3.01))), |
'object_recursive' => array($obj), |
'true' => array(true), |
// the following are considered FALSE in boolean context, but caches should still recognize their existence |
'null' => array(null), |
'false' => array(false), |
'array_empty' => array(array()), |
'string_zero' => array('0'), |
'integer_zero' => array(0), |
'float_zero' => array(0.0), |
'string_empty' => array(''), |
); |
} |
|
public function testDeleteIsSuccessfulWhenKeyDoesNotExist() |
{ |
$cache = $this->_getCacheDriver(); |
|
$cache->delete('key'); |
$this->assertFalse($cache->contains('key')); |
$this->assertTrue($cache->delete('key')); |
} |
|
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')); |
} |
|
/** |
* @dataProvider provideCacheIds |
*/ |
public function testCanHandleSpecialCacheIds($id) |
{ |
$cache = $this->_getCacheDriver(); |
|
$this->assertTrue($cache->save($id, 'value')); |
$this->assertTrue($cache->contains($id)); |
$this->assertEquals('value', $cache->fetch($id)); |
|
$this->assertTrue($cache->delete($id)); |
$this->assertFalse($cache->contains($id)); |
$this->assertFalse($cache->fetch($id)); |
} |
|
public function testNoCacheIdCollisions() |
{ |
$cache = $this->_getCacheDriver(); |
|
$ids = $this->provideCacheIds(); |
|
// fill cache with each id having a different value |
foreach ($ids as $index => $id) { |
$cache->save($id[0], $index); |
} |
|
// then check value of each cache id |
foreach ($ids as $index => $id) { |
$value = $cache->fetch($id[0]); |
$this->assertNotFalse($value, sprintf('Failed to retrieve data for cache id "%s".', $id[0])); |
if ($index !== $value) { |
$this->fail(sprintf('Cache id "%s" collides with id "%s".', $id[0], $ids[$value][0])); |
} |
} |
} |
|
/** |
* Returns cache ids with special characters that should still work. |
* |
* For example, the characters :\/<>"*?| are not valid in Windows filenames. So they must be encoded properly. |
* Each cache id should be considered different from the others. |
* |
* @return array |
*/ |
public function provideCacheIds() |
{ |
return array( |
array(':'), |
array('\\'), |
array('/'), |
array('<'), |
array('>'), |
array('"'), |
array('*'), |
array('?'), |
array('|'), |
array('['), |
array(']'), |
array('ä'), |
array('a'), |
array('é'), |
array('e'), |
array('.'), // directory traversal |
array('..'), // directory traversal |
array('-'), |
array('_'), |
array('$'), |
array('%'), |
array(' '), |
array("\0"), |
array(''), |
array(str_repeat('a', 300)), // long key |
array(str_repeat('a', 113)), |
); |
} |
|
public function testLifetime() |
{ |
$cache = $this->_getCacheDriver(); |
$cache->save('expire', 'value', 1); |
$this->assertTrue($cache->contains('expire'), 'Data should not be expired yet'); |
// @TODO should more TTL-based tests pop up, so then we should mock the `time` API instead |
sleep(2); |
$this->assertFalse($cache->contains('expire'), 'Data should be expired'); |
} |
|
public function testNoExpire() |
{ |
$cache = $this->_getCacheDriver(); |
$cache->save('noexpire', 'value', 0); |
// @TODO should more TTL-based tests pop up, so then we should mock the `time` API instead |
sleep(1); |
$this->assertTrue($cache->contains('noexpire'), 'Data with lifetime of zero should not expire'); |
} |
|
public function testLongLifetime() |
{ |
$cache = $this->_getCacheDriver(); |
$cache->save('longlifetime', 'value', 30 * 24 * 3600 + 1); |
$this->assertTrue($cache->contains('longlifetime'), 'Data with lifetime > 30 days should be accepted'); |
} |
|
public function testDeleteAllAndNamespaceVersioningBetweenCaches() |
{ |
if ( ! $this->isSharedStorage()) { |
$this->markTestSkipped('The cache storage needs to be shared.'); |
} |
|
$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 cache storage needs to be shared.'); |
} |
|
$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 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')); |
|
/* 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 testSaveReturnsTrueWithAndWithoutTTlSet() |
{ |
$cache = $this->_getCacheDriver(); |
$cache->deleteAll(); |
$this->assertTrue($cache->save('without_ttl', 'without_ttl')); |
$this->assertTrue($cache->save('with_ttl', 'with_ttl', 3600)); |
} |
|
/** |
* Return whether multiple cache providers share the same storage. |
* |
* This is used for skipping certain tests for shared storage behavior. |
* |
* @return bool |
*/ |
protected function isSharedStorage() |
{ |
return true; |
} |
|
/** |
* @return \Doctrine\Common\Cache\CacheProvider |
*/ |
abstract protected function _getCacheDriver(); |
} |
/vendor/doctrine/cache/tests/Doctrine/Tests/Common/Cache/FileCacheTest.php |
@@ -0,0 +1,268 @@ |
<?php |
|
namespace Doctrine\Tests\Common\Cache; |
|
use Doctrine\Common\Cache\Cache; |
|
/** |
* @group DCOM-101 |
*/ |
class FileCacheTest extends \Doctrine\Tests\DoctrineTestCase |
{ |
/** |
* @var \Doctrine\Common\Cache\FileCache |
*/ |
private $driver; |
|
protected function setUp() |
{ |
$this->driver = $this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array(), '', false |
); |
} |
|
public function testFilenameShouldCreateThePathWithOneSubDirectory() |
{ |
$cache = $this->driver; |
$method = new \ReflectionMethod($cache, 'getFilename'); |
$key = 'item-key'; |
$expectedDir = array( |
'84', |
); |
$expectedDir = implode(DIRECTORY_SEPARATOR, $expectedDir); |
|
$method->setAccessible(true); |
|
$path = $method->invoke($cache, $key); |
$dirname = pathinfo($path, PATHINFO_DIRNAME); |
|
$this->assertEquals(DIRECTORY_SEPARATOR . $expectedDir, $dirname); |
} |
|
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__ . '/../', DIRECTORY_SEPARATOR . basename(__FILE__)) |
); |
|
$doGetStats = new \ReflectionMethod($driver, 'doGetStats'); |
|
$doGetStats->setAccessible(true); |
|
$stats = $doGetStats->invoke($driver); |
|
$this->assertGreaterThan(0, $stats[Cache::STATS_MEMORY_USAGE]); |
} |
|
public function testNonIntUmaskThrowsInvalidArgumentException() |
{ |
$this->setExpectedException('InvalidArgumentException'); |
|
$this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array('', '', 'invalid') |
); |
} |
|
public function testGetDirectoryReturnsRealpathDirectoryString() |
{ |
$directory = __DIR__ . '/../'; |
$driver = $this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array($directory) |
); |
|
$doGetDirectory = new \ReflectionMethod($driver, 'getDirectory'); |
|
$actualDirectory = $doGetDirectory->invoke($driver); |
$expectedDirectory = realpath($directory); |
|
$this->assertEquals($expectedDirectory, $actualDirectory); |
} |
|
public function testGetExtensionReturnsExtensionString() |
{ |
$directory = __DIR__ . '/../'; |
$extension = DIRECTORY_SEPARATOR . basename(__FILE__); |
$driver = $this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array($directory, $extension) |
); |
|
$doGetExtension = new \ReflectionMethod($driver, 'getExtension'); |
|
$actualExtension = $doGetExtension->invoke($driver); |
|
$this->assertEquals($extension, $actualExtension); |
} |
|
const WIN_MAX_PATH_LEN = 258; |
|
public static function getBasePathForWindowsPathLengthTests($pathLength) |
{ |
// Not using __DIR__ because it can get screwed up when xdebug debugger is attached. |
$basePath = realpath(sys_get_temp_dir()) . '/' . uniqid('doctrine-cache', true); |
|
/** @noinspection MkdirRaceConditionInspection */ |
@mkdir($basePath); |
|
$basePath = realpath($basePath); |
|
// Test whether the desired path length is odd or even. |
$desiredPathLengthIsOdd = ($pathLength % 2) == 1; |
|
// If the cache key is not too long, the filecache codepath will add |
// a slash and bin2hex($key). The length of the added portion will be an odd number. |
// len(desired) = len(base path) + len(slash . bin2hex($key)) |
// odd = even + odd |
// even = odd + odd |
$basePathLengthShouldBeOdd = !$desiredPathLengthIsOdd; |
|
$basePathLengthIsOdd = (strlen($basePath) % 2) == 1; |
|
// If the base path needs to be odd or even where it is not, we add an odd number of |
// characters as a pad. In this case, we're adding '\aa' (or '/aa' depending on platform) |
// This is all to make it so that the key we're testing would result in |
// a path that is exactly the length we want to test IF the path length limit |
// were not in place in FileCache. |
if ($basePathLengthIsOdd != $basePathLengthShouldBeOdd) { |
$basePath .= DIRECTORY_SEPARATOR . "aa"; |
} |
|
return $basePath; |
} |
|
/** |
* @param int $length |
* @param string $basePath |
* |
* @return array |
*/ |
public static function getKeyAndPathFittingLength($length, $basePath) |
{ |
$baseDirLength = strlen($basePath); |
$extensionLength = strlen('.doctrine.cache'); |
$directoryLength = strlen(DIRECTORY_SEPARATOR . 'aa' . DIRECTORY_SEPARATOR); |
$keyLength = $length - ($baseDirLength + $extensionLength + $directoryLength); // - 1 because of slash |
|
$key = str_repeat('a', floor($keyLength / 2)); |
|
$keyHash = hash('sha256', $key); |
|
$keyPath = $basePath |
. DIRECTORY_SEPARATOR |
. substr($keyHash, 0, 2) |
. DIRECTORY_SEPARATOR |
. bin2hex($key) |
. '.doctrine.cache'; |
|
$hashedKeyPath = $basePath |
. DIRECTORY_SEPARATOR |
. substr($keyHash, 0, 2) |
. DIRECTORY_SEPARATOR |
. '_' . $keyHash |
. '.doctrine.cache'; |
|
return array($key, $keyPath, $hashedKeyPath); |
} |
|
public function getPathLengthsToTest() |
{ |
// Windows officially supports 260 bytes including null terminator |
// 259 characters is too large due to PHP bug (https://bugs.php.net/bug.php?id=70943) |
// 260 characters is too large - null terminator is included in allowable length |
return array( |
array(257, false), |
array(258, false), |
array(259, true), |
array(260, true) |
); |
} |
|
/** |
* @runInSeparateProcess |
* @dataProvider getPathLengthsToTest |
* |
* @covers \Doctrine\Common\Cache\FileCache::getFilename |
* |
* @param int $length |
* @param bool $pathShouldBeHashed |
*/ |
public function testWindowsPathLengthLimitationsAreCorrectlyRespected($length, $pathShouldBeHashed) |
{ |
if (! defined('PHP_WINDOWS_VERSION_BUILD')) { |
define('PHP_WINDOWS_VERSION_BUILD', 'Yes, this is the "usual suspect", with the usual limitations'); |
} |
|
$basePath = self::getBasePathForWindowsPathLengthTests($length); |
|
$fileCache = $this->getMockForAbstractClass( |
'Doctrine\Common\Cache\FileCache', |
array($basePath, '.doctrine.cache') |
); |
|
list($key, $keyPath, $hashedKeyPath) = self::getKeyAndPathFittingLength($length, $basePath); |
|
$getFileName = new \ReflectionMethod($fileCache, 'getFilename'); |
|
$getFileName->setAccessible(true); |
|
$this->assertEquals( |
$length, |
strlen($keyPath), |
sprintf('Path expected to be %d characters long is %d characters long', $length, strlen($keyPath)) |
); |
|
if ($pathShouldBeHashed) { |
$keyPath = $hashedKeyPath; |
} |
|
if ($pathShouldBeHashed) { |
$this->assertSame( |
$hashedKeyPath, |
$getFileName->invoke($fileCache, $key), |
'Keys should be hashed correctly if they are over the limit.' |
); |
} else { |
$this->assertSame( |
$keyPath, |
$getFileName->invoke($fileCache, $key), |
'Keys below limit of the allowed length are used directly, unhashed' |
); |
} |
} |
} |