/concrete/vendor/zendframework/zend-cache/src/Storage/Adapter/Redis.php
PHP | 435 lines | 238 code | 44 blank | 153 comment | 15 complexity | 782b3e6b4f5d6a56d88acf1f78960ec9 MD5 | raw file
- <?php
- /**
- * Zend Framework (http://framework.zend.com/)
- *
- * @link http://github.com/zendframework/zf2 for the canonical source repository
- * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
- namespace Zend\Cache\Storage\Adapter;
- use Redis as RedisResource;
- use RedisException as RedisResourceException;
- use stdClass;
- use Zend\Cache\Exception;
- use Zend\Cache\Storage\Capabilities;
- use Zend\Cache\Storage\FlushableInterface;
- use Zend\Cache\Storage\TotalSpaceCapableInterface;
- class Redis extends AbstractAdapter implements
- FlushableInterface,
- TotalSpaceCapableInterface
- {
- /**
- * Has this instance be initialized
- *
- * @var bool
- */
- protected $initialized = false;
- /**
- * The redis resource manager
- *
- * @var null|RedisResourceManager
- */
- protected $resourceManager;
- /**
- * The redis resource id
- *
- * @var null|string
- */
- protected $resourceId;
- /**
- * The namespace prefix
- *
- * @var string
- */
- protected $namespacePrefix = '';
- /**
- * Create new Adapter for redis storage
- *
- * @param null|array|Traversable|RedisOptions $options
- * @see \Zend\Cache\Storage\Adapter\Abstract
- */
- public function __construct($options = null)
- {
- if (!extension_loaded('redis')) {
- throw new Exception\ExtensionNotLoadedException("Redis extension is not loaded");
- }
- parent::__construct($options);
- // reset initialized flag on update option(s)
- $initialized = & $this->initialized;
- $this->getEventManager()->attach('option', function ($event) use (& $initialized) {
- $initialized = false;
- });
- }
- /**
- * Get Redis resource
- *
- * @return RedisResource
- */
- protected function getRedisResource()
- {
- if (!$this->initialized) {
- $options = $this->getOptions();
- // get resource manager and resource id
- $this->resourceManager = $options->getResourceManager();
- $this->resourceId = $options->getResourceId();
- // init namespace prefix
- $namespace = $options->getNamespace();
- if ($namespace !== '') {
- $this->namespacePrefix = $namespace . $options->getNamespaceSeparator();
- } else {
- $this->namespacePrefix = '';
- }
- // update initialized flag
- $this->initialized = true;
- }
- return $this->resourceManager->getResource($this->resourceId);
- }
- /* options */
- /**
- * Set options.
- *
- * @param array|Traversable|RedisOptions $options
- * @return Redis
- * @see getOptions()
- */
- public function setOptions($options)
- {
- if (!$options instanceof RedisOptions) {
- $options = new RedisOptions($options);
- }
- return parent::setOptions($options);
- }
- /**
- * Get options.
- *
- * @return RedisOptions
- * @see setOptions()
- */
- public function getOptions()
- {
- if (!$this->options) {
- $this->setOptions(new RedisOptions());
- }
- return $this->options;
- }
- /**
- * Internal method to get an item.
- *
- * @param string &$normalizedKey Key where to store data
- * @param bool &$success If the operation was successfull
- * @param mixed &$casToken Token
- * @return mixed Data on success, false on key not found
- * @throws Exception\RuntimeException
- */
- protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
- {
- $redis = $this->getRedisResource();
- try {
- $value = $redis->get($this->namespacePrefix . $normalizedKey);
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- if ($value === false) {
- $success = false;
- return null;
- }
- $success = true;
- $casToken = $value;
- return $value;
- }
- /**
- * Internal method to get multiple items.
- *
- * @param array &$normalizedKeys Array of keys to be obtained
- *
- * @return array Associative array of keys and values
- * @throws Exception\RuntimeException
- */
- protected function internalGetItems(array & $normalizedKeys)
- {
- $redis = $this->getRedisResource();
- $namespacedKeys = array();
- foreach ($normalizedKeys as & $normalizedKey) {
- $namespacedKeys[] = $this->namespacePrefix . $normalizedKey;
- }
- try {
- $results = $redis->mGet($namespacedKeys);
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- //combine the key => value pairs and remove all missing values
- return array_filter(
- array_combine($normalizedKeys, $results),
- function ($value) {
- return $value !== false;
- }
- );
- }
- /**
- * Internal method to test if an item exists.
- *
- * @param string &$normalizedKey Normalized key which will be checked
- *
- * @return bool
- * @throws Exception\RuntimeException
- */
- protected function internalHasItem(& $normalizedKey)
- {
- $redis = $this->getRedisResource();
- try {
- return $redis->exists($this->namespacePrefix . $normalizedKey);
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- }
- /**
- * Internal method to store an item.
- *
- * @param string &$normalizedKey Key in Redis under which value will be saved
- * @param mixed &$value Value to store under cache key
- *
- * @return bool
- * @throws Exception\RuntimeException
- */
- protected function internalSetItem(& $normalizedKey, & $value)
- {
- $redis = $this->getRedisResource();
- $ttl = $this->getOptions()->getTtl();
- try {
- if ($ttl) {
- if ($this->resourceManager->getMajorVersion($this->resourceId) < 2) {
- throw new Exception\UnsupportedMethodCallException("To use ttl you need version >= 2.0.0");
- }
- $success = $redis->setex($this->namespacePrefix . $normalizedKey, $ttl, $value);
- } else {
- $success = $redis->set($this->namespacePrefix . $normalizedKey, $value);
- }
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- return $success;
- }
- /**
- * Internal method to store multiple items.
- *
- * @param array &$normalizedKeyValuePairs An array of normalized key/value pairs
- *
- * @return array Array of not stored keys
- * @throws Exception\RuntimeException
- */
- protected function internalSetItems(array & $normalizedKeyValuePairs)
- {
- $redis = $this->getRedisResource();
- $ttl = $this->getOptions()->getTtl();
- $namespacedKeyValuePairs = array();
- foreach ($normalizedKeyValuePairs as $normalizedKey => & $value) {
- $namespacedKeyValuePairs[$this->namespacePrefix . $normalizedKey] = & $value;
- }
- try {
- if ($ttl > 0) {
- //check if ttl is supported
- if ($this->resourceManager->getMajorVersion($this->resourceId) < 2) {
- throw new Exception\UnsupportedMethodCallException("To use ttl you need version >= 2.0.0");
- }
- //mSet does not allow ttl, so use transaction
- $transaction = $redis->multi();
- foreach ($namespacedKeyValuePairs as $key => $value) {
- $transaction->setex($key, $ttl, $value);
- }
- $success = $transaction->exec();
- } else {
- $success = $redis->mSet($namespacedKeyValuePairs);
- }
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- if (!$success) {
- throw new Exception\RuntimeException($redis->getLastError());
- }
- return array();
- }
- /**
- * Add an item.
- *
- * @param string $normalizedKey
- * @param mixed $value
- * @return bool
- * @throws Exception\RuntimeException
- */
- protected function internalAddItem(& $normalizedKey, & $value)
- {
- $redis = $this->getRedisResource();
- try {
- return $redis->setnx($this->namespacePrefix . $normalizedKey, $value);
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- }
- /**
- * Internal method to remove an item.
- *
- * @param string &$normalizedKey Key which will be removed
- *
- * @return bool
- * @throws Exception\RuntimeException
- */
- protected function internalRemoveItem(& $normalizedKey)
- {
- $redis = $this->getRedisResource();
- try {
- return (bool) $redis->delete($this->namespacePrefix . $normalizedKey);
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- }
- /**
- * Internal method to increment an item.
- *
- * @param string $normalizedKey
- * @param int $value
- * @return int|bool The new value on success, false on failure
- * @throws Exception\RuntimeException
- */
- protected function internalIncrementItem(& $normalizedKey, & $value)
- {
- $redis = $this->getRedisResource();
- try {
- return $redis->incrBy($this->namespacePrefix . $normalizedKey, $value);
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- }
- /**
- * Internal method to decrement an item.
- *
- * @param string $normalizedKey
- * @param int $value
- * @return int|bool The new value on success, false on failure
- * @throws Exception\RuntimeException
- */
- protected function internalDecrementItem(& $normalizedKey, & $value)
- {
- $redis = $this->getRedisResource();
- try {
- return $redis->decrBy($this->namespacePrefix . $normalizedKey, $value);
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- }
- /**
- * Flush currently set DB
- *
- * @return bool
- * @throws Exception\RuntimeException
- */
- public function flush()
- {
- $redis = $this->getRedisResource();
- try {
- return $redis->flushDB();
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- }
- /* TotalSpaceCapableInterface */
- /**
- * Get total space in bytes
- *
- * @return int|float
- */
- public function getTotalSpace()
- {
- $redis = $this->getRedisResource();
- try {
- $info = $redis->info();
- } catch (RedisResourceException $e) {
- throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
- }
- return $info['used_memory'];
- }
- /* status */
- /**
- * Internal method to get capabilities of this adapter
- *
- * @return Capabilities
- */
- protected function internalGetCapabilities()
- {
- if ($this->capabilities === null) {
- $this->capabilityMarker = new stdClass();
- $minTtl = $this->resourceManager->getMajorVersion($this->resourceId) < 2 ? 0 : 1;
- //without serialization redis supports only strings for simple
- //get/set methods
- $this->capabilities = new Capabilities(
- $this,
- $this->capabilityMarker,
- array(
- 'supportedDatatypes' => array(
- 'NULL' => 'string',
- 'boolean' => 'string',
- 'integer' => 'string',
- 'double' => 'string',
- 'string' => true,
- 'array' => false,
- 'object' => false,
- 'resource' => false,
- ),
- 'supportedMetadata' => array(),
- 'minTtl' => $minTtl,
- 'maxTtl' => 0,
- 'staticTtl' => true,
- 'ttlPrecision' => 1,
- 'useRequestTime' => false,
- 'expiredRead' => false,
- 'maxKeyLength' => 255,
- 'namespaceIsPrefix' => true,
- )
- );
- }
- return $this->capabilities;
- }
- }