From e9165aa0028ed08f84c1450bfb4cce4f00a00841 Mon Sep 17 00:00:00 2001 From: Javier Spagnoletti Date: Fri, 15 Mar 2019 22:40:55 -0300 Subject: [PATCH] Build custom Redis client based on the installed extension --- .travis.yml | 20 +- Client/Phpredis/Client.php | 1615 +-------------- Client/Phpredis/ClientBuilder.php | 139 ++ Client/Phpredis/ClientCacheWarmer.php | 55 + .../Configuration/Configuration.php | 6 +- DependencyInjection/SncRedisExtension.php | 16 +- Factory/PhpredisClientFactory.php | 6 +- Logger/RedisLogger.php | 8 +- Resources/client_templates/ClientV2.php.tpl | 1727 ++++++++++++++++ Resources/client_templates/ClientV3.php.tpl | 1809 +++++++++++++++++ Resources/client_templates/ClientV4.php.tpl | 114 ++ Resources/config/redis.xml | 6 + SncRedisBundle.php | 19 + Tests/Client/Phpredis/ClientTest.php | 8 +- .../SncRedisExtensionEnvTest.php | 11 +- Tests/Factory/PhpredisClientFactoryTest.php | 55 +- .../App/KernelWithCustomRedisClient.php | 38 + Tests/Functional/App/config.yaml | 3 + Tests/Functional/CustomPhpredisClientTest.php | 95 + Tests/Functional/IntegrationTest.php | 7 +- 20 files changed, 4058 insertions(+), 1699 deletions(-) create mode 100644 Client/Phpredis/ClientBuilder.php create mode 100644 Client/Phpredis/ClientCacheWarmer.php create mode 100644 Resources/client_templates/ClientV2.php.tpl create mode 100644 Resources/client_templates/ClientV3.php.tpl create mode 100644 Resources/client_templates/ClientV4.php.tpl create mode 100644 Tests/Functional/App/KernelWithCustomRedisClient.php create mode 100644 Tests/Functional/CustomPhpredisClientTest.php diff --git a/.travis.yml b/.travis.yml index ddbf9090..1a9f9f0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,22 @@ matrix: - php: 7.1 - php: 7.1 env: COMPOSER_FLAGS="--prefer-lowest" SYMFONY_DEPRECATIONS_HELPER="weak" + - php: 7.1 + env: SYMFONY_VERSION="4.0.*" REDIS_VERSION="3.1.6" + - php: 7.1 + env: SYMFONY_VERSION="4.1.*" REDIS_VERSION="3.1.6" + - php: 7.2 + env: REDIS_VERSION="4.3.0" + - php: 7.2 + env: SYMFONY_VERSION="4.0.*" REDIS_VERSION="4.3.0" + - php: 7.2 + env: SYMFONY_VERSION="4.1.*" REDIS_VERSION="4.3.0" - php: 7.2 + env: SYMFONY_VERSION="4.2.*" SYMFONY_DEPRECATIONS_HELPER="weak" STABILITY="dev" REDIS_VERSION="4.3.0" + - php: 7.3 + env: REDIS_VERSION="4.3.0" + - php: 7.3 + env: REDIS_VERSION="5.0.2" - php: 7.3 env: SYMFONY_VERSION="3.4.*" - php: 7.3 @@ -24,7 +39,7 @@ matrix: - php: nightly allow_failures: - php: nightly - - env: SYMFONY_VERSION="4.4.*" SYMFONY_DEPRECATIONS_HELPER="weak" STABILITY="dev" + - env: SYMFONY_VERSION="4.2.*" SYMFONY_DEPRECATIONS_HELPER="weak" STABILITY="dev" REDIS_VERSION="4.3.0" sudo: false @@ -40,8 +55,9 @@ env: before_install: - phpenv config-rm xdebug.ini || true - if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then echo "extension = redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi; - - php -i | grep -i --color=never "Redis Version" + - if [ "$REDIS_VERSION" != "" ]; then pecl bundle "redis-$REDIS_VERSION" && cd redis && phpize && pecl install igbinary && ./configure --enable-redis-igbinary CFLAGS=-Wall && cd ..; fi; - if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then phpenv rehash; fi; + - php -i | grep -i --color=never "Redis Version" - composer self-update - if ! [ -z "$STABILITY" ]; then composer config minimum-stability ${STABILITY}; fi; - if [ "$SYMFONY_VERSION" != "" ]; then composer require --no-update symfony/symfony:${SYMFONY_VERSION}; fi; diff --git a/Client/Phpredis/Client.php b/Client/Phpredis/Client.php index 746c5c46..b01eb46f 100644 --- a/Client/Phpredis/Client.php +++ b/Client/Phpredis/Client.php @@ -13,1619 +13,14 @@ namespace Snc\RedisBundle\Client\Phpredis; -use Redis; -use Snc\RedisBundle\Logger\RedisLogger; - -/** - * PHP Redis client with logger. - * - * @author Henrik Westphal - * @author Yassine Khial - * @author Pierre Boudelle - */ -class Client extends Redis -{ - /** - * @var RedisLogger - */ - protected $logger; - - /** - * @var string - */ - protected $alias; - - /** - * Constructor. - * - * @param array $parameters List of parameters (only `alias` key is handled) - * @param RedisLogger $logger A RedisLogger instance - */ - public function __construct(array $parameters = array(), RedisLogger $logger = null) - { - $this->logger = $logger; - $this->alias = isset($parameters['alias']) ? $parameters['alias'] : ''; - } - - /** - * Proxy function. - * - * @param string $name A command name - * @param array $arguments Lit of command arguments - * - * @throws \RuntimeException If no Redis instance is defined - * - * @return mixed - */ - private function call($name, array $arguments = array()) - { - $startTime = microtime(true); - $result = call_user_func_array("parent::$name", $arguments); - $duration = (microtime(true) - $startTime) * 1000; - - if (null !== $this->logger) { - $this->logger->logCommand($this->getCommandString($name, $arguments), $duration, $this->alias, false); - } - - return $result; - } - - /** - * Returns a string representation of the given command including arguments. - * - * @param string $command A command name - * @param array $arguments List of command arguments - * - * @return string - */ - private function getCommandString($command, array $arguments) - { - $list = array(); - $this->flatten($arguments, $list); - - return trim(strtoupper($command).' '.implode(' ', $list)); - } - +if (false) { /** - * Flatten arguments to single dimension array. + * @author Javier Spagnoletti * - * @param array $arguments An array of command arguments - * @param array $list Holder of results - */ - private function flatten($arguments, array &$list) - { - foreach ($arguments as $key => $item) { - if (!is_numeric($key)) { - $list[] = $key; - } - - if (is_scalar($item)) { - $list[] = strval($item); - } elseif (null === $item) { - $list[] = ''; - } else { - $this->flatten($item, $list); - } - } - } - - /** - * {@inheritdoc} - */ - public function connect($host, $port = 6379, $timeout = 0.0, $reserved = null, $retry_interval = 0, $read_timeout = 0.0) - { - return $this->call('connect', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function isConnected() - { - return $this->call('isConnected', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function open($host, $port = 6379, $timeout = 0.0, $reserved = null, $retry_interval = 0, $read_timeout = 0.0) - { - return $this->call('open', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function pconnect($host, $port = 6379, $timeout = 0.0, $persistent_id = null, $retry_interval = 0, $read_timeout = 0.0) - { - return $this->call('pconnect', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function popen($host, $port = 6379, $timeout = 0.0, $persistent_id = '', $retry_interval = 0, $read_timeout = 0.0) - { - return $this->call('popen', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function close() - { - return $this->call('close', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function setOption($name, $value) - { - return $this->call('setOption', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function getOption($name) - { - return $this->call('getOption', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function ping() - { - return $this->call('ping', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function get($key) - { - return $this->call('get', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function set($key, $value, $timeout = null) - { - return $this->call('set', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function setex($key, $ttl, $value) - { - return $this->call('setex', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function psetex($key, $ttl, $value) - { - return $this->call('psetex', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function setnx($key, $value) - { - return $this->call('setnx', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function del($key1, $key2 = null, $key3 = null) - { - return $this->call('del', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function delete($key1, $key2 = null, $key3 = null) - { - return $this->call('delete', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function unlink($key1, $key2 = null, $key3 = null) - { - return $this->call('unlink', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function multi($mode = Redis::MULTI) - { - return $this->call('multi', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function exec() - { - return $this->call('exec', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function discard() - { - return $this->call('discard', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function watch($key) - { - return $this->call('watch', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function unwatch() - { - return $this->call('unwatch', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function subscribe($channels, $callback) - { - return $this->call('subscribe', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function psubscribe($patterns, $callback) - { - return $this->call('psubscribe', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function publish($channel, $message) - { - return $this->call('publish', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function pubsub($keyword, $argument) - { - return $this->call('pubsub', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function unsubscribe($channels = null) - { - return $this->call('unsubscribe', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function punsubscribe($patterns = null) - { - return $this->call('punsubscribe', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function exists($key) - { - return $this->call('exists', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function incr($key) - { - return $this->call('incr', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function incrByFloat($key, $increment) - { - return $this->call('incrByFloat', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function incrBy($key, $value) - { - return $this->call('incrBy', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function decr($key) - { - return $this->call('decr', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function decrBy($key, $value) - { - return $this->call('decrBy', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function getMultiple(array $keys) - { - return $this->call('getMultiple', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lPush($key, $value1, $value2 = null, $valueN = null) - { - return $this->call('lPush', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function rPush($key, $value1, $value2 = null, $valueN = null) - { - return $this->call('rPush', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lPushx($key, $value) - { - return $this->call('lPushx', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function rPushx($key, $value) - { - return $this->call('rPushx', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lPop($key) - { - return $this->call('lPop', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function rPop($key) - { - return $this->call('rPop', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function blPop(array $keys, $timeout) - { - return $this->call('blPop', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function brPop(array $keys, $timeout) - { - return $this->call('brPop', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lLen($key) - { - return $this->call('lLen', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lSize($key) - { - return $this->call('lSize', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lIndex($key, $index) - { - return $this->call('lIndex', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lGet($key, $index) - { - return $this->call('lGet', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lSet($key, $index, $value) - { - return $this->call('lSet', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lRange($key, $start, $end) - { - return $this->call('lRange', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lGetRange($key, $start, $end) - { - return $this->call('lGetRange', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lTrim($key, $start, $stop) - { - return $this->call('lTrim', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function listTrim($key, $start, $stop) - { - return $this->call('listTrim', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lRem($key, $value, $count) - { - return $this->call('lRem', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lRemove($key, $value, $count) - { - return $this->call('lRemove', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lInsert($key, $position, $pivot, $value) - { - return $this->call('lInsert', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sAdd($key, $value1, $value2 = null, $valueN = null) - { - return $this->call('sAdd', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sRem($key, $member1, $member2 = null, $memberN = null) - { - return $this->call('sRem', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sRemove($key, $member1, $member2 = null, $memberN = null) - { - return $this->call('sRemove', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sMove($srcKey, $dstKey, $member) - { - return $this->call('sMove', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sIsMember($key, $value) - { - return $this->call('sIsMember', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sContains($key, $value) - { - return $this->call('sContains', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sCard($key) - { - return $this->call('sCard', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sPop($key) - { - return $this->call('sPop', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sRandMember($key, $count = null) - { - return $this->call('sRandMember', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sInter($key1, $key2, $keyN = null) - { - return $this->call('sInter', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sInterStore($dstKey, $key1, $key2, $keyN = null) - { - return $this->call('sInterStore', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sUnion($key1, $key2, $keyN = null) - { - return $this->call('sUnion', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sUnionStore($dstKey, $key1, $key2, $keyN = null) - { - return $this->call('sUnionStore', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sDiff($key1, $key2, $keyN = null) - { - return $this->call('sDiff', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sDiffStore($dstKey, $key1, $key2, $keyN = null) - { - return $this->call('sDiffStore', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sMembers($key) - { - return $this->call('sMembers', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sGetMembers($key) - { - return $this->call('sGetMembers', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sScan($key, &$iterator, $pattern = null, $count = 0) - { - return $this->call('sScan', array($key, &$iterator, $pattern, $count)); - } - - /** - * {@inheritdoc} - */ - public function getSet($key, $value) - { - return $this->call('getSet', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function randomKey() - { - return $this->call('randomKey', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function select($dbindex) - { - return $this->call('select', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function move($key, $dbindex) - { - return $this->call('move', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function rename($srcKey, $dstKey) - { - return $this->call('rename', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function renameKey($srcKey, $dstKey) - { - return $this->call('renameKey', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function renameNx($srcKey, $dstKey) - { - return $this->call('renameNx', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function expire($key, $ttl) - { - return $this->call('expire', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function pExpire($key, $ttl) - { - return $this->call('pExpire', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function setTimeout($key, $ttl) - { - return $this->call('setTimeout', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function expireAt($key, $timestamp) - { - return $this->call('expireAt', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function pExpireAt($key, $timestamp) - { - return $this->call('pExpireAt', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function keys($pattern) - { - return $this->call('keys', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function getKeys($pattern) - { - return $this->call('getKeys', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function dbSize() - { - return $this->call('dbSize', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function auth($password) - { - return $this->call('auth', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function bgrewriteaof() - { - return $this->call('bgrewriteaof', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function slaveof($host = '127.0.0.1', $port = 6379) - { - return $this->call('slaveof', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function object($string = '', $key = '') - { - return $this->call('object', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function save() - { - return $this->call('save', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function bgsave() - { - return $this->call('bgsave', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function lastSave() - { - return $this->call('lastSave', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function wait($numSlaves, $timeout) - { - return $this->call('wait', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function type($key) - { - return $this->call('type', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function append($key, $value) - { - return $this->call('append', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function getRange($key, $start, $end) - { - return $this->call('getRange', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function substr($key, $start, $end) - { - return $this->call('substr', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function setRange($key, $offset, $value) - { - return $this->call('setRange', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function strlen($key) - { - return $this->call('strlen', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function bitpos($key, $bit, $start = 0, $end = null) - { - return $this->call('bitpos', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function getBit($key, $offset) - { - return $this->call('getBit', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function setBit($key, $offset, $value) - { - return $this->call('setBit', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function bitCount($key) - { - return $this->call('bitCount', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function bitOp($operation, $retKey, $key1, $key2, $key3 = null) - { - return $this->call('bitOp', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function flushDB() - { - return $this->call('flushDB', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function flushAll() - { - return $this->call('flushAll', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function sort($key, $option = null) - { - return $this->call('sort', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function info($option = null) - { - return $this->call('info', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function resetStat() - { - return $this->call('resetStat', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function ttl($key) - { - return $this->call('ttl', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function pttl($key) - { - return $this->call('pttl', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function persist($key) - { - return $this->call('persist', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function mset(array $array) - { - return $this->call('mset', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function mget(array $array) - { - return $this->call('mget', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function msetnx(array $array) - { - return $this->call('msetnx', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function rpoplpush($srcKey, $dstKey) - { - return $this->call('rpoplpush', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function brpoplpush($srcKey, $dstKey, $timeout) - { - return $this->call('brpoplpush', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zAdd($key, $score1, $value1, $score2 = null, $value2 = null, $scoreN = null, $valueN = null) - { - return $this->call('zAdd', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRange($key, $start, $end, $withscores = null) - { - return $this->call('zRange', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRem($key, $member1, $member2 = null, $memberN = null) - { - return $this->call('zRem', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zDelete($key, $member1, $member2 = null, $memberN = null) - { - return $this->call('zDelete', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRevRange($key, $start, $end, $withscore = null) - { - return $this->call('zRevRange', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRangeByScore($key, $start, $end, array $options = array()) - { - return $this->call('zRangeByScore', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRevRangeByScore($key, $start, $end, array $options = array()) - { - return $this->call('zRevRangeByScore', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRangeByLex($key, $min, $max, $offset = null, $limit = null) - { - return $this->call('zRangeByLex', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRevRangeByLex($key, $min, $max, $offset = null, $limit = null) - { - return $this->call('zRevRangeByLex', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zCount($key, $start, $end) - { - return $this->call('zCount', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRemRangeByScore($key, $start, $end) - { - return $this->call('zRemRangeByScore', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zDeleteRangeByScore($key, $start, $end) - { - return $this->call('zDeleteRangeByScore', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRemRangeByRank($key, $start, $end) - { - return $this->call('zRemRangeByRank', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zDeleteRangeByRank($key, $start, $end) - { - return $this->call('zDeleteRangeByRank', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zCard($key) - { - return $this->call('zCard', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zSize($key) - { - return $this->call('zSize', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zScore($key, $member) - { - return $this->call('zScore', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRank($key, $member) - { - return $this->call('zRank', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zRevRank($key, $member) - { - return $this->call('zRevRank', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zIncrBy($key, $value, $member) - { - return $this->call('zIncrBy', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zUnion($Output, $ZSetKeys, array $Weights = null, $aggregateFunction = 'SUM') - { - return $this->call('zUnion', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zInter($Output, $ZSetKeys, array $Weights = null, $aggregateFunction = 'SUM') - { - return $this->call('zInter', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function zScan($key, &$iterator, $pattern = null, $count = 0) - { - return $this->call('zScan', array($key, &$iterator, $pattern, $count)); - } - - /** - * {@inheritdoc} - */ - public function hSet($key, $hashKey, $value) - { - return $this->call('hSet', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hSetNx($key, $hashKey, $value) - { - return $this->call('hSetNx', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hGet($key, $hashKey) - { - return $this->call('hGet', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hLen($key) - { - return $this->call('hLen', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hDel($key, $hashKey1, $hashKey2 = null, $hashKeyN = null) - { - return $this->call('hDel', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hKeys($key) - { - return $this->call('hKeys', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hVals($key) - { - return $this->call('hVals', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hGetAll($key) - { - return $this->call('hGetAll', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hExists($key, $hashKey) - { - return $this->call('hExists', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hIncrBy($key, $hashKey, $value) - { - return $this->call('hIncrBy', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hIncrByFloat($key, $field, $increment) - { - return $this->call('hIncrByFloat', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hMSet($key, $hashKeys) - { - return $this->call('hMSet', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hMGet($key, $hashKeys) - { - return $this->call('hMGet', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function hScan($key, &$iterator, $pattern = null, $count = 0) - { - return $this->call('hScan', array($key, &$iterator, $pattern, $count)); - } - - /** - * {@inheritdoc} - */ - public function config($operation, $key, $value) - { - return $this->call('config', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function evaluate($script, $args = array(), $numKeys = 0) - { - return $this->call('evaluate', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function evalSha($scriptSha, $args = array(), $numKeys = 0) - { - return $this->call('evalSha', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function evaluateSha($scriptSha, $args = array(), $numKeys = 0) - { - return $this->call('evaluateSha', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function script($command, $script) - { - return $this->call('script', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function getLastError() - { - return $this->call('getLastError', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function clearLastError() - { - return $this->call('clearLastError', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function _prefix($value) - { - return $this->call('_prefix', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function _unserialize($value) - { - return $this->call('_unserialize', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function _serialize($value) - { - return $this->call('_serialize', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function dump($key) - { - return $this->call('dump', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function restore($key, $ttl, $value) - { - return $this->call('restore', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function migrate($host, $port, $key, $db, $timeout, $copy = false, $replace = false) - { - return $this->call('migrate', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function time() - { - return $this->call('time', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function scan(&$iterator, $pattern = null, $count = 0) - { - return $this->call('scan', array(&$iterator, $pattern, $count)); - } - - /** - * {@inheritdoc} - */ - public function pfAdd($key, array $elements) - { - return $this->call('pfAdd', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function pfCount($key) - { - return $this->call('pfCount', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function pfMerge($destkey, array $sourcekeys) - { - return $this->call('pfMerge', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function rawCommand($command, $arguments) - { - return $this->call('rawCommand', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function getMode() - { - return $this->call('getMode', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xAck($stream, $group, $arr_messages) - { - return $this->call('xAck', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xAdd($str_key, $str_id, $arr_message) - { - return $this->call('xAdd', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xClaim($str_key, $str_group, $str_consumer, $min_idle_time, $arr_ids, $arr_options = []) - { - return $this->call('xClaim', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xDel($str_key, $arr_ids) - { - return $this->call('xDel', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xGroup($operation, $str_key, $str_group, $str_msg_id) - { - return $this->call('xGroup', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xInfo($operation, $str_stream, $str_group) - { - return $this->call('xInfo', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xLen($str_stream) - { - return $this->call('xLen', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xPending($str_stream, $str_group, $str_start = null, $str_end = null, $i_count = null, $str_consumer = null) - { - return $this->call('xPending', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xRange($str_stream, $str_start, $str_end, $i_count = null) - { - return $this->call('xRange', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xRead($arr_streams, $i_count = null, $i_block = null) - { - return $this->call('xRead', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xReadGroup($str_group, $str_consumer, $arr_streams, $i_count, $i_block = null) - { - return $this->call('xReadGroup', func_get_args()); - } - - /** - * {@inheritdoc} - */ - public function xRevRange($str_stream, $str_end, $str_start, $i_count = null) - { - return $this->call('xRevRange', func_get_args()); - } - - /** - * {@inheritdoc} + * The real class is generated dynamically during cache warmup based on the + * installed Redis version. */ - public function xTrim($str_stream, $i_max_len, $boo_approximate) + final class Client extends \Redis { - return $this->call('xTrim', func_get_args()); } } diff --git a/Client/Phpredis/ClientBuilder.php b/Client/Phpredis/ClientBuilder.php new file mode 100644 index 00000000..01c20bef --- /dev/null +++ b/Client/Phpredis/ClientBuilder.php @@ -0,0 +1,139 @@ + + * (c) Yassine Khial + * (c) Pierre Boudelle + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Snc\RedisBundle\Client\Phpredis; + +/** + * @author Javier Spagnoletti + */ +final class ClientBuilder +{ + private $redisClass; + + /** + * @param string $redisClass + */ + public function __construct($redisClass = '\Redis') + { + $this->redisClass = $redisClass; + } + + /** + * @return srting + */ + public function getClassContents() + { + $templatesDir = __DIR__.'/../../Resources/client_templates/'; + $version = phpversion('redis'); + if (version_compare($version, '4.0.0') >= 0) { + $template = file_get_contents($templatesDir.'ClientV4.php.tpl'); + $template = str_replace(['{{version}}', '{{public_methods}}'], [phpversion('redis'), $this->generateRedisMethods()], $template); + } elseif (version_compare($version, '3.0.0') >= 0) { + $template = file_get_contents($templatesDir.'ClientV3.php.tpl'); + } elseif (version_compare($version, '2.0.0') >= 0) { + $template = file_get_contents($templatesDir.'ClientV2.php.tpl'); + } + + return str_replace('{{extended_classname}}', $this->redisClass, $template); + } + + /** + * @return srting + */ + private function generateRedisMethods() + { + $methods = ''; + $rc = new \ReflectionClass($this->redisClass); + $reflectedMethods = $rc->getMethods(\ReflectionMethod::IS_PUBLIC); + + /* @var $reflectedMethod \ReflectionMethod */ + foreach ($reflectedMethods as $reflectedMethod) { + if ($reflectedMethod->isFinal() || $reflectedMethod->isConstructor()) { + continue; + } + + $method = "\n /**\n"; + $method .= " * {@inheritdoc}\n"; + $method .= " */\n"; + + $method .= ' '; + + if ($reflectedMethod->isAbstract()) { + $method .= 'abstract '; + } + $method .= 'public '; + if ($reflectedMethod->isStatic()) { + $method .= 'static '; + } + $method .= 'function '; + $method .= $reflectedMethod->getName(); + $method .= '('; + $args = $reflectedMethod->getParameters(); + /* @var $rp \ReflectionParameter */ + foreach ($args as $rp) { + if ($rp->getType()) { + $method .= $rp->getType(); + $method .= ' '; + } + $isVariadic = false; + if ($rp->isVariadic()) { + $method .= '...'; + $isVariadic = true; + } + if ($rp->isPassedByReference()) { + $method .= '&'; + } + $method .= '$'; + $method .= $rp->getName(); + if ($rp->isDefaultValueAvailable() || $rp->isOptional() && !$isVariadic) { + $method .= ' = '; + $method .= $rp->isDefaultValueAvailable() ? $rp->getDefaultValue() : 'null'; + } + if ($rp->getPosition() < count($reflectedMethod->getParameters()) - 1) { + $method .= ', '; + } + } + + $method .= ')'; + + if ($reflectedMethod->hasReturnType()) { + $method .= ': '; + $method .= $reflectedMethod->getReturnType(); + } + + $method .= "\n"; + $method .= " {\n"; + $method .= ' return $this->call(\''.$reflectedMethod->getName().'\''; + if (count($args)) { + $method .= ', array('; + foreach ($args as $rp) { + if ($rp->isPassedByReference()) { + $method .= '&'; + } + $method .= '$'; + $method .= $rp->getName(); + if ($rp->getPosition() < count($reflectedMethod->getParameters()) - 1) { + $method .= ', '; + } + } + $method .= ')'; + } + $method .= ");\n"; + $method .= " }\n"; + + $methods .= $method; + } + + return $methods; + } +} diff --git a/Client/Phpredis/ClientCacheWarmer.php b/Client/Phpredis/ClientCacheWarmer.php new file mode 100644 index 00000000..3aee106b --- /dev/null +++ b/Client/Phpredis/ClientCacheWarmer.php @@ -0,0 +1,55 @@ + + * (c) Yassine Khial + * (c) Pierre Boudelle + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Snc\RedisBundle\Client\Phpredis; + +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; + +/** + * @author Javier Spagnoletti + */ +class ClientCacheWarmer implements CacheWarmerInterface +{ + /** + * @var ClientBuilder + */ + private $clientBuilder; + + public function __construct(ClientBuilder $clientBuilder) + { + $this->clientBuilder = $clientBuilder; + } + + /** + * {@inheritdoc} + */ + public function isOptional() + { + return !class_exists(\Redis::class) || class_exists(Client::class); + } + + /** + * {@inheritdoc} + */ + public function warmUp($cacheDir) + { + if (!class_exists(\Redis::class)) { + return; + } + + $filename = $cacheDir.'/snc_phpredis_client.php'; + + file_put_contents($filename, $this->clientBuilder->getClassContents()); + @chmod($filename, 0664); + } +} diff --git a/DependencyInjection/Configuration/Configuration.php b/DependencyInjection/Configuration/Configuration.php index 99ffbb5b..5cfc65f9 100644 --- a/DependencyInjection/Configuration/Configuration.php +++ b/DependencyInjection/Configuration/Configuration.php @@ -27,7 +27,7 @@ class Configuration implements ConfigurationInterface public function __construct($debug) { - $this->debug = (Boolean) $debug; + $this->debug = (bool) $debug; } /** @@ -85,8 +85,6 @@ public function getConfigTreeBuilder() */ private function addClientsSection(ArrayNodeDefinition $rootNode) { - $loggingDefault = (version_compare(phpversion('redis'), '4.0.0') >= 0 ? false : $this->debug); - $rootNode ->fixXmlConfig('client') ->children() @@ -108,7 +106,7 @@ private function addClientsSection(ArrayNodeDefinition $rootNode) ->children() ->scalarNode('type')->isRequired()->end() ->scalarNode('alias')->isRequired()->end() - ->booleanNode('logging')->defaultValue($loggingDefault)->end() + ->booleanNode('logging')->defaultValue($this->debug)->end() ->arrayNode('dsns') ->isRequired() ->performNoDeepMerging() diff --git a/DependencyInjection/SncRedisExtension.php b/DependencyInjection/SncRedisExtension.php index d9c91040..71f93f71 100644 --- a/DependencyInjection/SncRedisExtension.php +++ b/DependencyInjection/SncRedisExtension.php @@ -262,10 +262,6 @@ protected function loadPhpredisClient(array $client, ContainerBuilder $container $dsn = $client['dsns'][0]; $phpRedisVersion = phpversion('redis'); - if (version_compare($phpRedisVersion, '4.0.0') >= 0 && $client['logging']) { - $client['logging'] = false; - @trigger_error(sprintf('Redis logging is not supported on PhpRedis %s and has been automatically disabled, disable logging in config to suppress this warning', $phpRedisVersion), E_USER_WARNING); - } $phpredisClientclass = $container->getParameter('snc_redis.phpredis_client.class'); if ($client['logging']) { @@ -282,17 +278,7 @@ protected function loadPhpredisClient(array $client, ContainerBuilder $container $phpredisDef->addArgument($client['alias']); $phpredisDef->addTag('snc_redis.client', array('alias' => $client['alias'])); $phpredisDef->setPublic(false); - - // Older version of phpredis extension do not support lazy loading - $minimumVersionForLazyLoading = '4.1.1'; - $supportsLazyServices = version_compare($phpRedisVersion, $minimumVersionForLazyLoading, '>='); - $phpredisDef->setLazy($supportsLazyServices); - if (!$supportsLazyServices) { - @trigger_error( - sprintf('Lazy loading Redis is not supported on PhpRedis %s. Please update to PhpRedis %s or higher.', $phpRedisVersion, $minimumVersionForLazyLoading), - E_USER_WARNING - ); - } + $phpredisDef->setLazy(true); $phpredisId = sprintf('snc_redis.%s', $client['alias']); $container->setDefinition($phpredisId, $phpredisDef); diff --git a/Factory/PhpredisClientFactory.php b/Factory/PhpredisClientFactory.php index 0618e6d1..03058254 100644 --- a/Factory/PhpredisClientFactory.php +++ b/Factory/PhpredisClientFactory.php @@ -33,7 +33,7 @@ public function __construct(RedisLogger $logger = null) */ public function create($class, $dsn, $options, $alias) { - if (!is_a($class, '\Redis', true)) { + if (!is_a($class, \Redis::class, true)) { throw new \RuntimeException(sprintf('The factory can only instantiate \Redis classes: %s asked', $class)); } @@ -97,7 +97,7 @@ public function create($class, $dsn, $options, $alias) */ private function createClient($class, $alias) { - if (is_a($class, '\Snc\RedisBundle\Client\Phpredis\Client', true)) { + if (is_a($class, Client::class, true)) { $client = new $class(array('alias' => $alias), $this->logger); } else { $client = new $class(); @@ -122,7 +122,7 @@ private function loadSerializationType($type) 'php' => \Redis::SERIALIZER_PHP ); - if (defined('Redis::SERIALIZER_IGBINARY')) { + if (defined('\Redis::SERIALIZER_IGBINARY')) { $types['igbinary'] = \Redis::SERIALIZER_IGBINARY; } diff --git a/Logger/RedisLogger.php b/Logger/RedisLogger.php index 5ae91203..f8fe87a1 100644 --- a/Logger/RedisLogger.php +++ b/Logger/RedisLogger.php @@ -25,14 +25,10 @@ class RedisLogger /** * Constructor. * - * @param PsrLoggerInterface $logger A LoggerInterface instance + * @param PsrLoggerInterface|null $logger A LoggerInterface instance */ - public function __construct($logger = null) + public function __construct(PsrLoggerInterface $logger = null) { - if (!$logger instanceof PsrLoggerInterface && null !== $logger) { - throw new \InvalidArgumentException(sprintf('RedisLogger needs a PSR-3 LoggerInterface, "%s" was injected instead.', is_object($logger) ? get_class($logger) : gettype($logger))); - } - $this->logger = $logger; } diff --git a/Resources/client_templates/ClientV2.php.tpl b/Resources/client_templates/ClientV2.php.tpl new file mode 100644 index 00000000..90cb6113 --- /dev/null +++ b/Resources/client_templates/ClientV2.php.tpl @@ -0,0 +1,1727 @@ + + * (c) Yassine Khial + * (c) Pierre Boudelle + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Snc\RedisBundle\Client\Phpredis; +use Redis; +use Snc\RedisBundle\Logger\RedisLogger; +/** + * PHP Redis client with logger. + * + * @author Henrik Westphal + * @author Yassine Khial + * @author Pierre Boudelle + */ +class Client extends Redis +{ + const REDIS_VER = '2.2.8'; + + /** + * @var RedisLogger + */ + protected $logger; + /** + * @var string + */ + protected $alias; + /** + * Constructor. + * + * @param array $parameters List of parameters (only `alias` key is handled) + * @param RedisLogger $logger A RedisLogger instance + */ + public function __construct(array $parameters = array(), RedisLogger $logger = null) + { + $this->logger = $logger; + $this->alias = isset($parameters['alias']) ? $parameters['alias'] : ''; + } + + /** + * {@inheritdoc} + */ + public function __destruct() + { + return $this->call('__destruct'); + } + + /** + * {@inheritdoc} + */ + public function connect() + { + return $this->call('connect'); + } + + /** + * {@inheritdoc} + */ + public function pconnect() + { + return $this->call('pconnect'); + } + + /** + * {@inheritdoc} + */ + public function close() + { + return $this->call('close'); + } + + /** + * {@inheritdoc} + */ + public function ping() + { + return $this->call('ping'); + } + + /** + * {@inheritdoc} + */ + public function get() + { + return $this->call('get'); + } + + /** + * {@inheritdoc} + */ + public function set() + { + return $this->call('set'); + } + + /** + * {@inheritdoc} + */ + public function setex() + { + return $this->call('setex'); + } + + /** + * {@inheritdoc} + */ + public function psetex() + { + return $this->call('psetex'); + } + + /** + * {@inheritdoc} + */ + public function setnx() + { + return $this->call('setnx'); + } + + /** + * {@inheritdoc} + */ + public function getSet() + { + return $this->call('getSet'); + } + + /** + * {@inheritdoc} + */ + public function randomKey() + { + return $this->call('randomKey'); + } + + /** + * {@inheritdoc} + */ + public function renameKey() + { + return $this->call('renameKey'); + } + + /** + * {@inheritdoc} + */ + public function renameNx() + { + return $this->call('renameNx'); + } + + /** + * {@inheritdoc} + */ + public function getMultiple() + { + return $this->call('getMultiple'); + } + + /** + * {@inheritdoc} + */ + public function exists() + { + return $this->call('exists'); + } + + /** + * {@inheritdoc} + */ + public function delete() + { + return $this->call('delete'); + } + + /** + * {@inheritdoc} + */ + public function incr() + { + return $this->call('incr'); + } + + /** + * {@inheritdoc} + */ + public function incrBy() + { + return $this->call('incrBy'); + } + + /** + * {@inheritdoc} + */ + public function incrByFloat() + { + return $this->call('incrByFloat'); + } + + /** + * {@inheritdoc} + */ + public function decr() + { + return $this->call('decr'); + } + + /** + * {@inheritdoc} + */ + public function decrBy() + { + return $this->call('decrBy'); + } + + /** + * {@inheritdoc} + */ + public function type() + { + return $this->call('type'); + } + + /** + * {@inheritdoc} + */ + public function append() + { + return $this->call('append'); + } + + /** + * {@inheritdoc} + */ + public function getRange() + { + return $this->call('getRange'); + } + + /** + * {@inheritdoc} + */ + public function setRange() + { + return $this->call('setRange'); + } + + /** + * {@inheritdoc} + */ + public function getBit() + { + return $this->call('getBit'); + } + + /** + * {@inheritdoc} + */ + public function setBit() + { + return $this->call('setBit'); + } + + /** + * {@inheritdoc} + */ + public function strlen() + { + return $this->call('strlen'); + } + + /** + * {@inheritdoc} + */ + public function getKeys() + { + return $this->call('getKeys'); + } + + /** + * {@inheritdoc} + */ + public function sort() + { + return $this->call('sort'); + } + + /** + * {@inheritdoc} + */ + public function sortAsc() + { + return $this->call('sortAsc'); + } + + /** + * {@inheritdoc} + */ + public function sortAscAlpha() + { + return $this->call('sortAscAlpha'); + } + + /** + * {@inheritdoc} + */ + public function sortDesc() + { + return $this->call('sortDesc'); + } + + /** + * {@inheritdoc} + */ + public function sortDescAlpha() + { + return $this->call('sortDescAlpha'); + } + + /** + * {@inheritdoc} + */ + public function lPush() + { + return $this->call('lPush'); + } + + /** + * {@inheritdoc} + */ + public function rPush() + { + return $this->call('rPush'); + } + + /** + * {@inheritdoc} + */ + public function lPushx() + { + return $this->call('lPushx'); + } + + /** + * {@inheritdoc} + */ + public function rPushx() + { + return $this->call('rPushx'); + } + + /** + * {@inheritdoc} + */ + public function lPop() + { + return $this->call('lPop'); + } + + /** + * {@inheritdoc} + */ + public function rPop() + { + return $this->call('rPop'); + } + + /** + * {@inheritdoc} + */ + public function blPop() + { + return $this->call('blPop'); + } + + /** + * {@inheritdoc} + */ + public function brPop() + { + return $this->call('brPop'); + } + + /** + * {@inheritdoc} + */ + public function lSize() + { + return $this->call('lSize'); + } + + /** + * {@inheritdoc} + */ + public function lRemove() + { + return $this->call('lRemove'); + } + + /** + * {@inheritdoc} + */ + public function listTrim() + { + return $this->call('listTrim'); + } + + /** + * {@inheritdoc} + */ + public function lGet() + { + return $this->call('lGet'); + } + + /** + * {@inheritdoc} + */ + public function lGetRange() + { + return $this->call('lGetRange'); + } + + /** + * {@inheritdoc} + */ + public function lSet() + { + return $this->call('lSet'); + } + + /** + * {@inheritdoc} + */ + public function lInsert() + { + return $this->call('lInsert'); + } + + /** + * {@inheritdoc} + */ + public function sAdd() + { + return $this->call('sAdd'); + } + + /** + * {@inheritdoc} + */ + public function sAddArray() + { + return $this->call('sAddArray'); + } + + /** + * {@inheritdoc} + */ + public function sSize() + { + return $this->call('sSize'); + } + + /** + * {@inheritdoc} + */ + public function sRemove() + { + return $this->call('sRemove'); + } + + /** + * {@inheritdoc} + */ + public function sMove() + { + return $this->call('sMove'); + } + + /** + * {@inheritdoc} + */ + public function sPop() + { + return $this->call('sPop'); + } + + /** + * {@inheritdoc} + */ + public function sRandMember() + { + return $this->call('sRandMember'); + } + + /** + * {@inheritdoc} + */ + public function sContains() + { + return $this->call('sContains'); + } + + /** + * {@inheritdoc} + */ + public function sMembers() + { + return $this->call('sMembers'); + } + + /** + * {@inheritdoc} + */ + public function sInter() + { + return $this->call('sInter'); + } + + /** + * {@inheritdoc} + */ + public function sInterStore() + { + return $this->call('sInterStore'); + } + + /** + * {@inheritdoc} + */ + public function sUnion() + { + return $this->call('sUnion'); + } + + /** + * {@inheritdoc} + */ + public function sUnionStore() + { + return $this->call('sUnionStore'); + } + + /** + * {@inheritdoc} + */ + public function sDiff() + { + return $this->call('sDiff'); + } + + /** + * {@inheritdoc} + */ + public function sDiffStore() + { + return $this->call('sDiffStore'); + } + + /** + * {@inheritdoc} + */ + public function setTimeout() + { + return $this->call('setTimeout'); + } + + /** + * {@inheritdoc} + */ + public function save() + { + return $this->call('save'); + } + + /** + * {@inheritdoc} + */ + public function bgSave() + { + return $this->call('bgSave'); + } + + /** + * {@inheritdoc} + */ + public function lastSave() + { + return $this->call('lastSave'); + } + + /** + * {@inheritdoc} + */ + public function flushDB() + { + return $this->call('flushDB'); + } + + /** + * {@inheritdoc} + */ + public function flushAll() + { + return $this->call('flushAll'); + } + + /** + * {@inheritdoc} + */ + public function dbSize() + { + return $this->call('dbSize'); + } + + /** + * {@inheritdoc} + */ + public function auth() + { + return $this->call('auth'); + } + + /** + * {@inheritdoc} + */ + public function ttl() + { + return $this->call('ttl'); + } + + /** + * {@inheritdoc} + */ + public function pttl() + { + return $this->call('pttl'); + } + + /** + * {@inheritdoc} + */ + public function persist() + { + return $this->call('persist'); + } + + /** + * {@inheritdoc} + */ + public function info() + { + return $this->call('info'); + } + + /** + * {@inheritdoc} + */ + public function select() + { + return $this->call('select'); + } + + /** + * {@inheritdoc} + */ + public function move() + { + return $this->call('move'); + } + + /** + * {@inheritdoc} + */ + public function bgrewriteaof() + { + return $this->call('bgrewriteaof'); + } + + /** + * {@inheritdoc} + */ + public function slaveof() + { + return $this->call('slaveof'); + } + + /** + * {@inheritdoc} + */ + public function object() + { + return $this->call('object'); + } + + /** + * {@inheritdoc} + */ + public function bitop() + { + return $this->call('bitop'); + } + + /** + * {@inheritdoc} + */ + public function bitcount() + { + return $this->call('bitcount'); + } + + /** + * {@inheritdoc} + */ + public function bitpos() + { + return $this->call('bitpos'); + } + + /** + * {@inheritdoc} + */ + public function mset() + { + return $this->call('mset'); + } + + /** + * {@inheritdoc} + */ + public function msetnx() + { + return $this->call('msetnx'); + } + + /** + * {@inheritdoc} + */ + public function rpoplpush() + { + return $this->call('rpoplpush'); + } + + /** + * {@inheritdoc} + */ + public function brpoplpush() + { + return $this->call('brpoplpush'); + } + + /** + * {@inheritdoc} + */ + public function zAdd() + { + return $this->call('zAdd'); + } + + /** + * {@inheritdoc} + */ + public function zDelete() + { + return $this->call('zDelete'); + } + + /** + * {@inheritdoc} + */ + public function zRange() + { + return $this->call('zRange'); + } + + /** + * {@inheritdoc} + */ + public function zRevRange() + { + return $this->call('zRevRange'); + } + + /** + * {@inheritdoc} + */ + public function zRangeByScore() + { + return $this->call('zRangeByScore'); + } + + /** + * {@inheritdoc} + */ + public function zRevRangeByScore() + { + return $this->call('zRevRangeByScore'); + } + + /** + * {@inheritdoc} + */ + public function zRangeByLex() + { + return $this->call('zRangeByLex'); + } + + /** + * {@inheritdoc} + */ + public function zRevRangeByLex() + { + return $this->call('zRevRangeByLex'); + } + + /** + * {@inheritdoc} + */ + public function zLexCount() + { + return $this->call('zLexCount'); + } + + /** + * {@inheritdoc} + */ + public function zRemRangeByLex() + { + return $this->call('zRemRangeByLex'); + } + + /** + * {@inheritdoc} + */ + public function zCount() + { + return $this->call('zCount'); + } + + /** + * {@inheritdoc} + */ + public function zDeleteRangeByScore() + { + return $this->call('zDeleteRangeByScore'); + } + + /** + * {@inheritdoc} + */ + public function zDeleteRangeByRank() + { + return $this->call('zDeleteRangeByRank'); + } + + /** + * {@inheritdoc} + */ + public function zCard() + { + return $this->call('zCard'); + } + + /** + * {@inheritdoc} + */ + public function zScore() + { + return $this->call('zScore'); + } + + /** + * {@inheritdoc} + */ + public function zRank() + { + return $this->call('zRank'); + } + + /** + * {@inheritdoc} + */ + public function zRevRank() + { + return $this->call('zRevRank'); + } + + /** + * {@inheritdoc} + */ + public function zInter() + { + return $this->call('zInter'); + } + + /** + * {@inheritdoc} + */ + public function zUnion() + { + return $this->call('zUnion'); + } + + /** + * {@inheritdoc} + */ + public function zIncrBy() + { + return $this->call('zIncrBy'); + } + + /** + * {@inheritdoc} + */ + public function expireAt() + { + return $this->call('expireAt'); + } + + /** + * {@inheritdoc} + */ + public function pexpire() + { + return $this->call('pexpire'); + } + + /** + * {@inheritdoc} + */ + public function pexpireAt() + { + return $this->call('pexpireAt'); + } + + /** + * {@inheritdoc} + */ + public function hGet() + { + return $this->call('hGet'); + } + + /** + * {@inheritdoc} + */ + public function hSet() + { + return $this->call('hSet'); + } + + /** + * {@inheritdoc} + */ + public function hSetNx() + { + return $this->call('hSetNx'); + } + + /** + * {@inheritdoc} + */ + public function hDel() + { + return $this->call('hDel'); + } + + /** + * {@inheritdoc} + */ + public function hLen() + { + return $this->call('hLen'); + } + + /** + * {@inheritdoc} + */ + public function hKeys() + { + return $this->call('hKeys'); + } + + /** + * {@inheritdoc} + */ + public function hVals() + { + return $this->call('hVals'); + } + + /** + * {@inheritdoc} + */ + public function hGetAll() + { + return $this->call('hGetAll'); + } + + /** + * {@inheritdoc} + */ + public function hExists() + { + return $this->call('hExists'); + } + + /** + * {@inheritdoc} + */ + public function hIncrBy() + { + return $this->call('hIncrBy'); + } + + /** + * {@inheritdoc} + */ + public function hIncrByFloat() + { + return $this->call('hIncrByFloat'); + } + + /** + * {@inheritdoc} + */ + public function hMset() + { + return $this->call('hMset'); + } + + /** + * {@inheritdoc} + */ + public function hMget() + { + return $this->call('hMget'); + } + + /** + * {@inheritdoc} + */ + public function multi() + { + return $this->call('multi'); + } + + /** + * {@inheritdoc} + */ + public function discard() + { + return $this->call('discard'); + } + + /** + * {@inheritdoc} + */ + public function exec() + { + return $this->call('exec'); + } + + /** + * {@inheritdoc} + */ + public function pipeline() + { + return $this->call('pipeline'); + } + + /** + * {@inheritdoc} + */ + public function watch() + { + return $this->call('watch'); + } + + /** + * {@inheritdoc} + */ + public function unwatch() + { + return $this->call('unwatch'); + } + + /** + * {@inheritdoc} + */ + public function publish() + { + return $this->call('publish'); + } + + /** + * {@inheritdoc} + */ + public function subscribe() + { + return $this->call('subscribe'); + } + + /** + * {@inheritdoc} + */ + public function psubscribe() + { + return $this->call('psubscribe'); + } + + /** + * {@inheritdoc} + */ + public function unsubscribe() + { + return $this->call('unsubscribe'); + } + + /** + * {@inheritdoc} + */ + public function punsubscribe() + { + return $this->call('punsubscribe'); + } + + /** + * {@inheritdoc} + */ + public function time() + { + return $this->call('time'); + } + + /** + * {@inheritdoc} + */ + public function role() + { + return $this->call('role'); + } + + /** + * {@inheritdoc} + */ + public function evalsha() + { + return $this->call('evalsha'); + } + + /** + * {@inheritdoc} + */ + public function script() + { + return $this->call('script'); + } + + /** + * {@inheritdoc} + */ + public function debug() + { + return $this->call('debug'); + } + + /** + * {@inheritdoc} + */ + public function dump() + { + return $this->call('dump'); + } + + /** + * {@inheritdoc} + */ + public function restore() + { + return $this->call('restore'); + } + + /** + * {@inheritdoc} + */ + public function migrate() + { + return $this->call('migrate'); + } + + /** + * {@inheritdoc} + */ + public function getLastError() + { + return $this->call('getLastError'); + } + + /** + * {@inheritdoc} + */ + public function clearLastError() + { + return $this->call('clearLastError'); + } + + /** + * {@inheritdoc} + */ + public function _prefix() + { + return $this->call('_prefix'); + } + + /** + * {@inheritdoc} + */ + public function _serialize() + { + return $this->call('_serialize'); + } + + /** + * {@inheritdoc} + */ + public function _unserialize() + { + return $this->call('_unserialize'); + } + + /** + * {@inheritdoc} + */ + public function client() + { + return $this->call('client'); + } + + /** + * {@inheritdoc} + */ + public function command() + { + return $this->call('command'); + } + + /** + * {@inheritdoc} + */ + public function scan(&$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->call('scan', array(&$i_iterator, $str_pattern, $i_count)); + } + + /** + * {@inheritdoc} + */ + public function hscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->call('hscan', array($str_key, &$i_iterator, $str_pattern, $i_count)); + } + + /** + * {@inheritdoc} + */ + public function zscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->call('zscan', array($str_key, &$i_iterator, $str_pattern, $i_count)); + } + + /** + * {@inheritdoc} + */ + public function sscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->call('sscan', array($str_key, &$i_iterator, $str_pattern, $i_count)); + } + + /** + * {@inheritdoc} + */ + public function pfadd() + { + return $this->call('pfadd'); + } + + /** + * {@inheritdoc} + */ + public function pfcount() + { + return $this->call('pfcount'); + } + + /** + * {@inheritdoc} + */ + public function pfmerge() + { + return $this->call('pfmerge'); + } + + /** + * {@inheritdoc} + */ + public function getOption() + { + return $this->call('getOption'); + } + + /** + * {@inheritdoc} + */ + public function setOption() + { + return $this->call('setOption'); + } + + /** + * {@inheritdoc} + */ + public function config() + { + return $this->call('config'); + } + + /** + * {@inheritdoc} + */ + public function slowlog() + { + return $this->call('slowlog'); + } + + /** + * {@inheritdoc} + */ + public function rawcommand() + { + return $this->call('rawcommand'); + } + + /** + * {@inheritdoc} + */ + public function getHost() + { + return $this->call('getHost'); + } + + /** + * {@inheritdoc} + */ + public function getPort() + { + return $this->call('getPort'); + } + + /** + * {@inheritdoc} + */ + public function getDBNum() + { + return $this->call('getDBNum'); + } + + /** + * {@inheritdoc} + */ + public function getTimeout() + { + return $this->call('getTimeout'); + } + + /** + * {@inheritdoc} + */ + public function getReadTimeout() + { + return $this->call('getReadTimeout'); + } + + /** + * {@inheritdoc} + */ + public function getPersistentID() + { + return $this->call('getPersistentID'); + } + + /** + * {@inheritdoc} + */ + public function getAuth() + { + return $this->call('getAuth'); + } + + /** + * {@inheritdoc} + */ + public function isConnected() + { + return $this->call('isConnected'); + } + + /** + * {@inheritdoc} + */ + public function getMode() + { + return $this->call('getMode'); + } + + /** + * {@inheritdoc} + */ + public function wait() + { + return $this->call('wait'); + } + + /** + * {@inheritdoc} + */ + public function pubsub() + { + return $this->call('pubsub'); + } + + /** + * {@inheritdoc} + */ + public function open() + { + return $this->call('open'); + } + + /** + * {@inheritdoc} + */ + public function popen() + { + return $this->call('popen'); + } + + /** + * {@inheritdoc} + */ + public function lLen() + { + return $this->call('lLen'); + } + + /** + * {@inheritdoc} + */ + public function sGetMembers() + { + return $this->call('sGetMembers'); + } + + /** + * {@inheritdoc} + */ + public function mget() + { + return $this->call('mget'); + } + + /** + * {@inheritdoc} + */ + public function expire() + { + return $this->call('expire'); + } + + /** + * {@inheritdoc} + */ + public function zunionstore() + { + return $this->call('zunionstore'); + } + + /** + * {@inheritdoc} + */ + public function zinterstore() + { + return $this->call('zinterstore'); + } + + /** + * {@inheritdoc} + */ + public function zRemove() + { + return $this->call('zRemove'); + } + + /** + * {@inheritdoc} + */ + public function zRem() + { + return $this->call('zRem'); + } + + /** + * {@inheritdoc} + */ + public function zRemoveRangeByScore() + { + return $this->call('zRemoveRangeByScore'); + } + + /** + * {@inheritdoc} + */ + public function zRemRangeByScore() + { + return $this->call('zRemRangeByScore'); + } + + /** + * {@inheritdoc} + */ + public function zRemRangeByRank() + { + return $this->call('zRemRangeByRank'); + } + + /** + * {@inheritdoc} + */ + public function zSize() + { + return $this->call('zSize'); + } + + /** + * {@inheritdoc} + */ + public function substr() + { + return $this->call('substr'); + } + + /** + * {@inheritdoc} + */ + public function rename() + { + return $this->call('rename'); + } + + /** + * {@inheritdoc} + */ + public function del() + { + return $this->call('del'); + } + + /** + * {@inheritdoc} + */ + public function keys() + { + return $this->call('keys'); + } + + /** + * {@inheritdoc} + */ + public function lrem() + { + return $this->call('lrem'); + } + + /** + * {@inheritdoc} + */ + public function ltrim() + { + return $this->call('ltrim'); + } + + /** + * {@inheritdoc} + */ + public function lindex() + { + return $this->call('lindex'); + } + + /** + * {@inheritdoc} + */ + public function lrange() + { + return $this->call('lrange'); + } + + /** + * {@inheritdoc} + */ + public function scard() + { + return $this->call('scard'); + } + + /** + * {@inheritdoc} + */ + public function srem() + { + return $this->call('srem'); + } + + /** + * {@inheritdoc} + */ + public function sismember() + { + return $this->call('sismember'); + } + + /** + * {@inheritdoc} + */ + public function zReverseRange() + { + return $this->call('zReverseRange'); + } + + /** + * {@inheritdoc} + */ + public function sendEcho() + { + return $this->call('sendEcho'); + } + + /** + * {@inheritdoc} + */ + public function evaluate() + { + return $this->call('evaluate'); + } + + /** + * {@inheritdoc} + */ + public function evaluateSha() + { + return $this->call('evaluateSha'); + } + + /** + * Proxy function. + * + * @param string $name A command name + * @param array $arguments Lit of command arguments + * + * @throws \RuntimeException If no Redis instance is defined + * + * @return mixed + */ + private function call($name, array $arguments = array()) + { + $startTime = microtime(true); + $result = call_user_func_array("parent::$name", $arguments); + $duration = (microtime(true) - $startTime) * 1000; + if (null !== $this->logger) { + $this->logger->logCommand($this->getCommandString($name, $arguments), $duration, $this->alias, false); + } + return $result; + } + + /** + * Returns a string representation of the given command including arguments. + * + * @param string $command A command name + * @param array $arguments List of command arguments + * + * @return string + */ + private function getCommandString($command, array $arguments) + { + $list = array(); + $this->flatten($arguments, $list); + return trim(strtoupper($command).' '.implode(' ', $list)); + } + + /** + * Flatten arguments to single dimension array. + * + * @param array $arguments An array of command arguments + * @param array $list Holder of results + */ + private function flatten($arguments, array &$list) + { + foreach ($arguments as $key => $item) { + if (!is_numeric($key)) { + $list[] = $key; + } + if (is_scalar($item)) { + $list[] = strval($item); + } elseif (null === $item) { + $list[] = ''; + } else { + $this->flatten($item, $list); + } + } + } +} diff --git a/Resources/client_templates/ClientV3.php.tpl b/Resources/client_templates/ClientV3.php.tpl new file mode 100644 index 00000000..b504f6b2 --- /dev/null +++ b/Resources/client_templates/ClientV3.php.tpl @@ -0,0 +1,1809 @@ + + * (c) Yassine Khial + * (c) Pierre Boudelle + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Snc\RedisBundle\Client\Phpredis; + +use Redis; +use Snc\RedisBundle\Logger\RedisLogger; + +/** + * PHP Redis client with logger. + * + * @author Henrik Westphal + * @author Yassine Khial + * @author Pierre Boudelle + */ +class Client extends Redis +{ + const REDIS_VER = '3.1.6'; + + /** + * @var RedisLogger + */ + protected $logger; + + /** + * @var string + */ + protected $alias; + + /** + * Constructor. + * + * @param array $parameters List of parameters (only `alias` key is handled) + * @param RedisLogger $logger A RedisLogger instance + */ + public function __construct(array $parameters = array(), RedisLogger $logger = null) + { + $this->logger = $logger; + $this->alias = isset($parameters['alias']) ? $parameters['alias'] : ''; + } + + /** + * {@inheritdoc} + */ + public function __destruct() + { + return $this->call('__destruct'); + } + + /** + * {@inheritdoc} + */ + public function connect($host, $port, $timeout = null, $retry_interval = null) + { + return $this->call('connect', array($host, $port, $timeout, $retry_interval)); + } + + /** + * {@inheritdoc} + */ + public function pconnect($host, $port, $timeout = null) + { + return $this->call('pconnect', array($host, $port, $timeout)); + } + + /** + * {@inheritdoc} + */ + public function close() + { + return $this->call('close'); + } + + /** + * {@inheritdoc} + */ + public function ping() + { + return $this->call('ping'); + } + + /** + * {@inheritdoc} + */ + public function echo() + { + return $this->call('echo'); + } + + /** + * {@inheritdoc} + */ + public function get($key) + { + return $this->call('get', array($key)); + } + + /** + * {@inheritdoc} + */ + public function set($key, $value, $timeout = null) + { + return $this->call('set', array($key, $value, $timeout)); + } + + /** + * {@inheritdoc} + */ + public function setex($key, $expire, $value) + { + return $this->call('setex', array($key, $expire, $value)); + } + + /** + * {@inheritdoc} + */ + public function psetex() + { + return $this->call('psetex'); + } + + /** + * {@inheritdoc} + */ + public function setnx() + { + return $this->call('setnx'); + } + + /** + * {@inheritdoc} + */ + public function getSet() + { + return $this->call('getSet'); + } + + /** + * {@inheritdoc} + */ + public function randomKey() + { + return $this->call('randomKey'); + } + + /** + * {@inheritdoc} + */ + public function renameKey() + { + return $this->call('renameKey'); + } + + /** + * {@inheritdoc} + */ + public function renameNx() + { + return $this->call('renameNx'); + } + + /** + * {@inheritdoc} + */ + public function getMultiple(array $keys) + { + return $this->call('getMultiple', array($keys)); + } + + /** + * {@inheritdoc} + */ + public function exists() + { + return $this->call('exists'); + } + + /** + * {@inheritdoc} + */ + public function delete() + { + return $this->call('delete'); + } + + /** + * {@inheritdoc} + */ + public function incr() + { + return $this->call('incr'); + } + + /** + * {@inheritdoc} + */ + public function incrBy() + { + return $this->call('incrBy'); + } + + /** + * {@inheritdoc} + */ + public function incrByFloat() + { + return $this->call('incrByFloat'); + } + + /** + * {@inheritdoc} + */ + public function decr() + { + return $this->call('decr'); + } + + /** + * {@inheritdoc} + */ + public function decrBy() + { + return $this->call('decrBy'); + } + + /** + * {@inheritdoc} + */ + public function type() + { + return $this->call('type'); + } + + /** + * {@inheritdoc} + */ + public function append() + { + return $this->call('append'); + } + + /** + * {@inheritdoc} + */ + public function getRange() + { + return $this->call('getRange'); + } + + /** + * {@inheritdoc} + */ + public function setRange() + { + return $this->call('setRange'); + } + + /** + * {@inheritdoc} + */ + public function getBit() + { + return $this->call('getBit'); + } + + /** + * {@inheritdoc} + */ + public function setBit() + { + return $this->call('setBit'); + } + + /** + * {@inheritdoc} + */ + public function strlen() + { + return $this->call('strlen'); + } + + /** + * {@inheritdoc} + */ + public function getKeys() + { + return $this->call('getKeys'); + } + + /** + * {@inheritdoc} + */ + public function sort() + { + return $this->call('sort'); + } + + /** + * {@inheritdoc} + */ + public function sortAsc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) + { + return $this->call('sortAsc', array($key, $pattern, $get, $start, $end, $getList)); + } + + /** + * {@inheritdoc} + */ + public function sortAscAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) + { + return $this->call('sortAscAlpha', array($key, $pattern, $get, $start, $end, $getList)); + } + + /** + * {@inheritdoc} + */ + public function sortDesc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) + { + return $this->call('sortDesc', array($key, $pattern, $get, $start, $end, $getList)); + } + + /** + * {@inheritdoc} + */ + public function sortDescAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) + { + return $this->call('sortDescAlpha', array($key, $pattern, $get, $start, $end, $getList)); + } + + /** + * {@inheritdoc} + */ + public function lPush() + { + return $this->call('lPush'); + } + + /** + * {@inheritdoc} + */ + public function rPush() + { + return $this->call('rPush'); + } + + /** + * {@inheritdoc} + */ + public function lPushx() + { + return $this->call('lPushx'); + } + + /** + * {@inheritdoc} + */ + public function rPushx() + { + return $this->call('rPushx'); + } + + /** + * {@inheritdoc} + */ + public function lPop() + { + return $this->call('lPop'); + } + + /** + * {@inheritdoc} + */ + public function rPop() + { + return $this->call('rPop'); + } + + /** + * {@inheritdoc} + */ + public function blPop() + { + return $this->call('blPop'); + } + + /** + * {@inheritdoc} + */ + public function brPop() + { + return $this->call('brPop'); + } + + /** + * {@inheritdoc} + */ + public function lSize() + { + return $this->call('lSize'); + } + + /** + * {@inheritdoc} + */ + public function lRemove() + { + return $this->call('lRemove'); + } + + /** + * {@inheritdoc} + */ + public function listTrim() + { + return $this->call('listTrim'); + } + + /** + * {@inheritdoc} + */ + public function lGet() + { + return $this->call('lGet'); + } + + /** + * {@inheritdoc} + */ + public function lGetRange() + { + return $this->call('lGetRange'); + } + + /** + * {@inheritdoc} + */ + public function lSet() + { + return $this->call('lSet'); + } + + /** + * {@inheritdoc} + */ + public function lInsert() + { + return $this->call('lInsert'); + } + + /** + * {@inheritdoc} + */ + public function sAdd() + { + return $this->call('sAdd'); + } + + /** + * {@inheritdoc} + */ + public function sAddArray() + { + return $this->call('sAddArray'); + } + + /** + * {@inheritdoc} + */ + public function sSize() + { + return $this->call('sSize'); + } + + /** + * {@inheritdoc} + */ + public function sRemove() + { + return $this->call('sRemove'); + } + + /** + * {@inheritdoc} + */ + public function sMove() + { + return $this->call('sMove'); + } + + /** + * {@inheritdoc} + */ + public function sPop($key) + { + return $this->call('sPop', array($key)); + } + + /** + * {@inheritdoc} + */ + public function sRandMember() + { + return $this->call('sRandMember'); + } + + /** + * {@inheritdoc} + */ + public function sContains() + { + return $this->call('sContains'); + } + + /** + * {@inheritdoc} + */ + public function sMembers() + { + return $this->call('sMembers'); + } + + /** + * {@inheritdoc} + */ + public function sInter() + { + return $this->call('sInter'); + } + + /** + * {@inheritdoc} + */ + public function sInterStore() + { + return $this->call('sInterStore'); + } + + /** + * {@inheritdoc} + */ + public function sUnion() + { + return $this->call('sUnion'); + } + + /** + * {@inheritdoc} + */ + public function sUnionStore() + { + return $this->call('sUnionStore'); + } + + /** + * {@inheritdoc} + */ + public function sDiff() + { + return $this->call('sDiff'); + } + + /** + * {@inheritdoc} + */ + public function sDiffStore() + { + return $this->call('sDiffStore'); + } + + /** + * {@inheritdoc} + */ + public function setTimeout() + { + return $this->call('setTimeout'); + } + + /** + * {@inheritdoc} + */ + public function save() + { + return $this->call('save'); + } + + /** + * {@inheritdoc} + */ + public function bgSave() + { + return $this->call('bgSave'); + } + + /** + * {@inheritdoc} + */ + public function lastSave() + { + return $this->call('lastSave'); + } + + /** + * {@inheritdoc} + */ + public function flushDB() + { + return $this->call('flushDB'); + } + + /** + * {@inheritdoc} + */ + public function flushAll() + { + return $this->call('flushAll'); + } + + /** + * {@inheritdoc} + */ + public function dbSize() + { + return $this->call('dbSize'); + } + + /** + * {@inheritdoc} + */ + public function auth($password) + { + return $this->call('auth', array($password)); + } + + /** + * {@inheritdoc} + */ + public function ttl() + { + return $this->call('ttl'); + } + + /** + * {@inheritdoc} + */ + public function pttl() + { + return $this->call('pttl'); + } + + /** + * {@inheritdoc} + */ + public function persist() + { + return $this->call('persist'); + } + + /** + * {@inheritdoc} + */ + public function info() + { + return $this->call('info'); + } + + /** + * {@inheritdoc} + */ + public function select($dbindex) + { + return $this->call('select', array($dbindex)); + } + + /** + * {@inheritdoc} + */ + public function move($key, $dbindex) + { + return $this->call('move', array($key, $dbindex)); + } + + /** + * {@inheritdoc} + */ + public function bgrewriteaof() + { + return $this->call('bgrewriteaof'); + } + + /** + * {@inheritdoc} + */ + public function slaveof($host = null, $port = null) + { + return $this->call('slaveof', array($host, $port)); + } + + /** + * {@inheritdoc} + */ + public function object() + { + return $this->call('object'); + } + + /** + * {@inheritdoc} + */ + public function bitop() + { + return $this->call('bitop'); + } + + /** + * {@inheritdoc} + */ + public function bitcount() + { + return $this->call('bitcount'); + } + + /** + * {@inheritdoc} + */ + public function bitpos() + { + return $this->call('bitpos'); + } + + /** + * {@inheritdoc} + */ + public function mset(array $pairs) + { + return $this->call('mset', array($pairs)); + } + + /** + * {@inheritdoc} + */ + public function msetnx(array $pairs) + { + return $this->call('msetnx', array($pairs)); + } + + /** + * {@inheritdoc} + */ + public function rpoplpush() + { + return $this->call('rpoplpush'); + } + + /** + * {@inheritdoc} + */ + public function brpoplpush() + { + return $this->call('brpoplpush'); + } + + /** + * {@inheritdoc} + */ + public function zAdd() + { + return $this->call('zAdd'); + } + + /** + * {@inheritdoc} + */ + public function zDelete() + { + return $this->call('zDelete'); + } + + /** + * {@inheritdoc} + */ + public function zRange() + { + return $this->call('zRange'); + } + + /** + * {@inheritdoc} + */ + public function zRevRange() + { + return $this->call('zRevRange'); + } + + /** + * {@inheritdoc} + */ + public function zRangeByScore() + { + return $this->call('zRangeByScore'); + } + + /** + * {@inheritdoc} + */ + public function zRevRangeByScore() + { + return $this->call('zRevRangeByScore'); + } + + /** + * {@inheritdoc} + */ + public function zRangeByLex() + { + return $this->call('zRangeByLex'); + } + + /** + * {@inheritdoc} + */ + public function zRevRangeByLex() + { + return $this->call('zRevRangeByLex'); + } + + /** + * {@inheritdoc} + */ + public function zLexCount() + { + return $this->call('zLexCount'); + } + + /** + * {@inheritdoc} + */ + public function zRemRangeByLex() + { + return $this->call('zRemRangeByLex'); + } + + /** + * {@inheritdoc} + */ + public function zCount() + { + return $this->call('zCount'); + } + + /** + * {@inheritdoc} + */ + public function zDeleteRangeByScore() + { + return $this->call('zDeleteRangeByScore'); + } + + /** + * {@inheritdoc} + */ + public function zDeleteRangeByRank() + { + return $this->call('zDeleteRangeByRank'); + } + + /** + * {@inheritdoc} + */ + public function zCard() + { + return $this->call('zCard'); + } + + /** + * {@inheritdoc} + */ + public function zScore() + { + return $this->call('zScore'); + } + + /** + * {@inheritdoc} + */ + public function zRank() + { + return $this->call('zRank'); + } + + /** + * {@inheritdoc} + */ + public function zRevRank() + { + return $this->call('zRevRank'); + } + + /** + * {@inheritdoc} + */ + public function zInter() + { + return $this->call('zInter'); + } + + /** + * {@inheritdoc} + */ + public function zUnion() + { + return $this->call('zUnion'); + } + + /** + * {@inheritdoc} + */ + public function zIncrBy() + { + return $this->call('zIncrBy'); + } + + /** + * {@inheritdoc} + */ + public function expireAt() + { + return $this->call('expireAt'); + } + + /** + * {@inheritdoc} + */ + public function pexpire() + { + return $this->call('pexpire'); + } + + /** + * {@inheritdoc} + */ + public function pexpireAt() + { + return $this->call('pexpireAt'); + } + + /** + * {@inheritdoc} + */ + public function hGet() + { + return $this->call('hGet'); + } + + /** + * {@inheritdoc} + */ + public function hSet() + { + return $this->call('hSet'); + } + + /** + * {@inheritdoc} + */ + public function hSetNx() + { + return $this->call('hSetNx'); + } + + /** + * {@inheritdoc} + */ + public function hDel() + { + return $this->call('hDel'); + } + + /** + * {@inheritdoc} + */ + public function hLen() + { + return $this->call('hLen'); + } + + /** + * {@inheritdoc} + */ + public function hKeys() + { + return $this->call('hKeys'); + } + + /** + * {@inheritdoc} + */ + public function hVals() + { + return $this->call('hVals'); + } + + /** + * {@inheritdoc} + */ + public function hGetAll() + { + return $this->call('hGetAll'); + } + + /** + * {@inheritdoc} + */ + public function hExists() + { + return $this->call('hExists'); + } + + /** + * {@inheritdoc} + */ + public function hIncrBy() + { + return $this->call('hIncrBy'); + } + + /** + * {@inheritdoc} + */ + public function hIncrByFloat() + { + return $this->call('hIncrByFloat'); + } + + /** + * {@inheritdoc} + */ + public function hMset() + { + return $this->call('hMset'); + } + + /** + * {@inheritdoc} + */ + public function hMget() + { + return $this->call('hMget'); + } + + /** + * {@inheritdoc} + */ + public function hStrLen() + { + return $this->call('hStrLen'); + } + + /** + * {@inheritdoc} + */ + public function multi() + { + return $this->call('multi'); + } + + /** + * {@inheritdoc} + */ + public function discard() + { + return $this->call('discard'); + } + + /** + * {@inheritdoc} + */ + public function exec() + { + return $this->call('exec'); + } + + /** + * {@inheritdoc} + */ + public function pipeline() + { + return $this->call('pipeline'); + } + + /** + * {@inheritdoc} + */ + public function watch() + { + return $this->call('watch'); + } + + /** + * {@inheritdoc} + */ + public function unwatch() + { + return $this->call('unwatch'); + } + + /** + * {@inheritdoc} + */ + public function publish() + { + return $this->call('publish'); + } + + /** + * {@inheritdoc} + */ + public function subscribe() + { + return $this->call('subscribe'); + } + + /** + * {@inheritdoc} + */ + public function psubscribe() + { + return $this->call('psubscribe'); + } + + /** + * {@inheritdoc} + */ + public function unsubscribe() + { + return $this->call('unsubscribe'); + } + + /** + * {@inheritdoc} + */ + public function punsubscribe() + { + return $this->call('punsubscribe'); + } + + /** + * {@inheritdoc} + */ + public function time() + { + return $this->call('time'); + } + + /** + * {@inheritdoc} + */ + public function role() + { + return $this->call('role'); + } + + /** + * {@inheritdoc} + */ + public function eval() + { + return $this->call('eval'); + } + + /** + * {@inheritdoc} + */ + public function evalsha() + { + return $this->call('evalsha'); + } + + /** + * {@inheritdoc} + */ + public function script() + { + return $this->call('script'); + } + + /** + * {@inheritdoc} + */ + public function debug() + { + return $this->call('debug'); + } + + /** + * {@inheritdoc} + */ + public function dump() + { + return $this->call('dump'); + } + + /** + * {@inheritdoc} + */ + public function restore() + { + return $this->call('restore'); + } + + /** + * {@inheritdoc} + */ + public function migrate($host, $port, $key, $db, $timeout, $copy = null, $replace = null) + { + return $this->call('migrate', array($host, $port, $key, $db, $timeout, $copy, $replace)); + } + + /** + * {@inheritdoc} + */ + public function getLastError() + { + return $this->call('getLastError'); + } + + /** + * {@inheritdoc} + */ + public function clearLastError() + { + return $this->call('clearLastError'); + } + + /** + * {@inheritdoc} + */ + public function _prefix() + { + return $this->call('_prefix'); + } + + /** + * {@inheritdoc} + */ + public function _serialize() + { + return $this->call('_serialize'); + } + + /** + * {@inheritdoc} + */ + public function _unserialize() + { + return $this->call('_unserialize'); + } + + /** + * {@inheritdoc} + */ + public function client($cmd, ...$args) + { + return $this->call('client', array($cmd, $args)); + } + + /** + * {@inheritdoc} + */ + public function command() + { + return $this->call('command'); + } + + /** + * {@inheritdoc} + */ + public function scan(&$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->call('scan', array(&$i_iterator, $str_pattern, $i_count)); + } + + /** + * {@inheritdoc} + */ + public function hscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->call('hscan', array($str_key, &$i_iterator, $str_pattern, $i_count)); + } + + /** + * {@inheritdoc} + */ + public function zscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->call('zscan', array($str_key, &$i_iterator, $str_pattern, $i_count)); + } + + /** + * {@inheritdoc} + */ + public function sscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) + { + return $this->call('sscan', array($str_key, &$i_iterator, $str_pattern, $i_count)); + } + + /** + * {@inheritdoc} + */ + public function pfadd() + { + return $this->call('pfadd'); + } + + /** + * {@inheritdoc} + */ + public function pfcount() + { + return $this->call('pfcount'); + } + + /** + * {@inheritdoc} + */ + public function pfmerge() + { + return $this->call('pfmerge'); + } + + /** + * {@inheritdoc} + */ + public function getOption($option) + { + return $this->call('getOption', array($option)); + } + + /** + * {@inheritdoc} + */ + public function setOption($option, $value) + { + return $this->call('setOption', array($option, $value)); + } + + /** + * {@inheritdoc} + */ + public function config($cmd, $key, $value = null) + { + return $this->call('config', array($cmd, $key, $value)); + } + + /** + * {@inheritdoc} + */ + public function slowlog($arg, $option = null) + { + return $this->call('slowlog', array($arg, $option)); + } + + /** + * {@inheritdoc} + */ + public function rawcommand($cmd, ...$args) + { + return $this->call('rawcommand', array($cmd, $args)); + } + + /** + * {@inheritdoc} + */ + public function geoadd() + { + return $this->call('geoadd'); + } + + /** + * {@inheritdoc} + */ + public function geohash() + { + return $this->call('geohash'); + } + + /** + * {@inheritdoc} + */ + public function geopos() + { + return $this->call('geopos'); + } + + /** + * {@inheritdoc} + */ + public function geodist() + { + return $this->call('geodist'); + } + + /** + * {@inheritdoc} + */ + public function georadius() + { + return $this->call('georadius'); + } + + /** + * {@inheritdoc} + */ + public function georadiusbymember() + { + return $this->call('georadiusbymember'); + } + + /** + * {@inheritdoc} + */ + public function getHost() + { + return $this->call('getHost'); + } + + /** + * {@inheritdoc} + */ + public function getPort() + { + return $this->call('getPort'); + } + + /** + * {@inheritdoc} + */ + public function getDBNum() + { + return $this->call('getDBNum'); + } + + /** + * {@inheritdoc} + */ + public function getTimeout() + { + return $this->call('getTimeout'); + } + + /** + * {@inheritdoc} + */ + public function getReadTimeout() + { + return $this->call('getReadTimeout'); + } + + /** + * {@inheritdoc} + */ + public function getPersistentID() + { + return $this->call('getPersistentID'); + } + + /** + * {@inheritdoc} + */ + public function getAuth() + { + return $this->call('getAuth'); + } + + /** + * {@inheritdoc} + */ + public function isConnected() + { + return $this->call('isConnected'); + } + + /** + * {@inheritdoc} + */ + public function getMode() + { + return $this->call('getMode'); + } + + /** + * {@inheritdoc} + */ + public function wait($numslaves, $timeout) + { + return $this->call('wait', array($numslaves, $timeout)); + } + + /** + * {@inheritdoc} + */ + public function pubsub($cmd, ...$args) + { + return $this->call('pubsub', array($cmd, $args)); + } + + /** + * {@inheritdoc} + */ + public function open($host, $port, $timeout = null, $retry_interval = null) + { + return $this->call('open', array($host, $port, $timeout, $retry_interval)); + } + + /** + * {@inheritdoc} + */ + public function popen($host, $port, $timeout = null) + { + return $this->call('popen', array($host, $port, $timeout)); + } + + /** + * {@inheritdoc} + */ + public function lLen() + { + return $this->call('lLen'); + } + + /** + * {@inheritdoc} + */ + public function sGetMembers() + { + return $this->call('sGetMembers'); + } + + /** + * {@inheritdoc} + */ + public function mget(array $keys) + { + return $this->call('mget', array($keys)); + } + + /** + * {@inheritdoc} + */ + public function expire() + { + return $this->call('expire'); + } + + /** + * {@inheritdoc} + */ + public function zunionstore() + { + return $this->call('zunionstore'); + } + + /** + * {@inheritdoc} + */ + public function zinterstore() + { + return $this->call('zinterstore'); + } + + /** + * {@inheritdoc} + */ + public function zRemove() + { + return $this->call('zRemove'); + } + + /** + * {@inheritdoc} + */ + public function zRem() + { + return $this->call('zRem'); + } + + /** + * {@inheritdoc} + */ + public function zRemoveRangeByScore() + { + return $this->call('zRemoveRangeByScore'); + } + + /** + * {@inheritdoc} + */ + public function zRemRangeByScore() + { + return $this->call('zRemRangeByScore'); + } + + /** + * {@inheritdoc} + */ + public function zRemRangeByRank() + { + return $this->call('zRemRangeByRank'); + } + + /** + * {@inheritdoc} + */ + public function zSize() + { + return $this->call('zSize'); + } + + /** + * {@inheritdoc} + */ + public function substr() + { + return $this->call('substr'); + } + + /** + * {@inheritdoc} + */ + public function rename() + { + return $this->call('rename'); + } + + /** + * {@inheritdoc} + */ + public function del() + { + return $this->call('del'); + } + + /** + * {@inheritdoc} + */ + public function keys() + { + return $this->call('keys'); + } + + /** + * {@inheritdoc} + */ + public function lrem() + { + return $this->call('lrem'); + } + + /** + * {@inheritdoc} + */ + public function ltrim() + { + return $this->call('ltrim'); + } + + /** + * {@inheritdoc} + */ + public function lindex() + { + return $this->call('lindex'); + } + + /** + * {@inheritdoc} + */ + public function lrange() + { + return $this->call('lrange'); + } + + /** + * {@inheritdoc} + */ + public function scard() + { + return $this->call('scard'); + } + + /** + * {@inheritdoc} + */ + public function srem() + { + return $this->call('srem'); + } + + /** + * {@inheritdoc} + */ + public function sismember() + { + return $this->call('sismember'); + } + + /** + * {@inheritdoc} + */ + public function zReverseRange() + { + return $this->call('zReverseRange'); + } + + /** + * {@inheritdoc} + */ + public function sendEcho() + { + return $this->call('sendEcho'); + } + + /** + * {@inheritdoc} + */ + public function evaluate() + { + return $this->call('evaluate'); + } + + /** + * {@inheritdoc} + */ + public function evaluateSha() + { + return $this->call('evaluateSha'); + } + + /** + * Proxy function. + * + * @param string $name A command name + * @param array $arguments Lit of command arguments + * + * @throws \RuntimeException If no Redis instance is defined + * + * @return mixed + */ + private function call($name, array $arguments = array()) + { + $startTime = microtime(true); + $result = call_user_func_array("parent::$name", $arguments); + $duration = (microtime(true) - $startTime) * 1000; + + if (null !== $this->logger) { + $this->logger->logCommand($this->getCommandString($name, $arguments), $duration, $this->alias, false); + } + + return $result; + } + + /** + * Returns a string representation of the given command including arguments. + * + * @param string $command A command name + * @param array $arguments List of command arguments + * + * @return string + */ + private function getCommandString($command, array $arguments) + { + $list = array(); + $this->flatten($arguments, $list); + + return trim(strtoupper($command).' '.implode(' ', $list)); + } + + /** + * Flatten arguments to single dimension array. + * + * @param array $arguments An array of command arguments + * @param array $list Holder of results + */ + private function flatten($arguments, array &$list) + { + foreach ($arguments as $key => $item) { + if (!is_numeric($key)) { + $list[] = $key; + } + + if (is_scalar($item)) { + $list[] = strval($item); + } elseif (null === $item) { + $list[] = ''; + } else { + $this->flatten($item, $list); + } + } + } +} diff --git a/Resources/client_templates/ClientV4.php.tpl b/Resources/client_templates/ClientV4.php.tpl new file mode 100644 index 00000000..2725403e --- /dev/null +++ b/Resources/client_templates/ClientV4.php.tpl @@ -0,0 +1,114 @@ + + * (c) Yassine Khial + * (c) Pierre Boudelle + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Snc\RedisBundle\Client\Phpredis; + +use Snc\RedisBundle\Logger\RedisLogger; + +/** + * PHP Redis client with logger. + * + * @author Henrik Westphal + * @author Yassine Khial + * @author Pierre Boudelle + */ +class Client extends {{extended_classname}} +{ + const REDIS_VER = '{{version}}'; + + /** + * @var RedisLogger + */ + protected $logger; + + /** + * @var string + */ + protected $alias; + + /** + * Constructor. + * + * @param array $parameters List of parameters (only `alias` key is handled) + * @param RedisLogger $logger A RedisLogger instance + */ + public function __construct(array $parameters = array(), RedisLogger $logger = null) + { + $this->logger = $logger; + $this->alias = isset($parameters['alias']) ? $parameters['alias'] : ''; + } + + {{public_methods}} + + /** + * Proxy function. + * + * @param string $name A command name + * @param array $arguments Lit of command arguments + * + * @throws \RuntimeException If no Redis instance is defined + * + * @return mixed + */ + private function call($name, array $arguments = array()) + { + $startTime = microtime(true); + $result = call_user_func_array("parent::$name", $arguments); + $duration = (microtime(true) - $startTime) * 1000; + + if (null !== $this->logger) { + $this->logger->logCommand($this->getCommandString($name, $arguments), $duration, $this->alias, false); + } + + return $result; + } + + /** + * Returns a string representation of the given command including arguments. + * + * @param string $command A command name + * @param array $arguments List of command arguments + * + * @return string + */ + private function getCommandString($command, array $arguments) + { + $list = array(); + $this->flatten($arguments, $list); + + return trim(strtoupper($command).' '.implode(' ', $list)); + } + + /** + * Flatten arguments to single dimension array. + * + * @param array $arguments An array of command arguments + * @param array $list Holder of results + */ + private function flatten($arguments, array &$list) + { + foreach ($arguments as $key => $item) { + if (!is_numeric($key)) { + $list[] = $key; + } + + if (is_scalar($item)) { + $list[] = strval($item); + } elseif (null === $item) { + $list[] = ''; + } else { + $this->flatten($item, $list); + } + } + } +} diff --git a/Resources/config/redis.xml b/Resources/config/redis.xml index e962031b..08925d52 100644 --- a/Resources/config/redis.xml +++ b/Resources/config/redis.xml @@ -24,6 +24,12 @@ + + + + + + diff --git a/SncRedisBundle.php b/SncRedisBundle.php index 5f3df697..559c562c 100644 --- a/SncRedisBundle.php +++ b/SncRedisBundle.php @@ -11,6 +11,7 @@ namespace Snc\RedisBundle; +use Snc\RedisBundle\Client\Phpredis\Client; use Snc\RedisBundle\DependencyInjection\Compiler\ClientLocatorPass; use Snc\RedisBundle\DependencyInjection\Compiler\LoggingPass; use Snc\RedisBundle\DependencyInjection\Compiler\MonologPass; @@ -23,6 +24,24 @@ */ class SncRedisBundle extends Bundle { + /** + * {@inheritdoc} + */ + public function boot() + { + parent::boot(); + + if ($this->container->getParameter('snc_redis.phpredis_client.class') === Client::class) { + if (!class_exists(Client::class)) { + if (!file_exists($file = $this->container->getParameter('kernel.cache_dir').'/snc_phpredis_client.php')) { + throw new \LogicException(sprintf('You must warmup the cache before using the %s class', Client::class)); + } + + require $file; + } + } + } + /** * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container */ diff --git a/Tests/Client/Phpredis/ClientTest.php b/Tests/Client/Phpredis/ClientTest.php index e74a02cf..a24910c4 100644 --- a/Tests/Client/Phpredis/ClientTest.php +++ b/Tests/Client/Phpredis/ClientTest.php @@ -11,19 +11,17 @@ class ClientTest extends TestCase { /** + * @depends \Snc\RedisBundle\Tests\Functional\CustomPhpredisClientTest::testCreateFullConfig + * * @covers \Snc\RedisBundle\Client\Phpredis\Client::getCommandString */ public function testGetCommandString() { if (!extension_loaded('redis')) { $this->markTestSkipped('This test needs the PHP Redis extension to work'); - } elseif (version_compare(phpversion('redis'), '4.0.0') >= 0) { - $this->markTestSkipped('This test cannot be executed on Redis extension version ' . phpversion('redis')); } - $method = new \ReflectionMethod( - '\Snc\RedisBundle\Client\Phpredis\Client', 'getCommandString' - ); + $method = new \ReflectionMethod(Client::class, 'getCommandString'); $method->setAccessible(true); diff --git a/Tests/DependencyInjection/SncRedisExtensionEnvTest.php b/Tests/DependencyInjection/SncRedisExtensionEnvTest.php index 56ff72cc..8e4bc5cd 100644 --- a/Tests/DependencyInjection/SncRedisExtensionEnvTest.php +++ b/Tests/DependencyInjection/SncRedisExtensionEnvTest.php @@ -4,6 +4,7 @@ use PHPUnit\Framework\TestCase; use Snc\RedisBundle\DependencyInjection\SncRedisExtension; +use Snc\RedisBundle\Client\Phpredis\Client; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; @@ -67,14 +68,8 @@ public function testPhpredisFullConfig() $clientDefinition = $container->findDefinition('snc_redis.alias_test'); - $clientClass = 'Snc\RedisBundle\Client\Phpredis\Client'; - if (version_compare(phpversion('redis'), '4.0.0') >= 0) { - // Logging is not supported for this version >=4.0.0 of phpredis - $clientClass = 'Redis'; - } - - $this->assertSame($clientClass, $clientDefinition->getClass()); - $this->assertSame($clientClass, $clientDefinition->getArgument(0)); + $this->assertSame(Client::class, $clientDefinition->getClass()); + $this->assertSame(Client::class, $clientDefinition->getArgument(0)); $this->assertContains('TEST_URL_2', $clientDefinition->getArgument(1)); $this->assertSame('alias_test', $clientDefinition->getArgument(3)); $this->assertSame(array( diff --git a/Tests/Factory/PhpredisClientFactoryTest.php b/Tests/Factory/PhpredisClientFactoryTest.php index 28b34a69..4592cfc8 100644 --- a/Tests/Factory/PhpredisClientFactoryTest.php +++ b/Tests/Factory/PhpredisClientFactoryTest.php @@ -9,9 +9,19 @@ class PhpredisClientFactoryTest extends TestCase { + /** + * @var LoggerInterface + */ + private $logger; + + /** + * @var RedisLogger + */ + private $redisLogger; + protected function setUp() { - if (!class_exists('\Redis')) { + if (!class_exists(\Redis::class)) { $this->markTestSkipped(sprintf('The %s requires phpredis extension.', __CLASS__)); } @@ -21,58 +31,23 @@ protected function setUp() $this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); $this->redisLogger = new RedisLogger($this->logger); + + parent::setUp(); } public function testCreateMinimalConfig() { $factory = new PhpredisClientFactory(); - $client = $factory->create('\Redis', 'redis://localhost:6379', array(), 'default'); + $client = $factory->create(\Redis::class, 'redis://localhost:6379', array(), 'default'); - $this->assertInstanceOf('\Redis', $client); + $this->assertInstanceOf(\Redis::class, $client); $this->assertNull($client->getOption(\Redis::OPT_PREFIX)); $this->assertSame(0, $client->getOption(\Redis::OPT_SERIALIZER)); $this->assertSame(0, $client->getDBNum()); $this->assertNull($client->getAuth()); } - public function testCreateFullConfig() - { - // @todo: Remove this condition when the inheritance from `\Redis` is fixed - // see https://github.com/snc/SncRedisBundle/issues/399 - if (version_compare(phpversion('redis'), '4.0.0') >= 0) { - $this->markTestSkipped('This test cannot be executed on Redis extension version ' . phpversion('redis')); - } - - $logger = $this->getMockBuilder('Snc\RedisBundle\Logger\RedisLogger')->getMock(); - $factory = new PhpredisClientFactory($logger); - - $client = $factory->create( - '\Snc\RedisBundle\Client\Phpredis\Client', - 'redis://localhost:6379', - array( - 'connection_timeout' => 10, - 'connection_persistent' => true, - 'prefix' => 'toto', - 'serialization' => 'php', - 'read_write_timeout' => 4, - 'parameters' => [ - 'database' => 3, - 'password' => 'secret', - ], - ), - 'alias_test' - ); - - $this->assertInstanceOf('\Snc\RedisBundle\Client\Phpredis\Client', $client); - $this->assertSame('toto', $client->getOption(\Redis::OPT_PREFIX)); - $this->assertSame(1, $client->getOption(\Redis::OPT_SERIALIZER)); - $this->assertSame(4., $client->getOption(\Redis::OPT_READ_TIMEOUT)); - $this->assertSame(3, $client->getDBNum()); - $this->assertSame('secret', $client->getAuth()); - $this->assertAttributeSame($logger, 'logger', $client); - } - public function testDsnConfig() { $factory = new PhpredisClientFactory(); diff --git a/Tests/Functional/App/KernelWithCustomRedisClient.php b/Tests/Functional/App/KernelWithCustomRedisClient.php new file mode 100644 index 00000000..16f68037 --- /dev/null +++ b/Tests/Functional/App/KernelWithCustomRedisClient.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Snc\RedisBundle\Tests\Functional\App; + +use Snc\RedisBundle\Client\Phpredis\Client; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Javier Spagnoletti + */ +class KernelWithCustomRedisClient extends Kernel +{ + /** + * {@inheritdoc} + */ + protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader) + { + parent::configureContainer($container, $loader); + + $container->loadFromExtension('snc_redis', [ + 'class' => [ + 'phpredis_client' => Client::class, + ], + ]); + } +} diff --git a/Tests/Functional/App/config.yaml b/Tests/Functional/App/config.yaml index 6dd9c1e4..5c5fac53 100644 --- a/Tests/Functional/App/config.yaml +++ b/Tests/Functional/App/config.yaml @@ -25,6 +25,9 @@ doctrine: dir: '%kernel.project_dir%/Entity' prefix: 'Snc\RedisBundle\Tests\Functional\App\Entity' +twig: + strict_variables: '%kernel.debug%' + snc_redis: clients: default: diff --git a/Tests/Functional/CustomPhpredisClientTest.php b/Tests/Functional/CustomPhpredisClientTest.php new file mode 100644 index 00000000..574f5eaf --- /dev/null +++ b/Tests/Functional/CustomPhpredisClientTest.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Snc\RedisBundle\Tests\Functional; + +use Snc\RedisBundle\Client\Phpredis\Client; +use Snc\RedisBundle\Factory\PhpredisClientFactory; +use Snc\RedisBundle\Logger\RedisLogger; +use Snc\RedisBundle\Tests\Functional\App\KernelWithCustomRedisClient; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; +use Symfony\Component\Filesystem\Filesystem; + +/** + * @author Javier Spagnoletti + */ +class CustomPhpredisClientTest extends WebTestCase +{ + public function testCreateFullConfig() + { + $logger = $this->getMockBuilder(RedisLogger::class)->getMock(); + $factory = new PhpredisClientFactory($logger); + + $this->assertTrue(class_exists(Client::class)); + + $client = $factory->create( + Client::class, + 'redis://localhost:6379', + array( + 'connection_timeout' => 10, + 'connection_persistent' => true, + 'prefix' => 'toto', + 'serialization' => 'php', + 'read_write_timeout' => 4, + 'parameters' => [ + 'database' => 3, + 'password' => 'secret', + ], + ), + 'alias_test' + ); + + $this->assertInstanceOf(Client::class, $client); + $this->assertSame('toto', $client->getOption(\Redis::OPT_PREFIX)); + $this->assertSame(1, $client->getOption(\Redis::OPT_SERIALIZER)); + $this->assertSame(4., $client->getOption(\Redis::OPT_READ_TIMEOUT)); + $this->assertSame(3, $client->getDBNum()); + $this->assertSame('secret', $client->getAuth()); + $this->assertAttributeSame($logger, 'logger', $client); + } + + /** + * Manage schema and cleanup chores + */ + public static function setUpBeforeClass() + { + parent::setUpBeforeClass(); + + static::deleteTmpDir(); + + static::createClient()->getKernel(); + } + + public static function tearDownAfterClass() + { + static::deleteTmpDir(); + + parent::tearDownAfterClass(); + } + + protected static function deleteTmpDir() + { + $dir = __DIR__ .'/App/var'; + if (!file_exists($dir)) { + return; + } + + $fs = new Filesystem(); + $fs->remove($dir); + } + + protected static function getKernelClass() + { + return KernelWithCustomRedisClient::class; + } +} diff --git a/Tests/Functional/IntegrationTest.php b/Tests/Functional/IntegrationTest.php index 0d31f60e..484f654f 100644 --- a/Tests/Functional/IntegrationTest.php +++ b/Tests/Functional/IntegrationTest.php @@ -15,7 +15,6 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Tools\SchemaTool; -use Snc\RedisBundle\Command\RedisFlushallCommand; use Snc\RedisBundle\DataCollector\RedisDataCollector; use Snc\RedisBundle\Tests\Functional\App\Kernel; use Symfony\Bundle\FrameworkBundle\Client; @@ -24,7 +23,6 @@ use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Profiler\Profile; /** * IntegrationTest @@ -51,10 +49,7 @@ public function testIntegration() $collector = $this->client->getProfile()->getCollector('redis'); $this->assertInstanceOf(RedisDataCollector::class, $collector); - if (version_compare(phpversion('redis'), '4.0.0') < 0) { - // Logging is currently disabled on PHPRedis 4+ - $this->assertCount(4, $collector->getCommands()); - } + $this->assertCount(4, $collector->getCommands()); } public function testCreateUser()