PK oYR
LICENSE.mdnu ٘ Copyright (c) 2019-2020, Laminas Foundation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
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.
PK oYR%'\ \ COPYRIGHT.mdnu ٘ Copyright (c) 2019-2020, Laminas Foundation.
All rights reserved. (https://getlaminas.org/)
PK oYR&] ] .travis.ymlnu ٘ language: php
cache:
directories:
- $HOME/.composer/cache
services:
- redis-server
env:
global:
- COMPOSER_ARGS="--no-interaction"
- COVERAGE_DEPS="php-coveralls/php-coveralls"
- SERIALIZER_DEPS="laminas/laminas-serializer"
matrix:
fast_finish: true
include:
- php: 5.6
env:
- DEPS=lowest
- REDIS_PECL_VERSION="redis-2.2.3"
- php: 5.6
env:
- DEPS=latest
- REDIS_PECL_VERSION="redis-4.3.0"
- php: 7.0
env:
- DEPS=lowest
- REDIS_PECL_VERSION="redis-4.0.0"
- php: 7.0
env:
- DEPS=latest
- REDIS_PECL_VERSION="redis"
- php: 7.1
env:
- DEPS=lowest
- REDIS_PECL_VERSION="redis-4.0.0"
- php: 7.1
env:
- DEPS=latest
- REDIS_PECL_VERSION="redis"
- php: 7.2
env:
- DEPS=lowest
- REDIS_PECL_VERSION="redis-4.0.0"
- php: 7.2
env:
- DEPS=latest
- REDIS_PECL_VERSION="redis"
- php: 7.3
env:
- DEPS=lowest
- REDIS_PECL_VERSION="redis-4.0.0"
- php: 7.3
env:
- DEPS=latest
- REDIS_PECL_VERSION="redis"
- php: 7.4
env:
- DEPS=lowest
- REDIS_PECL_VERSION="redis-4.0.0"
- php: 7.4
env:
- DEPS=latest
- REDIS_PECL_VERSION="redis"
- CS_CHECK=true
- TEST_COVERAGE=true
before_install:
- if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi
install:
- echo "no" | pecl install -f $REDIS_PECL_VERSION ;
- travis_retry composer install $COMPOSER_ARGS
- travis_retry composer require --dev $COMPOSER_ARGS $SERIALIZER_DEPS
- if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi
- if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi
- if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi
- stty cols 120 && composer show
script:
- if [[ $TEST_COVERAGE == 'true' ]]; then composer run-script test-coverage -- --verbose ; else composer run-script test -- --verbose ; fi
- if [[ $CS_CHECK == 'true' ]]; then composer cs-check ; fi
after_script:
- if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry vendor/bin/php-coveralls -v ; fi
notifications:
email: false
PK oYRx= = .coveralls.ymlnu ٘ coverage_clover: clover.xml
json_path: coveralls-upload.json
PK oYR}CC phpcs.xmlnu ٘
src
test
PK oYR'韒F F README.mdnu ٘ # laminas-cache-storage-adapter-redis
[![Build Status](https://travis-ci.com/laminas/laminas-cache-storage-adapter-redis.svg?branch=master)](https://travis-ci.com/laminas/laminas-cache-storage-adapter-redis)
[![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-cache-storage-adapter-redis/badge.svg?branch=master)](https://coveralls.io/github/laminas/laminas-cache-storage-adapter-redis?branch=master)
This library provides …
## Installation
Run the following to install this library:
```bash
$ composer require laminas/laminas-cache-storage-adapter-redis
```
## Documentation
Browse the documentation online at https://docs.laminas.dev/laminas-cache-storage-adapter-redis/
## Support
* [Issues](https://github.com/laminas/laminas-cache-storage-adapter-redis/issues/)
* [Forum](https://discourse.laminas.dev/)
PK oYRfj j
.gitignorenu ٘ /.phpunit.result.cache
/composer.lock
/docs/html/
/laminas-mkdoc-theme.tgz
/laminas-mkdoc-theme/
/vendor/
PK oYRQr src/RedisOptions.phpnu ٘ namespaceSeparator !== $namespaceSeparator) {
$this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
$this->namespaceSeparator = $namespaceSeparator;
}
return $this;
}
/**
* Get namespace separator
*
* @return string
*/
public function getNamespaceSeparator()
{
return $this->namespaceSeparator;
}
/**
* Set the redis resource manager to use
*
* @param null|RedisResourceManager $resourceManager
* @return RedisOptions Provides a fluent interface
*/
public function setResourceManager(RedisResourceManager $resourceManager = null)
{
if ($this->resourceManager !== $resourceManager) {
$this->triggerOptionEvent('resource_manager', $resourceManager);
$this->resourceManager = $resourceManager;
}
return $this;
}
/**
* Get the redis resource manager
*
* @return RedisResourceManager
*/
public function getResourceManager()
{
if (! $this->resourceManager) {
$this->resourceManager = new RedisResourceManager();
}
return $this->resourceManager;
}
/**
* Get the redis resource id
*
* @return string
*/
public function getResourceId()
{
return $this->resourceId;
}
/**
* Set the redis resource id
*
* @param string $resourceId
* @return RedisOptions Provides a fluent interface
*/
public function setResourceId($resourceId)
{
$resourceId = (string) $resourceId;
if ($this->resourceId !== $resourceId) {
$this->triggerOptionEvent('resource_id', $resourceId);
$this->resourceId = $resourceId;
}
return $this;
}
/**
* Get the persistent id
*
* @return string
*/
public function getPersistentId()
{
return $this->getResourceManager()->getPersistentId($this->getResourceId());
}
/**
* Set the persistent id
*
* @param string $persistentId
* @return RedisOptions Provides a fluent interface
*/
public function setPersistentId($persistentId)
{
$this->triggerOptionEvent('persistent_id', $persistentId);
$this->getResourceManager()->setPersistentId($this->getResourceId(), $persistentId);
return $this;
}
/**
* Set redis options
*
* @param array $libOptions
* @return RedisOptions Provides a fluent interface
* @link http://github.com/nicolasff/phpredis#setoption
*/
public function setLibOptions(array $libOptions)
{
$this->triggerOptionEvent('lib_option', $libOptions);
$this->getResourceManager()->setLibOptions($this->getResourceId(), $libOptions);
return $this;
}
/**
* Get redis options
*
* @return array
* @link http://github.com/nicolasff/phpredis#setoption
*/
public function getLibOptions()
{
return $this->getResourceManager()->getLibOptions($this->getResourceId());
}
/**
* Set server
*
* Server can be described as follows:
* - URI: /path/to/sock.sock
* - Assoc: array('host' => [, 'port' => [, 'timeout' => ]])
* - List: array([, , [, ]])
*
* @param string|array $server
*
* @return RedisOptions Provides a fluent interface
*/
public function setServer($server)
{
$this->getResourceManager()->setServer($this->getResourceId(), $server);
return $this;
}
/**
* Get server
*
* @return array array('host' => [, 'port' => [, 'timeout' => ]])
*/
public function getServer()
{
return $this->getResourceManager()->getServer($this->getResourceId());
}
/**
* Set resource database number
*
* @param int $database Database number
*
* @return RedisOptions Provides a fluent interface
*/
public function setDatabase($database)
{
$this->getResourceManager()->setDatabase($this->getResourceId(), $database);
return $this;
}
/**
* Get resource database number
*
* @return int Database number
*/
public function getDatabase()
{
return $this->getResourceManager()->getDatabase($this->getResourceId());
}
/**
* Set resource password
*
* @param string $password Password
*
* @return RedisOptions Provides a fluent interface
*/
public function setPassword($password)
{
$this->getResourceManager()->setPassword($this->getResourceId(), $password);
return $this;
}
/**
* Get resource password
*
* @return string
*/
public function getPassword()
{
return $this->getResourceManager()->getPassword($this->getResourceId());
}
}
PK oYRTI I src/RedisResourceManager.phpnu ٘ resources[$id]);
}
/**
* Get redis server version
*
* @param string $resourceId
* @return string
* @throws Exception\RuntimeException
*/
public function getVersion($resourceId)
{
// check resource id and initialize the resource
$this->getResource($resourceId);
return $this->resources[$resourceId]['version'];
}
/**
* Get redis major server version
*
* @param string $resourceId
* @return int
* @throws Exception\RuntimeException
*/
public function getMajorVersion($resourceId)
{
// check resource id and initialize the resource
$this->getResource($resourceId);
return (int) $this->resources[$resourceId]['version'];
}
/**
* Get redis server version
*
* @deprecated 2.2.2 Use getMajorVersion instead
*
* @param string $id
* @return int
* @throws Exception\RuntimeException
*/
public function getMayorVersion($id)
{
return $this->getMajorVersion($id);
}
/**
* Get redis resource database
*
* @param string $id
* @return string
*/
public function getDatabase($id)
{
if (! $this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
$resource = & $this->resources[$id];
return $resource['database'];
}
/**
* Get redis resource password
*
* @param string $id
* @return string
*/
public function getPassword($id)
{
if (! $this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
$resource = & $this->resources[$id];
return $resource['password'];
}
/**
* Gets a redis resource
*
* @param string $id
* @return RedisResource
* @throws Exception\RuntimeException
*/
public function getResource($id)
{
if (! $this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
$resource = & $this->resources[$id];
if ($resource['resource'] instanceof RedisResource) {
//in case new server was set then connect
if (! $resource['initialized']) {
$this->connect($resource);
}
if (! $resource['version']) {
$info = $resource['resource']->info();
$resource['version'] = $info['redis_version'];
}
return $resource['resource'];
}
$redis = new RedisResource();
$resource['resource'] = $redis;
$this->connect($resource);
$this->normalizeLibOptions($resource['lib_options']);
foreach ($resource['lib_options'] as $k => $v) {
$redis->setOption($k, $v);
}
$info = $redis->info();
$resource['version'] = $info['redis_version'];
$this->resources[$id]['resource'] = $redis;
return $redis;
}
/**
* Get server
* @param string $id
* @throws Exception\RuntimeException
* @return array array('host' => [, 'port' => [, 'timeout' => ]])
*/
public function getServer($id)
{
if (! $this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
$resource = & $this->resources[$id];
return $resource['server'];
}
/**
* Normalize one server into the following format:
* array('host' => [, 'port' => [, 'timeout' => ]])
*
* @param string|array $server
*
* @throws Exception\InvalidArgumentException
*/
protected function normalizeServer(&$server)
{
$host = null;
$port = null;
$timeout = 0;
// convert a single server into an array
if ($server instanceof Traversable) {
$server = ArrayUtils::iteratorToArray($server);
}
if (is_array($server)) {
// array([, [, ]])
if (isset($server[0])) {
$host = (string) $server[0];
$port = isset($server[1]) ? (int) $server[1] : $port;
$timeout = isset($server[2]) ? (int) $server[2] : $timeout;
}
// array('host' => [, 'port' => , ['timeout' => ]])
if (! isset($server[0]) && isset($server['host'])) {
$host = (string) $server['host'];
$port = isset($server['port']) ? (int) $server['port'] : $port;
$timeout = isset($server['timeout']) ? (int) $server['timeout'] : $timeout;
}
} else {
// parse server from URI host{:?port}
$server = trim($server);
if (strpos($server, '/') !== 0) {
//non unix domain socket connection
$server = parse_url($server);
} else {
$server = ['host' => $server];
}
if (! $server) {
throw new Exception\InvalidArgumentException("Invalid server given");
}
$host = $server['host'];
$port = isset($server['port']) ? (int) $server['port'] : $port;
$timeout = isset($server['timeout']) ? (int) $server['timeout'] : $timeout;
}
if (! $host) {
throw new Exception\InvalidArgumentException('Missing required server host');
}
$server = [
'host' => $host,
'port' => $port,
'timeout' => $timeout,
];
}
/**
* Extract password to be used on connection
*
* @param mixed $resource
* @param mixed $serverUri
*
* @return string|null
*/
protected function extractPassword($resource, $serverUri)
{
if (! empty($resource['password'])) {
return $resource['password'];
}
if (! is_string($serverUri)) {
return;
}
// parse server from URI host{:?port}
$server = trim($serverUri);
if (strpos($server, '/') === 0) {
return;
}
//non unix domain socket connection
$server = parse_url($server);
return isset($server['pass']) ? $server['pass'] : null;
}
/**
* Connects to redis server
*
*
* @param array & $resource
*
* @return null
* @throws Exception\RuntimeException
*/
protected function connect(array & $resource)
{
$server = $resource['server'];
$redis = $resource['resource'];
if ($resource['persistent_id'] !== '') {
//connect or reuse persistent connection
$success = $redis->pconnect(
$server['host'],
$server['port'],
$server['timeout'],
$resource['persistent_id']
);
} elseif ($server['port']) {
$success = $redis->connect($server['host'], $server['port'], $server['timeout']);
} elseif ($server['timeout']) {
//connect through unix domain socket
$success = $redis->connect($server['host'], $server['timeout']);
} else {
$success = $redis->connect($server['host']);
}
if (! $success) {
throw new Exception\RuntimeException('Could not establish connection with Redis instance');
}
$resource['initialized'] = true;
if ($resource['password']) {
$redis->auth($resource['password']);
}
$redis->select($resource['database']);
}
/**
* Set a resource
*
* @param string $id
* @param array|Traversable|RedisResource $resource
* @return RedisResourceManager Fluent interface
*/
public function setResource($id, $resource)
{
$id = (string) $id;
//TODO: how to get back redis connection info from resource?
$defaults = [
'persistent_id' => '',
'lib_options' => [],
'server' => [],
'password' => '',
'database' => 0,
'resource' => null,
'initialized' => false,
'version' => 0,
];
if (! $resource instanceof RedisResource) {
if ($resource instanceof Traversable) {
$resource = ArrayUtils::iteratorToArray($resource);
} elseif (! is_array($resource)) {
throw new Exception\InvalidArgumentException(
'Resource must be an instance of an array or Traversable'
);
}
$resource = array_merge($defaults, $resource);
// normalize and validate params
$this->normalizePersistentId($resource['persistent_id']);
// #6495 note: order is important here, as `normalizeServer` applies destructive
// transformations on $resource['server']
$resource['password'] = $this->extractPassword($resource, $resource['server']);
$this->normalizeServer($resource['server']);
} else {
//there are two ways of determining if redis is already initialized
//with connect function:
//1) pinging server
//2) checking undocumented property socket which is available only
//after successful connect
$resource = array_merge(
$defaults,
[
'resource' => $resource,
'initialized' => isset($resource->socket),
]
);
}
$this->resources[$id] = $resource;
return $this;
}
/**
* Remove a resource
*
* @param string $id
* @return RedisResourceManager Fluent interface
*/
public function removeResource($id)
{
unset($this->resources[$id]);
return $this;
}
/**
* Set the persistent id
*
* @param string $id
* @param string $persistentId
* @return RedisResourceManager Fluent interface
* @throws Exception\RuntimeException
*/
public function setPersistentId($id, $persistentId)
{
if (! $this->hasResource($id)) {
return $this->setResource($id, [
'persistent_id' => $persistentId
]);
}
$resource = & $this->resources[$id];
if ($resource['resource'] instanceof RedisResource && $resource['initialized']) {
throw new Exception\RuntimeException(
"Can't change persistent id of resource {$id} after initialization"
);
}
$this->normalizePersistentId($persistentId);
$resource['persistent_id'] = $persistentId;
return $this;
}
/**
* Get the persistent id
*
* @param string $id
* @return string
* @throws Exception\RuntimeException
*/
public function getPersistentId($id)
{
if (! $this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
$resource = & $this->resources[$id];
return $resource['persistent_id'];
}
/**
* Normalize the persistent id
*
* @param string $persistentId
*/
protected function normalizePersistentId(& $persistentId)
{
$persistentId = (string) $persistentId;
}
/**
* Set Redis options
*
* @param string $id
* @param array $libOptions
* @return RedisResourceManager Fluent interface
*/
public function setLibOptions($id, array $libOptions)
{
if (! $this->hasResource($id)) {
return $this->setResource($id, [
'lib_options' => $libOptions
]);
}
$resource = & $this->resources[$id];
$resource['lib_options'] = $libOptions;
if (! $resource['resource'] instanceof RedisResource) {
return $this;
}
$this->normalizeLibOptions($libOptions);
$redis = & $resource['resource'];
if (method_exists($redis, 'setOptions')) {
$redis->setOptions($libOptions);
} else {
foreach ($libOptions as $key => $value) {
$redis->setOption($key, $value);
}
}
return $this;
}
/**
* Get Redis options
*
* @param string $id
* @return array
* @throws Exception\RuntimeException
*/
public function getLibOptions($id)
{
if (! $this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
$resource = & $this->resources[$id];
if ($resource['resource'] instanceof RedisResource) {
$libOptions = [];
$reflection = new ReflectionClass('Redis');
$constants = $reflection->getConstants();
foreach ($constants as $constName => $constValue) {
if (strpos($constName, 'OPT_') === 0) {
$libOptions[$constValue] = $resource['resource']->getOption($constValue);
}
}
return $libOptions;
}
return $resource['lib_options'];
}
/**
* Set one Redis option
*
* @param string $id
* @param string|int $key
* @param mixed $value
* @return RedisResourceManager Fluent interface
*/
public function setLibOption($id, $key, $value)
{
return $this->setLibOptions($id, [$key => $value]);
}
/**
* Get one Redis option
*
* @param string $id
* @param string|int $key
* @return mixed
* @throws Exception\RuntimeException
*/
public function getLibOption($id, $key)
{
if (! $this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
$this->normalizeLibOptionKey($key);
$resource = & $this->resources[$id];
if ($resource['resource'] instanceof RedisResource) {
return $resource['resource']->getOption($key);
}
return isset($resource['lib_options'][$key]) ? $resource['lib_options'][$key] : null;
}
/**
* Normalize Redis options
*
* @param array|Traversable $libOptions
* @throws Exception\InvalidArgumentException
*/
protected function normalizeLibOptions(& $libOptions)
{
if (! is_array($libOptions) && ! ($libOptions instanceof Traversable)) {
throw new Exception\InvalidArgumentException(
"Lib-Options must be an array or an instance of Traversable"
);
}
$result = [];
foreach ($libOptions as $key => $value) {
$this->normalizeLibOptionKey($key);
$result[$key] = $value;
}
$libOptions = $result;
}
/**
* Convert option name into it's constant value
*
* @param string|int $key
* @throws Exception\InvalidArgumentException
*/
protected function normalizeLibOptionKey(& $key)
{
// convert option name into it's constant value
if (is_string($key)) {
$const = 'Redis::OPT_' . str_replace([' ', '-'], '_', strtoupper($key));
if (! defined($const)) {
throw new Exception\InvalidArgumentException("Unknown redis option '{$key}' ({$const})");
}
$key = constant($const);
} else {
$key = (int) $key;
}
}
/**
* Set server
*
* Server can be described as follows:
* - URI: /path/to/sock.sock
* - Assoc: array('host' => [, 'port' => [, 'timeout' => ]])
* - List: array([, , [, ]])
*
* @param string $id
* @param string|array $server
* @return RedisResourceManager
*/
public function setServer($id, $server)
{
if (! $this->hasResource($id)) {
return $this->setResource($id, [
'server' => $server
]);
}
$this->normalizeServer($server);
$resource = & $this->resources[$id];
$resource['password'] = $this->extractPassword($resource, $server);
if ($resource['resource'] instanceof RedisResource) {
$resourceParams = ['server' => $server];
if (! empty($resource['password'])) {
$resourceParams['password'] = $resource['password'];
}
$this->setResource($id, $resourceParams);
} else {
$resource['server'] = $server;
}
return $this;
}
/**
* Set redis password
*
* @param string $id
* @param string $password
* @return RedisResource
*/
public function setPassword($id, $password)
{
if (! $this->hasResource($id)) {
return $this->setResource($id, [
'password' => $password,
]);
}
$resource = & $this->resources[$id];
$resource['password'] = $password;
$resource['initialized'] = false;
return $this;
}
/**
* Set redis database number
*
* @param string $id
* @param int $database
* @return RedisResourceManager
*/
public function setDatabase($id, $database)
{
$database = (int) $database;
if (! $this->hasResource($id)) {
return $this->setResource($id, [
'database' => $database,
]);
}
$resource = & $this->resources[$id];
if ($resource['resource'] instanceof RedisResource && $resource['initialized']) {
$resource['resource']->select($database);
}
$resource['database'] = $database;
return $this;
}
}
PK oYRO O
src/Redis.phpnu ٘ initialized;
$this->getEventManager()->attach('option', function () 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 successful
* @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;
}
$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 = [];
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 (bool) $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();
$options = $this->getOptions();
$ttl = $options->getTtl();
try {
if ($ttl) {
if ($options->getResourceManager()->getMajorVersion($options->getResourceId()) < 2) {
throw new Exception\UnsupportedMethodCallException("To use ttl you need version >= 2.0.0");
}
$success = $redis->setex($this->namespacePrefix . $normalizedKey, $ttl, $this->preSerialize($value));
} else {
$success = $redis->set($this->namespacePrefix . $normalizedKey, $this->preSerialize($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();
$options = $this->getOptions();
$ttl = $options->getTtl();
$namespacedKeyValuePairs = [];
foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
$namespacedKeyValuePairs[$this->namespacePrefix . $normalizedKey] = $this->preSerialize($value);
}
try {
if ($ttl > 0) {
//check if ttl is supported
if ($options->getResourceManager()->getMajorVersion($options->getResourceId()) < 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 [];
}
/**
* Add an item.
*
* @param string $normalizedKey
* @param mixed $value
* @return bool
* @throws Exception\RuntimeException
*/
protected function internalAddItem(& $normalizedKey, & $value)
{
$redis = $this->getRedisResource();
$options = $this->getOptions();
$ttl = $options->getTtl();
try {
if ($ttl) {
if ($options->getResourceManager()->getMajorVersion($options->getResourceId()) < 2) {
throw new Exception\UnsupportedMethodCallException("To use ttl you need version >= 2.0.0");
}
/**
* To ensure expected behaviour, we stick with the "setnx" method.
* This means we only set the ttl after the key/value has been successfully set.
*/
$success = $redis->setnx($this->namespacePrefix . $normalizedKey, $this->preSerialize($value));
if ($success) {
$redis->expire($this->namespacePrefix . $normalizedKey, $ttl);
}
} else {
$success = $redis->setnx($this->namespacePrefix . $normalizedKey, $this->preSerialize($value));
}
return $success;
} catch (RedisResourceException $e) {
throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
}
}
/**
* Internal method to touch an item.
*
* @param string &$normalizedKey Key which will be touched
*
* @return bool
* @throws Exception\RuntimeException
*/
protected function internalTouchItem(& $normalizedKey)
{
$redis = $this->getRedisResource();
try {
$ttl = $this->getOptions()->getTtl();
return (bool) $redis->expire($this->namespacePrefix . $normalizedKey, $ttl);
} 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->del($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);
}
}
/* ClearByNamespaceInterface */
/**
* Remove items of given namespace
*
* @param string $namespace
* @return bool
*/
public function clearByNamespace($namespace)
{
$redis = $this->getRedisResource();
$namespace = (string) $namespace;
if ($namespace === '') {
throw new Exception\InvalidArgumentException('No namespace given');
}
$options = $this->getOptions();
$prefix = $namespace . $options->getNamespaceSeparator();
$redis->del($redis->keys($prefix . '*'));
return true;
}
/* ClearByPrefixInterface */
/**
* Remove items matching given prefix
*
* @param string $prefix
* @return bool
*/
public function clearByPrefix($prefix)
{
$redis = $this->getRedisResource();
$prefix = (string) $prefix;
if ($prefix === '') {
throw new Exception\InvalidArgumentException('No prefix given');
}
$options = $this->getOptions();
$namespace = $options->getNamespace();
$prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator() . $prefix;
$redis->del($redis->keys($prefix.'*'));
return true;
}
/* 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();
$options = $this->getOptions();
$resourceMgr = $options->getResourceManager();
$serializer = $resourceMgr->getLibOption($options->getResourceId(), RedisResource::OPT_SERIALIZER);
$redisVersion = $resourceMgr->getMajorVersion($options->getResourceId());
$minTtl = version_compare($redisVersion, '2', '<') ? 0 : 1;
$supportedMetadata = $redisVersion >= 2 ? ['ttl'] : [];
$this->capabilities = new Capabilities(
$this,
$this->capabilityMarker,
[
'supportedDatatypes' => $serializer ? [
'NULL' => true,
'boolean' => true,
'integer' => true,
'double' => true,
'string' => true,
'array' => 'array',
'object' => 'object',
'resource' => false,
] : [
'NULL' => 'string',
'boolean' => 'string',
'integer' => 'string',
'double' => 'string',
'string' => true,
'array' => false,
'object' => false,
'resource' => false,
],
'supportedMetadata' => $supportedMetadata,
'minTtl' => $minTtl,
'maxTtl' => 0,
'staticTtl' => true,
'ttlPrecision' => 1,
'useRequestTime' => false,
'maxKeyLength' => 255,
'namespaceIsPrefix' => true,
]
);
}
return $this->capabilities;
}
/**
* {@inheritDoc}
*
* @throws Exception\ExceptionInterface
*/
protected function internalGetMetadata(& $normalizedKey)
{
$redis = $this->getRedisResource();
$metadata = [];
try {
$redisVersion = $this->resourceManager->getVersion($this->resourceId);
// redis >= 2.8
// The command 'pttl' returns -2 if the item does not exist
// and -1 if the item has no associated expire
if (version_compare($redisVersion, '2.8', '>=')) {
$pttl = $redis->pttl($this->namespacePrefix . $normalizedKey);
if ($pttl <= -2) {
return false;
}
$metadata['ttl'] = ($pttl == -1) ? null : $pttl / 1000;
// redis >= 2.6, < 2.8
// The command 'pttl' returns -1 if the item does not exist or the item has no associated expire
} elseif (version_compare($redisVersion, '2.6', '>=')) {
$pttl = $redis->pttl($this->namespacePrefix . $normalizedKey);
if ($pttl <= -1) {
if (! $this->internalHasItem($normalizedKey)) {
return false;
}
$metadata['ttl'] = null;
} else {
$metadata['ttl'] = $pttl / 1000;
}
// redis >= 2, < 2.6
// The command 'pttl' is not supported but 'ttl'
// The command 'ttl' returns 0 if the item does not exist same as if the item is going to be expired
// NOTE: In case of ttl=0 we return false because the item is going to be expired in a very near future
// and then doesn't exist any more
} elseif (version_compare($redisVersion, '2', '>=')) {
$ttl = $redis->ttl($this->namespacePrefix . $normalizedKey);
if ($ttl <= -1) {
if (! $this->internalHasItem($normalizedKey)) {
return false;
}
$metadata['ttl'] = null;
} else {
$metadata['ttl'] = $ttl;
}
// redis < 2
// The commands 'pttl' and 'ttl' are not supported
// but item existence have to be checked
} elseif (! $this->internalHasItem($normalizedKey)) {
return false;
}
} catch (RedisResourceException $e) {
throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
}
return $metadata;
}
/**
* Pre-Serialize value before putting it to the redis extension
* The reason for this is the buggy extension version < 2.5.7
* which is producing a segfault on storing NULL as long as no serializer was configured.
* @link https://github.com/zendframework/zend-cache/issues/88
*/
protected function preSerialize($value)
{
$options = $this->getOptions();
$resourceMgr = $options->getResourceManager();
$serializer = $resourceMgr->getLibOption($options->getResourceId(), RedisResource::OPT_SERIALIZER);
if ($serializer === null) {
return (string) $value;
}
return $value;
}
}
PK oYR
mkdocs.ymlnu ٘ docs_dir: docs/book
site_dir: docs/html
nav:
- Home: index.md
- Introduction: v1/intro.md
site_name: 'laminas-cache-storage-adapter-redis'
site_description: ''
repo_url: 'https://github.com/laminas/laminas-cache-storage-adapter-redis'
PK oYRu|e)
1 .github/workflows/release-on-milestone-closed.ymlnu ٘ # Alternate workflow example.
# This one is identical to the one in release-on-milestone.yml, with one change:
# the Release step uses the ORGANIZATION_ADMIN_TOKEN instead, to allow it to
# trigger a release workflow event. This is useful if you have other actions
# that intercept that event.
name: "Automatic Releases"
on:
milestone:
types:
- "closed"
jobs:
release:
name: "GIT tag, release & create merge-up PR"
runs-on: ubuntu-latest
steps:
- name: "Checkout"
uses: "actions/checkout@v2"
- name: "Release"
uses: "laminas/automatic-releases@v1"
with:
command-name: "laminas:automatic-releases:release"
env:
"GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
- name: "Create Merge-Up Pull Request"
uses: "laminas/automatic-releases@v1"
with:
command-name: "laminas:automatic-releases:create-merge-up-pull-request"
env:
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
- name: "Create and/or Switch to new Release Branch"
uses: "laminas/automatic-releases@v1"
with:
command-name: "laminas:automatic-releases:switch-default-branch-to-next-minor"
env:
"GITHUB_TOKEN": ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
- name: "Bump Changelog Version On Originating Release Branch"
uses: "laminas/automatic-releases@v1"
with:
command-name: "laminas:automatic-releases:bump-changelog"
env:
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
- name: "Create new milestones"
uses: "laminas/automatic-releases@v1"
with:
command-name: "laminas:automatic-releases:create-milestones"
env:
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
PK oYRRa .gitattributesnu ٘ /.coveralls.yml export-ignore
/.gitattributes export-ignore
/.github/ export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/docs/ export-ignore
/mkdocs.yml export-ignore
/phpcs.xml export-ignore
/phpunit.xml.dist export-ignore
/test/ export-ignore
PK oYR
9 test/integration/Psr/SimpleCache/RedisIntegrationTest.phpnu ٘ tz = date_default_timezone_get();
date_default_timezone_set('America/Vancouver');
parent::setUp();
}
protected function tearDown()
{
date_default_timezone_set($this->tz);
if ($this->storage) {
$this->storage->flush();
}
parent::tearDown();
}
public function createSimpleCache()
{
$options = ['resource_id' => __CLASS__];
if (getenv('TESTS_LAMINAS_CACHE_REDIS_HOST') && getenv('TESTS_LAMINAS_CACHE_REDIS_PORT')) {
$options['server'] = [getenv('TESTS_LAMINAS_CACHE_REDIS_HOST'), getenv('TESTS_LAMINAS_CACHE_REDIS_PORT')];
} elseif (getenv('TESTS_LAMINAS_CACHE_REDIS_HOST')) {
$options['server'] = [getenv('TESTS_LAMINAS_CACHE_REDIS_HOST')];
}
if (getenv('TESTS_LAMINAS_CACHE_REDIS_DATABASE')) {
$options['database'] = getenv('TESTS_LAMINAS_CACHE_REDIS_DATABASE');
}
if (getenv('TESTS_LAMINAS_CACHE_REDIS_PASSWORD')) {
$options['password'] = getenv('TESTS_LAMINAS_CACHE_REDIS_PASSWORD');
}
try {
$storage = StorageFactory::adapterFactory('redis', $options);
$storage->addPlugin(new Serializer());
return new SimpleCacheDecorator($storage);
} catch (Exception\ExtensionNotLoadedException $e) {
$this->markTestSkipped($e->getMessage());
} catch (ServiceNotCreatedException $e) {
if ($e->getPrevious() instanceof Exception\ExtensionNotLoadedException) {
$this->markTestSkipped($e->getMessage());
}
throw $e;
}
}
}
PK oYR ; test/integration/Psr/CacheItemPool/RedisIntegrationTest.phpnu ٘ tz = date_default_timezone_get();
date_default_timezone_set('America/Vancouver');
parent::setUp();
}
protected function tearDown()
{
date_default_timezone_set($this->tz);
if ($this->storage) {
$this->storage->flush();
}
parent::tearDown();
}
public function createCachePool()
{
$options = ['resource_id' => __CLASS__];
if (getenv('TESTS_LAMINAS_CACHE_REDIS_HOST') && getenv('TESTS_LAMINAS_CACHE_REDIS_PORT')) {
$options['server'] = [getenv('TESTS_LAMINAS_CACHE_REDIS_HOST'), getenv('TESTS_LAMINAS_CACHE_REDIS_PORT')];
} elseif (getenv('TESTS_LAMINAS_CACHE_REDIS_HOST')) {
$options['server'] = [getenv('TESTS_LAMINAS_CACHE_REDIS_HOST')];
}
if (getenv('TESTS_LAMINAS_CACHE_REDIS_DATABASE')) {
$options['database'] = getenv('TESTS_LAMINAS_CACHE_REDIS_DATABASE');
}
if (getenv('TESTS_LAMINAS_CACHE_REDIS_PASSWORD')) {
$options['password'] = getenv('TESTS_LAMINAS_CACHE_REDIS_PASSWORD');
}
try {
$storage = StorageFactory::adapterFactory('redis', $options);
$storage->addPlugin(new Serializer());
$deferredSkippedMessage = sprintf(
'%s storage doesn\'t support driver deferred',
\get_class($storage)
);
$this->skippedTests['testHasItemReturnsFalseWhenDeferredItemIsExpired'] = $deferredSkippedMessage;
return new CacheItemPoolDecorator($storage);
} catch (Exception\ExtensionNotLoadedException $e) {
$this->markTestSkipped($e->getMessage());
} catch (ServiceNotCreatedException $e) {
if ($e->getPrevious() instanceof Exception\ExtensionNotLoadedException) {
$this->markTestSkipped($e->getMessage());
}
throw $e;
}
}
}
PK oYR̽,7 7 test/unit/RedisTest.phpnu ٘
*/
class RedisTest extends CommonAdapterTest
{
// @codingStandardsIgnoreStart
/**
*
* @var Cache\Storage\Adapter\RedisOptions
*/
protected $_options;
/**
*
* @var Cache\Storage\Adapter\Redis
*/
protected $_storage;
// @codingStandardsIgnoreEnd
public function setUp()
{
if (! extension_loaded('redis')) {
$this->markTestSkipped("Redis extension is not loaded");
}
$options = ['resource_id' => __CLASS__];
if (getenv('TESTS_LAMINAS_CACHE_REDIS_HOST') && getenv('TESTS_LAMINAS_CACHE_REDIS_PORT')) {
$options['server'] = [getenv('TESTS_LAMINAS_CACHE_REDIS_HOST'), getenv('TESTS_LAMINAS_CACHE_REDIS_PORT')];
} elseif (getenv('TESTS_LAMINAS_CACHE_REDIS_HOST')) {
$options['server'] = [getenv('TESTS_LAMINAS_CACHE_REDIS_HOST')];
}
if (getenv('TESTS_LAMINAS_CACHE_REDIS_DATABASE')) {
$options['database'] = getenv('TESTS_LAMINAS_CACHE_REDIS_DATABASE');
}
if (getenv('TESTS_LAMINAS_CACHE_REDIS_PASSWORD')) {
$options['password'] = getenv('TESTS_LAMINAS_CACHE_REDIS_PASSWORD');
}
$this->_options = new Cache\Storage\Adapter\RedisOptions($options);
$this->_storage = new Cache\Storage\Adapter\Redis($this->_options);
parent::setUp();
}
public function tearDown()
{
if ($this->_storage) {
$this->_storage->flush();
}
parent::tearDown();
}
public function getCommonAdapterNamesProvider()
{
return [
['redis'],
['Redis'],
];
}
public function testLibOptionsFirst()
{
$options = [
'resource_id' => __CLASS__ . '2',
'lib_options' => [
RedisResource::OPT_SERIALIZER => RedisResource::SERIALIZER_PHP,
],
];
if (getenv('TESTS_LAMINAS_CACHE_REDIS_HOST') && getenv('TESTS_LAMINAS_CACHE_REDIS_PORT')) {
$options['server'] = [getenv('TESTS_LAMINAS_CACHE_REDIS_HOST'), getenv('TESTS_LAMINAS_CACHE_REDIS_PORT')];
} elseif (getenv('TESTS_LAMINAS_CACHE_REDIS_HOST')) {
$options['server'] = [getenv('TESTS_LAMINAS_CACHE_REDIS_HOST')];
}
if (getenv('TESTS_LAMINAS_CACHE_REDIS_DATABASE')) {
$options['database'] = getenv('TESTS_LAMINAS_CACHE_REDIS_DATABASE');
}
if (getenv('TESTS_LAMINAS_CACHE_REDIS_PASSWORD')) {
$options['password'] = getenv('TESTS_LAMINAS_CACHE_REDIS_PASSWORD');
}
$redisOptions = new Cache\Storage\Adapter\RedisOptions($options);
$storage = new Cache\Storage\Adapter\Redis($redisOptions);
$this->assertInstanceOf('Laminas\\Cache\\Storage\\Adapter\\Redis', $storage);
}
public function testRedisSerializer()
{
$this->_storage->addPlugin(new \Laminas\Cache\Storage\Plugin\Serializer());
$value = ['test', 'of', 'array'];
$this->_storage->setItem('key', $value);
$this->assertCount(count($value), $this->_storage->getItem('key'), 'Problem with Redis serialization');
}
public function testRedisSetInt()
{
$key = 'key';
$this->assertTrue($this->_storage->setItem($key, 123));
$this->assertEquals('123', $this->_storage->getItem($key), 'Integer should be cast to string');
}
public function testRedisSetDouble()
{
$key = 'key';
$this->assertTrue($this->_storage->setItem($key, 123.12));
$this->assertEquals('123.12', $this->_storage->getItem($key), 'Integer should be cast to string');
}
public function testRedisSetNull()
{
$key = 'key';
$this->assertTrue($this->_storage->setItem($key, null));
$this->assertEquals('', $this->_storage->getItem($key), 'Null should be cast to string');
}
public function testRedisSetBoolean()
{
$key = 'key';
$this->assertTrue($this->_storage->setItem($key, true));
$this->assertEquals('1', $this->_storage->getItem($key), 'Boolean should be cast to string');
$this->assertTrue($this->_storage->setItem($key, false));
$this->assertEquals('', $this->_storage->getItem($key), 'Boolean should be cast to string');
}
public function testGetCapabilitiesTtl()
{
$resourceManager = $this->_options->getResourceManager();
$resourceId = $this->_options->getResourceId();
$redis = $resourceManager->getResource($resourceId);
$majorVersion = (int) $redis->info()['redis_version'];
$this->assertEquals($majorVersion, $resourceManager->getMajorVersion($resourceId));
$capabilities = $this->_storage->getCapabilities();
if ($majorVersion < 2) {
$this->assertEquals(0, $capabilities->getMinTtl(), 'Redis version < 2.0.0 does not support key expiration');
} else {
$this->assertEquals(1, $capabilities->getMinTtl(), 'Redis version > 2.0.0 supports key expiration');
}
}
/* ResourceManager */
public function testSocketConnection()
{
$socket = '/tmp/redis.sock';
$this->_options->getResourceManager()->setServer($this->_options->getResourceId(), $socket);
$normalized = $this->_options->getResourceManager()->getServer($this->_options->getResourceId());
$this->assertEquals($socket, $normalized['host'], 'Host should equal to socket {$socket}');
// Don't try to flush on shutdown
$this->_storage = null;
}
public function testGetSetDatabase()
{
$this->assertTrue($this->_storage->setItem('key', 'val'));
$this->assertEquals('val', $this->_storage->getItem('key'));
$databaseNumber = 1;
$resourceManager = $this->_options->getResourceManager();
$resourceManager->setDatabase($this->_options->getResourceId(), $databaseNumber);
$this->assertNull(
$this->_storage->getItem('key'),
'No value should be found because set was done on different database than get'
);
$this->assertEquals(
$databaseNumber,
$resourceManager->getDatabase($this->_options->getResourceId()),
'Incorrect database was returned'
);
}
public function testGetSetPassword()
{
$pass = 'super secret';
$this->_options->getResourceManager()->setPassword($this->_options->getResourceId(), $pass);
$this->assertEquals(
$pass,
$this->_options->getResourceManager()->getPassword($this->_options->getResourceId()),
'Password was not correctly set'
);
}
public function testGetSetLibOptionsOnExistingRedisResourceInstance()
{
$options = ['serializer' => RedisResource::SERIALIZER_PHP];
$this->_options->setLibOptions($options);
$value = ['value'];
$key = 'key';
//test if it's still possible to set/get item and if lib serializer works
$this->_storage->setItem($key, $value);
$this->assertEquals(
$value,
$this->_storage->getItem($key),
'Redis should return an array, lib options were not set correctly'
);
$options = ['serializer' => RedisResource::SERIALIZER_NONE];
$this->_options->setLibOptions($options);
$this->_storage->setItem($key, $value);
//should not serialize array correctly
$this->assertNotInternalType(
'array',
$this->_storage->getItem($key),
'Redis should not serialize automatically anymore, lib options were not set correctly'
);
}
public function testGetSetLibOptionsWithCleanRedisResourceInstance()
{
$options = ['serializer' => RedisResource::SERIALIZER_PHP];
$this->_options->setLibOptions($options);
$redis = new Cache\Storage\Adapter\Redis($this->_options);
$value = ['value'];
$key = 'key';
//test if it's still possible to set/get item and if lib serializer works
$redis->setItem($key, $value);
$this->assertEquals(
$value,
$redis->getItem($key),
'Redis should return an array, lib options were not set correctly'
);
$options = ['serializer' => RedisResource::SERIALIZER_NONE];
$this->_options->setLibOptions($options);
$redis->setItem($key, $value);
//should not serialize array correctly
$this->assertNotInternalType(
'array',
$redis->getItem($key),
'Redis should not serialize automatically anymore, lib options were not set correctly'
);
}
/* RedisOptions */
public function testGetSetNamespace()
{
$namespace = 'testNamespace';
$this->_options->setNamespace($namespace);
$this->assertEquals($namespace, $this->_options->getNamespace(), 'Namespace was not set correctly');
}
public function testGetSetNamespaceSeparator()
{
$separator = '/';
$this->_options->setNamespaceSeparator($separator);
$this->assertEquals($separator, $this->_options->getNamespaceSeparator(), 'Separator was not set correctly');
}
public function testGetSetResourceManager()
{
$resourceManager = new \Laminas\Cache\Storage\Adapter\RedisResourceManager();
$options = new \Laminas\Cache\Storage\Adapter\RedisOptions();
$options->setResourceManager($resourceManager);
$this->assertInstanceOf(
'Laminas\\Cache\\Storage\\Adapter\\RedisResourceManager',
$options->getResourceManager(),
'Wrong resource manager retuned, it should of type RedisResourceManager'
);
$this->assertEquals($resourceManager, $options->getResourceManager());
}
public function testGetSetResourceId()
{
$resourceId = '1';
$options = new \Laminas\Cache\Storage\Adapter\RedisOptions();
$options->setResourceId($resourceId);
$this->assertEquals($resourceId, $options->getResourceId(), 'Resource id was not set correctly');
}
public function testGetSetPersistentId()
{
$persistentId = '1';
$this->_options->setPersistentId($persistentId);
$this->assertEquals($persistentId, $this->_options->getPersistentId(), 'Persistent id was not set correctly');
}
public function testOptionsGetSetLibOptions()
{
$options = ['serializer' => RedisResource::SERIALIZER_PHP];
$this->_options->setLibOptions($options);
$this->assertEquals(
$options,
$this->_options->getLibOptions(),
'Lib Options were not set correctly through RedisOptions'
);
}
public function testGetSetServer()
{
$server = [
'host' => '127.0.0.1',
'port' => 6379,
'timeout' => 0,
];
$this->_options->setServer($server);
$this->assertEquals($server, $this->_options->getServer(), 'Server was not set correctly through RedisOptions');
// Don't try to flush on shutdown
$this->_storage = null;
}
public function testOptionsGetSetDatabase()
{
$database = 1;
$this->_options->setDatabase($database);
$this->assertEquals($database, $this->_options->getDatabase(), 'Database not set correctly using RedisOptions');
}
public function testOptionsGetSetPassword()
{
$password = 'my-secret';
$this->_options->setPassword($password);
$this->assertEquals(
$password,
$this->_options->getPassword(),
'Password was set incorrectly using RedisOptions'
);
}
public function testTouchItem()
{
$key = 'key';
// no TTL
$this->_storage->getOptions()->setTtl(0);
$this->_storage->setItem($key, 'val');
$this->assertEquals(0, $this->_storage->getMetadata($key)['ttl']);
// touch with a specific TTL will add this TTL
$ttl = 1000;
$this->_storage->getOptions()->setTtl($ttl);
$this->assertTrue($this->_storage->touchItem($key));
$this->assertEquals($ttl, ceil($this->_storage->getMetadata($key)['ttl']));
}
public function testHasItemReturnsFalseIfRedisExistsReturnsZero()
{
$redis = $this->mockInitializedRedisResource();
$redis->method('exists')->willReturn(0);
$adapter = $this->createAdapterFromResource($redis);
$hasItem = $adapter->hasItem('does-not-exist');
$this->assertFalse($hasItem);
}
public function testHasItemReturnsTrueIfRedisExistsReturnsNonZeroInt()
{
$redis = $this->mockInitializedRedisResource();
$redis->method('exists')->willReturn(23);
$adapter = $this->createAdapterFromResource($redis);
$hasItem = $adapter->hasItem('does-not-exist');
$this->assertTrue($hasItem);
}
/**
* @return Redis
*/
private function createAdapterFromResource(RedisResource $redis)
{
$resourceManager = new RedisResourceManager();
$resourceId = 'my-resource';
$resourceManager->setResource($resourceId, $redis);
$options = new RedisOptions(['resource_manager' => $resourceManager, 'resource_id' => $resourceId]);
return new Redis($options);
}
/**
* @return PHPUnit_Framework_MockObject_MockObject|RedisResource
*/
private function mockInitializedRedisResource()
{
$redis = $this->getMockBuilder(RedisResource::class)->getMock();
$redis->socket = true;
return $redis;
}
}
PK oYRpX &