Predis to v2.2.2

This commit is contained in:
the-djmaze 2024-04-02 20:15:23 +02:00
parent f6b440adef
commit 84ffe1e552
259 changed files with 2407 additions and 9937 deletions

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -11,21 +12,35 @@
namespace Predis;
use ArrayIterator;
use InvalidArgumentException;
use IteratorAggregate;
use Predis\Command\CommandInterface;
use Predis\Command\RawCommand;
use Predis\Command\Redis\Container\ContainerFactory;
use Predis\Command\Redis\Container\ContainerInterface;
use Predis\Command\ScriptCommand;
use Predis\Configuration\Options;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\AggregateConnectionInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Connection\Parameters;
use Predis\Connection\ParametersInterface;
use Predis\Connection\RelayConnection;
use Predis\Monitor\Consumer as MonitorConsumer;
use Predis\Pipeline\Atomic;
use Predis\Pipeline\FireAndForget;
use Predis\Pipeline\Pipeline;
use Predis\Pipeline\RelayAtomic;
use Predis\Pipeline\RelayPipeline;
use Predis\PubSub\Consumer as PubSubConsumer;
use Predis\PubSub\RelayConsumer as RelayPubSubConsumer;
use Predis\Response\ErrorInterface as ErrorResponseInterface;
use Predis\Response\ResponseInterface;
use Predis\Response\ServerException;
use Predis\Transaction\MultiExec as MultiExecTransaction;
use ReturnTypeWillChange;
use RuntimeException;
use Traversable;
/**
* Client class used for connecting and executing commands on Redis.
@ -34,17 +49,20 @@ use Predis\Transaction\MultiExec as MultiExecTransaction;
* abstractions are built. Internally it aggregates various other classes each
* one with its own responsibility and scope.
*
* {@inheritdoc}
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @template-implements \IteratorAggregate<string, static>
*/
class Client implements ClientInterface
class Client implements ClientInterface, IteratorAggregate
{
const VERSION = '1.0.3';
public const VERSION = '2.2.2';
protected $connection;
protected $options;
private $profile;
/** @var OptionsInterface */
private $options;
/** @var ConnectionInterface */
private $connection;
/** @var Command\FactoryInterface */
private $commands;
/**
* @param mixed $parameters Connection parameters for one or more servers.
@ -52,126 +70,99 @@ class Client implements ClientInterface
*/
public function __construct($parameters = null, $options = null)
{
$this->options = $this->createOptions($options ?: array());
$this->connection = $this->createConnection($parameters ?: array());
$this->profile = $this->options->profile;
$this->options = static::createOptions($options ?? new Options());
$this->connection = static::createConnection($this->options, $parameters ?? new Parameters());
$this->commands = $this->options->commands;
}
/**
* Creates a new instance of Predis\Configuration\Options from different
* types of arguments or simply returns the passed argument if it is an
* instance of Predis\Configuration\OptionsInterface.
* Creates a new set of client options for the client.
*
* @param mixed $options Client options.
*
* @throws \InvalidArgumentException
* @param array|OptionsInterface $options Set of client options
*
* @return OptionsInterface
* @throws InvalidArgumentException
*/
protected function createOptions($options)
protected static function createOptions($options)
{
if (is_array($options)) {
return new Options($options);
}
if ($options instanceof OptionsInterface) {
} elseif ($options instanceof OptionsInterface) {
return $options;
} else {
throw new InvalidArgumentException('Invalid type for client options');
}
throw new \InvalidArgumentException('Invalid type for client options.');
}
/**
* Creates single or aggregate connections from different types of arguments
* (string, array) or returns the passed argument if it is an instance of a
* class implementing Predis\Connection\ConnectionInterface.
* Creates single or aggregate connections from supplied arguments.
*
* Accepted types for connection parameters are:
* This method accepts the following types to create a connection instance:
*
* - Instance of Predis\Connection\ConnectionInterface.
* - Instance of Predis\Connection\ParametersInterface.
* - Array
* - String
* - Callable
* - Array (dictionary: single connection, indexed: aggregate connections)
* - String (URI for a single connection)
* - Callable (connection initializer callback)
* - Instance of Predis\Connection\ParametersInterface (used as-is)
* - Instance of Predis\Connection\ConnectionInterface (returned as-is)
*
* @param mixed $parameters Connection parameters or connection instance.
* When a callable is passed, it receives the original set of client options
* and must return an instance of Predis\Connection\ConnectionInterface.
*
* @throws \InvalidArgumentException
* Connections are created using the connection factory (in case of single
* connections) or a specialized aggregate connection initializer (in case
* of cluster and replication) retrieved from the supplied client options.
*
* @param OptionsInterface $options Client options container
* @param mixed $parameters Connection parameters
*
* @return ConnectionInterface
* @throws InvalidArgumentException
*/
protected function createConnection($parameters)
protected static function createConnection(OptionsInterface $options, $parameters)
{
if ($parameters instanceof ConnectionInterface) {
return $parameters;
}
if ($parameters instanceof ParametersInterface || is_string($parameters)) {
return $this->options->connections->create($parameters);
return $options->connections->create($parameters);
}
if (is_array($parameters)) {
if (!isset($parameters[0])) {
return $this->options->connections->create($parameters);
}
$options = $this->options;
if ($options->defined('aggregate')) {
$initializer = $this->getConnectionInitializerWrapper($options->aggregate);
$connection = $initializer($parameters, $options);
return $options->connections->create($parameters);
} elseif ($options->defined('cluster') && $initializer = $options->cluster) {
return $initializer($parameters, true);
} elseif ($options->defined('replication') && $initializer = $options->replication) {
return $initializer($parameters, true);
} elseif ($options->defined('aggregate') && $initializer = $options->aggregate) {
return $initializer($parameters, false);
} else {
if ($options->defined('replication') && $replication = $options->replication) {
$connection = $replication;
} else {
$connection = $options->cluster;
}
$options->connections->aggregate($connection, $parameters);
throw new InvalidArgumentException(
'Array of connection parameters requires `cluster`, `replication` or `aggregate` client option'
);
}
return $connection;
}
if (is_callable($parameters)) {
$initializer = $this->getConnectionInitializerWrapper($parameters);
$connection = $initializer($this->options);
$connection = call_user_func($parameters, $options);
if (!$connection instanceof ConnectionInterface) {
throw new InvalidArgumentException('Callable parameters must return a valid connection');
}
return $connection;
}
throw new \InvalidArgumentException('Invalid type for connection parameters.');
}
/**
* Wraps a callable to make sure that its returned value represents a valid
* connection type.
*
* @param mixed $callable
*
* @return \Closure
*/
protected function getConnectionInitializerWrapper($callable)
{
return function () use ($callable) {
$connection = call_user_func_array($callable, func_get_args());
if (!$connection instanceof ConnectionInterface) {
throw new \UnexpectedValueException(
'The callable connection initializer returned an invalid type.'
);
}
return $connection;
};
throw new InvalidArgumentException('Invalid type for connection parameters');
}
/**
* {@inheritdoc}
*/
public function getProfile()
public function getCommandFactory()
{
return $this->profile;
return $this->commands;
}
/**
@ -183,23 +174,53 @@ class Client implements ClientInterface
}
/**
* Creates a new client instance for the specified connection ID or alias,
* only when working with an aggregate connection (cluster, replication).
* The new client instances uses the same options of the original one.
* Creates a new client using a specific underlying connection.
*
* @param string $connectionID Identifier of a connection.
* This method allows to create a new client instance by picking a specific
* connection out of an aggregate one, with the same options of the original
* client instance.
*
* @throws \InvalidArgumentException
* The specified selector defines which logic to use to look for a suitable
* connection by the specified value. Supported selectors are:
*
* @return Client
* - `id`
* - `key`
* - `slot`
* - `command`
* - `alias`
* - `role`
*
* Internally the client relies on duck-typing and follows this convention:
*
* $selector string => getConnectionBy$selector($value) method
*
* This means that support for specific selectors may vary depending on the
* actual logic implemented by connection classes and there is no interface
* binding a connection class to implement any of these.
*
* @param string $selector Type of selector.
* @param mixed $value Value to be used by the selector.
*
* @return ClientInterface
*/
public function getClientFor($connectionID)
public function getClientBy($selector, $value)
{
if (!$connection = $this->getConnectionById($connectionID)) {
throw new \InvalidArgumentException("Invalid connection ID: $connectionID.");
$selector = strtolower($selector);
if (!in_array($selector, ['id', 'key', 'slot', 'role', 'alias', 'command'])) {
throw new InvalidArgumentException("Invalid selector type: `$selector`");
}
return new static($connection, $this->options);
if (!method_exists($this->connection, $method = "getConnectionBy$selector")) {
$class = get_class($this->connection);
throw new InvalidArgumentException("Selecting connection by $selector is not supported by $class");
}
if (!$connection = $this->connection->$method($value)) {
throw new InvalidArgumentException("Cannot find a connection by $selector matching `$value`");
}
return new static($connection, $this->getOptions());
}
/**
@ -248,24 +269,29 @@ class Client implements ClientInterface
}
/**
* Retrieves the specified connection from the aggregate connection when the
* client is in cluster or replication mode.
* Applies the configured serializer and compression to given value.
*
* @param string $connectionID Index or alias of the single connection.
*
* @throws NotSupportedException
*
* @return Connection\NodeConnectionInterface
* @param mixed $value
* @return string
*/
public function getConnectionById($connectionID)
public function pack($value)
{
if (!$this->connection instanceof AggregateConnectionInterface) {
throw new NotSupportedException(
'Retrieving connections by ID is supported only by aggregate connections.'
);
}
return $this->connection instanceof RelayConnection
? $this->connection->pack($value)
: $value;
}
return $this->connection->getConnectionById($connectionID);
/**
* Deserializes and decompresses to given value.
*
* @param mixed $value
* @return string
*/
public function unpack($value)
{
return $this->connection instanceof RelayConnection
? $this->connection->unpack($value)
: $value;
}
/**
@ -273,7 +299,7 @@ class Client implements ClientInterface
* applying any prefix to keys or throwing exceptions on Redis errors even
* regardless of client options.
*
* It is possibile to indentify Redis error responses from normal responses
* It is possible to identify Redis error responses from normal responses
* using the second optional argument which is populated by reference.
*
* @param array $arguments Command arguments as defined by the command signature.
@ -284,9 +310,10 @@ class Client implements ClientInterface
public function executeRaw(array $arguments, &$error = null)
{
$error = false;
$commandID = array_shift($arguments);
$response = $this->connection->executeCommand(
new RawCommand($arguments)
new RawCommand($commandID, $arguments)
);
if ($response instanceof ResponseInterface) {
@ -313,9 +340,37 @@ class Client implements ClientInterface
/**
* {@inheritdoc}
*/
public function createCommand($commandID, $arguments = array())
public function createCommand($commandID, $arguments = [])
{
return $this->profile->createCommand($commandID, $arguments);
return $this->commands->create($commandID, $arguments);
}
/**
* @param string $name
* @return ContainerInterface
*/
public function __get(string $name)
{
return ContainerFactory::create($this, $name);
}
/**
* @param string $name
* @param mixed $value
* @return mixed
*/
public function __set(string $name, $value)
{
throw new RuntimeException('Not allowed');
}
/**
* @param string $name
* @return mixed
*/
public function __isset(string $name)
{
throw new RuntimeException('Not allowed');
}
/**
@ -342,17 +397,13 @@ class Client implements ClientInterface
* @param CommandInterface $command Redis command that generated the error.
* @param ErrorResponseInterface $response Instance of the error response.
*
* @throws ServerException
*
* @return mixed
* @throws ServerException
*/
protected function onErrorResponse(CommandInterface $command, ErrorResponseInterface $response)
{
if ($command instanceof ScriptCommand && $response->getErrorType() === 'NOSCRIPT') {
$eval = $this->createCommand('EVAL');
$eval->setRawArguments($command->getEvalArguments());
$response = $this->executeCommand($eval);
$response = $this->executeCommand($command->getEvalCommand());
if (!$response instanceof ResponseInterface) {
$response = $command->parseResponse($response);
@ -370,7 +421,7 @@ class Client implements ClientInterface
/**
* Executes the specified initializer method on `$this` by adjusting the
* actual invokation depending on the arity (0, 1 or 2 arguments). This is
* actual invocation depending on the arity (0, 1 or 2 arguments). This is
* simply an utility method to create Redis contexts instances since they
* follow a common initialization path.
*
@ -391,7 +442,7 @@ class Client implements ClientInterface
: $this->$initializer(null, $argv[0]);
case 2:
list($arg0, $arg1) = $argv;
[$arg0, $arg1] = $argv;
return $this->$initializer($arg0, $arg1);
@ -404,11 +455,11 @@ class Client implements ClientInterface
* Creates a new pipeline context and returns it, or returns the results of
* a pipeline executed inside the optionally provided callable object.
*
* @param mixed ... Array of options, a callable for execution, or both.
* @param mixed ...$arguments Array of options, a callable for execution, or both.
*
* @return Pipeline|array
*/
public function pipeline(/* arguments */)
public function pipeline(...$arguments)
{
return $this->sharedContextFactory('createPipeline', func_get_args());
}
@ -416,19 +467,29 @@ class Client implements ClientInterface
/**
* Actual pipeline context initializer method.
*
* @param array $options Options for the context.
* @param mixed $callable Optional callable used to execute the context.
* @param array|null $options Options for the context.
* @param mixed $callable Optional callable used to execute the context.
*
* @return Pipeline|array
*/
protected function createPipeline(array $options = null, $callable = null)
{
if (isset($options['atomic']) && $options['atomic']) {
$class = 'Predis\Pipeline\Atomic';
$class = Atomic::class;
} elseif (isset($options['fire-and-forget']) && $options['fire-and-forget']) {
$class = 'Predis\Pipeline\FireAndForget';
$class = FireAndForget::class;
} else {
$class = 'Predis\Pipeline\Pipeline';
$class = Pipeline::class;
}
if ($this->connection instanceof RelayConnection) {
if (isset($options['atomic']) && $options['atomic']) {
$class = RelayAtomic::class;
} elseif (isset($options['fire-and-forget']) && $options['fire-and-forget']) {
throw new NotSupportedException('The "relay" extension does not support fire-and-forget pipelines.');
} else {
$class = RelayPipeline::class;
}
}
/*
@ -447,11 +508,11 @@ class Client implements ClientInterface
* Creates a new transaction context and returns it, or returns the results
* of a transaction executed inside the optionally provided callable object.
*
* @param mixed ... Array of options, a callable for execution, or both.
* @param mixed ...$arguments Array of options, a callable for execution, or both.
*
* @return MultiExecTransaction|array
*/
public function transaction(/* arguments */)
public function transaction(...$arguments)
{
return $this->sharedContextFactory('createTransaction', func_get_args());
}
@ -476,14 +537,14 @@ class Client implements ClientInterface
}
/**
* Creates a new publis/subscribe context and returns it, or starts its loop
* Creates a new publish/subscribe context and returns it, or starts its loop
* inside the optionally provided callable object.
*
* @param mixed ... Array of options, a callable for execution, or both.
* @param mixed ...$arguments Array of options, a callable for execution, or both.
*
* @return PubSubConsumer|null
*/
public function pubSubLoop(/* arguments */)
public function pubSubLoop(...$arguments)
{
return $this->sharedContextFactory('createPubSub', func_get_args());
}
@ -498,7 +559,11 @@ class Client implements ClientInterface
*/
protected function createPubSub(array $options = null, $callable = null)
{
$pubsub = new PubSubConsumer($this, $options);
if ($this->connection instanceof RelayConnection) {
$pubsub = new RelayPubSubConsumer($this, $options);
} else {
$pubsub = new PubSubConsumer($this, $options);
}
if (!isset($callable)) {
return $pubsub;
@ -509,6 +574,8 @@ class Client implements ClientInterface
$pubsub->stop();
}
}
return null;
}
/**
@ -520,4 +587,26 @@ class Client implements ClientInterface
{
return new MonitorConsumer($this);
}
/**
* @return Traversable<string, static>
*/
#[ReturnTypeWillChange]
public function getIterator()
{
$clients = [];
$connection = $this->getConnection();
if (!$connection instanceof Traversable) {
return new ArrayIterator([
(string) $connection => new static($connection, $this->getOptions()),
]);
}
foreach ($connection as $node) {
$clients[(string) $node] = new static($node, $this->getOptions());
}
return new ArrayIterator($clients);
}
}

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -11,16 +12,49 @@
namespace Predis;
use Predis\Command\Argument\Geospatial\ByInterface;
use Predis\Command\Argument\Geospatial\FromInterface;
use Predis\Command\Argument\Search\AggregateArguments;
use Predis\Command\Argument\Search\AlterArguments;
use Predis\Command\Argument\Search\CreateArguments;
use Predis\Command\Argument\Search\DropArguments;
use Predis\Command\Argument\Search\ExplainArguments;
use Predis\Command\Argument\Search\ProfileArguments;
use Predis\Command\Argument\Search\SchemaFields\FieldInterface;
use Predis\Command\Argument\Search\SearchArguments;
use Predis\Command\Argument\Search\SugAddArguments;
use Predis\Command\Argument\Search\SugGetArguments;
use Predis\Command\Argument\Search\SynUpdateArguments;
use Predis\Command\Argument\Server\LimitOffsetCount;
use Predis\Command\Argument\Server\To;
use Predis\Command\Argument\TimeSeries\AddArguments;
use Predis\Command\Argument\TimeSeries\AlterArguments as TSAlterArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments as TSCreateArguments;
use Predis\Command\Argument\TimeSeries\DecrByArguments;
use Predis\Command\Argument\TimeSeries\GetArguments;
use Predis\Command\Argument\TimeSeries\IncrByArguments;
use Predis\Command\Argument\TimeSeries\InfoArguments;
use Predis\Command\Argument\TimeSeries\MGetArguments;
use Predis\Command\Argument\TimeSeries\MRangeArguments;
use Predis\Command\Argument\TimeSeries\RangeArguments;
use Predis\Command\CommandInterface;
use Predis\Command\Redis\Container\ACL;
use Predis\Command\Redis\Container\CLUSTER;
use Predis\Command\Redis\Container\FunctionContainer;
use Predis\Command\Redis\Container\Json\JSONDEBUG;
use Predis\Command\Redis\Container\Search\FTCONFIG;
use Predis\Command\Redis\Container\Search\FTCURSOR;
/**
* Interface defining a client-side context such as a pipeline or transaction.
*
* @method $this del(array $keys)
* @method $this copy(string $source, string $destination, int $db = -1, bool $replace = false)
* @method $this del(array|string $keys)
* @method $this dump($key)
* @method $this exists($key)
* @method $this expire($key, $seconds)
* @method $this expireat($key, $timestamp)
* @method $this expire($key, $seconds, string $expireOption = '')
* @method $this expireat($key, $timestamp, string $expireOption = '')
* @method $this expiretime(string $key)
* @method $this keys($pattern)
* @method $this move($key, $db)
* @method $this object($subcommand, $key)
@ -33,16 +67,77 @@ use Predis\Command\CommandInterface;
* @method $this renamenx($key, $target)
* @method $this scan($cursor, array $options = null)
* @method $this sort($key, array $options = null)
* @method $this sort_ro(string $key, ?string $byPattern = null, ?LimitOffsetCount $limit = null, array $getPatterns = [], ?string $sorting = null, bool $alpha = false)
* @method $this ttl($key)
* @method $this type($key)
* @method $this append($key, $value)
* @method $this bitcount($key, $start = null, $end = null)
* @method $this bfadd(string $key, $item)
* @method $this bfexists(string $key, $item)
* @method $this bfinfo(string $key, string $modifier = '')
* @method $this bfinsert(string $key, int $capacity = -1, float $error = -1, int $expansion = -1, bool $noCreate = false, bool $nonScaling = false, string ...$item)
* @method $this bfloadchunk(string $key, int $iterator, $data)
* @method $this bfmadd(string $key, ...$item)
* @method $this bfmexists(string $key, ...$item)
* @method $this bfreserve(string $key, float $errorRate, int $capacity, int $expansion = -1, bool $nonScaling = false)
* @method $this bfscandump(string $key, int $iterator)
* @method $this bitcount(string $key, $start = null, $end = null, string $index = 'byte')
* @method $this bitop($operation, $destkey, $key)
* @method $this bitfield($key, $subcommand, ...$subcommandArg)
* @method $this bitpos($key, $bit, $start = null, $end = null, string $index = 'byte')
* @method $this blmpop(int $timeout, array $keys, string $modifier = 'left', int $count = 1)
* @method $this bzpopmax(array $keys, int $timeout)
* @method $this bzpopmin(array $keys, int $timeout)
* @method $this bzmpop(int $timeout, array $keys, string $modifier = 'min', int $count = 1)
* @method $this cfadd(string $key, $item)
* @method $this cfaddnx(string $key, $item)
* @method $this cfcount(string $key, $item)
* @method $this cfdel(string $key, $item)
* @method $this cfexists(string $key, $item)
* @method $this cfloadchunk(string $key, int $iterator, $data)
* @method $this cfmexists(string $key, ...$item)
* @method $this cfinfo(string $key)
* @method $this cfinsert(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
* @method $this cfinsertnx(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
* @method $this cfreserve(string $key, int $capacity, int $bucketSize = -1, int $maxIterations = -1, int $expansion = -1)
* @method $this cfscandump(string $key, int $iterator)
* @method $this cmsincrby(string $key, string|int...$itemIncrementDictionary)
* @method $this cmsinfo(string $key)
* @method $this cmsinitbydim(string $key, int $width, int $depth)
* @method $this cmsinitbyprob(string $key, float $errorRate, float $probability)
* @method $this cmsmerge(string $destination, array $sources, array $weights = [])
* @method $this cmsquery(string $key, string ...$item)
* @method $this decr($key)
* @method $this decrby($key, $decrement)
* @method $this failover(?To $to = null, bool $abort = false, int $timeout = -1)
* @method $this fcall(string $function, array $keys, ...$args)
* @method $this fcall_ro(string $function, array $keys, ...$args)
* @method $this ftaggregate(string $index, string $query, ?AggregateArguments $arguments = null)
* @method $this ftaliasadd(string $alias, string $index)
* @method $this ftaliasdel(string $alias)
* @method $this ftaliasupdate(string $alias, string $index)
* @method $this ftalter(string $index, FieldInterface[] $schema, ?AlterArguments $arguments = null)
* @method $this ftcreate(string $index, FieldInterface[] $schema, ?CreateArguments $arguments = null)
* @method $this ftdictadd(string $dict, ...$term)
* @method $this ftdictdel(string $dict, ...$term)
* @method $this ftdictdump(string $dict)
* @method $this ftdropindex(string $index, ?DropArguments $arguments = null)
* @method $this ftexplain(string $index, string $query, ?ExplainArguments $arguments = null)
* @method $this ftinfo(string $index)
* @method $this ftprofile(string $index, ProfileArguments $arguments)
* @method $this ftsearch(string $index, string $query, ?SearchArguments $arguments = null)
* @method $this ftspellcheck(string $index, string $query, ?SearchArguments $arguments = null)
* @method $this ftsugadd(string $key, string $string, float $score, ?SugAddArguments $arguments = null)
* @method $this ftsugdel(string $key, string $string)
* @method $this ftsugget(string $key, string $prefix, ?SugGetArguments $arguments = null)
* @method $this ftsuglen(string $key)
* @method $this ftsyndump(string $index)
* @method $this ftsynupdate(string $index, string $synonymGroupId, ?SynUpdateArguments $arguments = null, string ...$terms)
* @method $this fttagvals(string $index, string $fieldName)
* @method $this get($key)
* @method $this getbit($key, $offset)
* @method $this getex(string $key, $modifier = '', $value = false)
* @method $this getrange($key, $start, $end)
* @method $this getdel(string $key)
* @method $this getset($key, $value)
* @method $this incr($key)
* @method $this incrby($key, $increment)
@ -67,19 +162,47 @@ use Predis\Command\CommandInterface;
* @method $this hlen($key)
* @method $this hmget($key, array $fields)
* @method $this hmset($key, array $dictionary)
* @method $this hrandfield(string $key, int $count = 1, bool $withValues = false)
* @method $this hscan($key, $cursor, array $options = null)
* @method $this hset($key, $field, $value)
* @method $this hsetnx($key, $field, $value)
* @method $this hvals($key)
* @method $this blpop(array $keys, $timeout)
* @method $this brpop(array $keys, $timeout)
* @method $this hstrlen($key, $field)
* @method $this jsonarrappend(string $key, string $path = '$', ...$value)
* @method $this jsonarrindex(string $key, string $path, string $value, int $start = 0, int $stop = 0)
* @method $this jsonarrinsert(string $key, string $path, int $index, string ...$value)
* @method $this jsonarrlen(string $key, string $path = '$')
* @method $this jsonarrpop(string $key, string $path = '$', int $index = -1)
* @method $this jsonarrtrim(string $key, string $path, int $start, int $stop)
* @method $this jsonclear(string $key, string $path = '$')
* @method $this jsondel(string $key, string $path = '$')
* @method $this jsonforget(string $key, string $path = '$')
* @method $this jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths)
* @method $this jsonnumincrby(string $key, string $path, int $value)
* @method $this jsonmerge(string $key, string $path, string $value)
* @method $this jsonmget(array $keys, string $path)
* @method $this jsonmset(string ...$keyPathValue)
* @method $this jsonobjkeys(string $key, string $path = '$')
* @method $this jsonobjlen(string $key, string $path = '$')
* @method $this jsonresp(string $key, string $path = '$')
* @method $this jsonset(string $key, string $path, string $value, ?string $subcommand = null)
* @method $this jsonstrappend(string $key, string $path, string $value)
* @method $this jsonstrlen(string $key, string $path = '$')
* @method $this jsontoggle(string $key, string $path)
* @method $this jsontype(string $key, string $path = '$')
* @method $this blmove(string $source, string $destination, string $where, string $to, int $timeout)
* @method $this blpop(array|string $keys, $timeout)
* @method $this brpop(array|string $keys, $timeout)
* @method $this brpoplpush($source, $destination, $timeout)
* @method $this lcs(string $key1, string $key2, bool $len = false, bool $idx = false, int $minMatchLen = 0, bool $withMatchLen = false)
* @method $this lindex($key, $index)
* @method $this linsert($key, $whence, $pivot, $value)
* @method $this llen($key)
* @method $this lmove(string $source, string $destination, string $where, string $to)
* @method $this lmpop(array $keys, string $modifier = 'left', int $count = 1)
* @method $this lpop($key)
* @method $this lpush($key, array $values)
* @method $this lpushx($key, $value)
* @method $this lpushx($key, array $values)
* @method $this lrange($key, $start, $stop)
* @method $this lrem($key, $count, $value)
* @method $this lset($key, $index, $value)
@ -87,55 +210,109 @@ use Predis\Command\CommandInterface;
* @method $this rpop($key)
* @method $this rpoplpush($source, $destination)
* @method $this rpush($key, array $values)
* @method $this rpushx($key, $value)
* @method $this rpushx($key, array $values)
* @method $this sadd($key, array $members)
* @method $this scard($key)
* @method $this sdiff(array $keys)
* @method $this sdiffstore($destination, array $keys)
* @method $this sinter(array $keys)
* @method $this sinterstore($destination, array $keys)
* @method $this sdiff(array|string $keys)
* @method $this sdiffstore($destination, array|string $keys)
* @method $this sinter(array|string $keys)
* @method $this sintercard(array $keys, int $limit = 0)
* @method $this sinterstore($destination, array|string $keys)
* @method $this sismember($key, $member)
* @method $this smembers($key)
* @method $this smismember(string $key, string ...$members)
* @method $this smove($source, $destination, $member)
* @method $this spop($key)
* @method $this spop($key, $count = null)
* @method $this srandmember($key, $count = null)
* @method $this srem($key, $member)
* @method $this sscan($key, $cursor, array $options = null)
* @method $this sunion(array $keys)
* @method $this sunionstore($destination, array $keys)
* @method $this sunion(array|string $keys)
* @method $this sunionstore($destination, array|string $keys)
* @method $this tdigestadd(string $key, float ...$value)
* @method $this tdigestbyrank(string $key, int ...$rank)
* @method $this tdigestbyrevrank(string $key, int ...$reverseRank)
* @method $this tdigestcdf(string $key, int ...$value)
* @method $this tdigestcreate(string $key, int $compression = 0)
* @method $this tdigestinfo(string $key)
* @method $this tdigestmax(string $key)
* @method $this tdigestmerge(string $destinationKey, array $sourceKeys, int $compression = 0, bool $override = false)
* @method $this tdigestquantile(string $key, float ...$quantile)
* @method $this tdigestmin(string $key)
* @method $this tdigestrank(string $key, ...$value)
* @method $this tdigestreset(string $key)
* @method $this tdigestrevrank(string $key, float ...$value)
* @method $this tdigesttrimmed_mean(string $key, float $lowCutQuantile, float $highCutQuantile)
* @method $this topkadd(string $key, ...$items)
* @method $this topkincrby(string $key, ...$itemIncrement)
* @method $this topkinfo(string $key)
* @method $this topklist(string $key, bool $withCount = false)
* @method $this topkquery(string $key, ...$items)
* @method $this topkreserve(string $key, int $topK, int $width = 8, int $depth = 7, float $decay = 0.9)
* @method $this tsadd(string $key, int $timestamp, float $value, ?AddArguments $arguments = null)
* @method $this tsalter(string $key, ?TSAlterArguments $arguments = null)
* @method $this tscreate(string $key, ?TSCreateArguments $arguments = null)
* @method $this tscreaterule(string $sourceKey, string $destKey, string $aggregator, int $bucketDuration, int $alignTimestamp = 0)
* @method $this tsdecrby(string $key, float $value, ?DecrByArguments $arguments = null)
* @method $this tsdel(string $key, int $fromTimestamp, int $toTimestamp)
* @method $this tsdeleterule(string $sourceKey, string $destKey)
* @method $this tsget(string $key, GetArguments $arguments = null)
* @method $this tsincrby(string $key, float $value, ?IncrByArguments $arguments = null)
* @method $this tsinfo(string $key, ?InfoArguments $arguments = null)
* @method $this tsmadd(mixed ...$keyTimestampValue)
* @method $this tsmget(MGetArguments $arguments, string ...$filterExpression)
* @method $this tsmrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method $this tsmrevrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method $this tsqueryindex(string ...$filterExpression)
* @method $this tsrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method $this tsrevrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method $this zadd($key, array $membersAndScoresDictionary)
* @method $this zcard($key)
* @method $this zcount($key, $min, $max)
* @method $this zdiff(array $keys, bool $withScores = false)
* @method $this zdiffstore(string $destination, array $keys)
* @method $this zincrby($key, $increment, $member)
* @method $this zinterstore($destination, array $keys, array $options = null)
* @method $this zintercard(array $keys, int $limit = 0)
* @method $this zinterstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
* @method $this zinter(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
* @method $this zmpop(array $keys, string $modifier = 'min', int $count = 1)
* @method $this zmscore(string $key, string ...$member)
* @method $this zrandmember(string $key, int $count = 1, bool $withScores = false)
* @method $this zrange($key, $start, $stop, array $options = null)
* @method $this zrangebyscore($key, $min, $max, array $options = null)
* @method $this zrangestore(string $destination, string $source, int|string $min, string|int $max, string|bool $by = false, bool $reversed = false, bool $limit = false, int $offset = 0, int $count = 0)
* @method $this zrank($key, $member)
* @method $this zrem($key, $member)
* @method $this zremrangebyrank($key, $start, $stop)
* @method $this zremrangebyscore($key, $min, $max)
* @method $this zrevrange($key, $start, $stop, array $options = null)
* @method $this zrevrangebyscore($key, $min, $max, array $options = null)
* @method $this zrevrangebyscore($key, $max, $min, array $options = null)
* @method $this zrevrank($key, $member)
* @method $this zunionstore($destination, array $keys, array $options = null)
* @method $this zunion(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
* @method $this zunionstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
* @method $this zscore($key, $member)
* @method $this zscan($key, $cursor, array $options = null)
* @method $this zrangebylex($key, $start, $stop, array $options = null)
* @method $this zrevrangebylex($key, $start, $stop, array $options = null)
* @method $this zremrangebylex($key, $min, $max)
* @method $this zlexcount($key, $min, $max)
* @method $this pexpiretime(string $key)
* @method $this pfadd($key, array $elements)
* @method $this pfmerge($destinationKey, array $sourceKeys)
* @method $this pfcount(array $keys)
* @method $this pfmerge($destinationKey, array|string $sourceKeys)
* @method $this pfcount(array|string $keys)
* @method $this pubsub($subcommand, $argument)
* @method $this publish($channel, $message)
* @method $this discard()
* @method $this exec()
* @method $this multi()
* @method $this unwatch()
* @method $this waitaof(int $numLocal, int $numReplicas, int $timeout)
* @method $this watch($key)
* @method $this eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this eval_ro(string $script, array $keys, ...$argument)
* @method $this evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this evalsha_ro(string $sha1, array $keys, ...$argument)
* @method $this script($subcommand, $argument = null)
* @method $this shutdown(bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
* @method $this auth($password)
* @method $this echo($message)
* @method $this ping($message = null)
@ -154,8 +331,22 @@ use Predis\Command\CommandInterface;
* @method $this slowlog($subcommand, $argument = null)
* @method $this time()
* @method $this command()
* @method $this geoadd($key, $longitude, $latitude, $member)
* @method $this geohash($key, array $members)
* @method $this geopos($key, array $members)
* @method $this geodist($key, $member1, $member2, $unit = null)
* @method $this georadius($key, $longitude, $latitude, $radius, $unit, array $options = null)
* @method $this georadiusbymember($key, $member, $radius, $unit, array $options = null)
* @method $this geosearch(string $key, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $withCoord = false, bool $withDist = false, bool $withHash = false)
* @method $this geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* Container commands
* @property CLUSTER $cluster
* @property FunctionContainer $function
* @property FTCONFIG $ftconfig
* @property FTCURSOR $ftcursor
* @property JSONDEBUG $jsondebug
* @property ACL $acl
*/
interface ClientContextInterface
{

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -13,8 +14,6 @@ namespace Predis;
/**
* Exception class that identifies client-side errors.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ClientException extends PredisException
{

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -11,10 +12,42 @@
namespace Predis;
use Predis\Command\Argument\Geospatial\ByInterface;
use Predis\Command\Argument\Geospatial\FromInterface;
use Predis\Command\Argument\Search\AggregateArguments;
use Predis\Command\Argument\Search\AlterArguments;
use Predis\Command\Argument\Search\CreateArguments;
use Predis\Command\Argument\Search\DropArguments;
use Predis\Command\Argument\Search\ExplainArguments;
use Predis\Command\Argument\Search\ProfileArguments;
use Predis\Command\Argument\Search\SchemaFields\FieldInterface;
use Predis\Command\Argument\Search\SearchArguments;
use Predis\Command\Argument\Search\SugAddArguments;
use Predis\Command\Argument\Search\SugGetArguments;
use Predis\Command\Argument\Search\SynUpdateArguments;
use Predis\Command\Argument\Server\LimitOffsetCount;
use Predis\Command\Argument\Server\To;
use Predis\Command\Argument\TimeSeries\AddArguments;
use Predis\Command\Argument\TimeSeries\AlterArguments as TSAlterArguments;
use Predis\Command\Argument\TimeSeries\CreateArguments as TSCreateArguments;
use Predis\Command\Argument\TimeSeries\DecrByArguments;
use Predis\Command\Argument\TimeSeries\GetArguments;
use Predis\Command\Argument\TimeSeries\IncrByArguments;
use Predis\Command\Argument\TimeSeries\InfoArguments;
use Predis\Command\Argument\TimeSeries\MGetArguments;
use Predis\Command\Argument\TimeSeries\MRangeArguments;
use Predis\Command\Argument\TimeSeries\RangeArguments;
use Predis\Command\CommandInterface;
use Predis\Command\FactoryInterface;
use Predis\Command\Redis\Container\ACL;
use Predis\Command\Redis\Container\CLUSTER;
use Predis\Command\Redis\Container\FunctionContainer;
use Predis\Command\Redis\Container\Json\JSONDEBUG;
use Predis\Command\Redis\Container\Search\FTCONFIG;
use Predis\Command\Redis\Container\Search\FTCURSOR;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Profile\ProfileInterface;
use Predis\Response\Status;
/**
* Interface defining a client able to execute commands against Redis.
@ -24,155 +57,323 @@ use Predis\Profile\ProfileInterface;
* and more friendly interface to ease programming which is described in the
* following list of methods:
*
* @method int del(array $keys)
* @method string dump($key)
* @method int exists($key)
* @method int expire($key, $seconds)
* @method int expireat($key, $timestamp)
* @method array keys($pattern)
* @method int move($key, $db)
* @method mixed object($subcommand, $key)
* @method int persist($key)
* @method int pexpire($key, $milliseconds)
* @method int pexpireat($key, $timestamp)
* @method int pttl($key)
* @method string randomkey()
* @method mixed rename($key, $target)
* @method int renamenx($key, $target)
* @method array scan($cursor, array $options = null)
* @method array sort($key, array $options = null)
* @method int ttl($key)
* @method mixed type($key)
* @method int append($key, $value)
* @method int bitcount($key, $start = null, $end = null)
* @method int bitop($operation, $destkey, $key)
* @method int decr($key)
* @method int decrby($key, $decrement)
* @method string get($key)
* @method int getbit($key, $offset)
* @method string getrange($key, $start, $end)
* @method string getset($key, $value)
* @method int incr($key)
* @method int incrby($key, $increment)
* @method string incrbyfloat($key, $increment)
* @method array mget(array $keys)
* @method mixed mset(array $dictionary)
* @method int msetnx(array $dictionary)
* @method mixed psetex($key, $milliseconds, $value)
* @method mixed set($key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
* @method int setbit($key, $offset, $value)
* @method int setex($key, $seconds, $value)
* @method int setnx($key, $value)
* @method int setrange($key, $offset, $value)
* @method int strlen($key)
* @method int hdel($key, array $fields)
* @method int hexists($key, $field)
* @method string hget($key, $field)
* @method array hgetall($key)
* @method int hincrby($key, $field, $increment)
* @method string hincrbyfloat($key, $field, $increment)
* @method array hkeys($key)
* @method int hlen($key)
* @method array hmget($key, array $fields)
* @method mixed hmset($key, array $dictionary)
* @method array hscan($key, $cursor, array $options = null)
* @method int hset($key, $field, $value)
* @method int hsetnx($key, $field, $value)
* @method array hvals($key)
* @method array blpop(array $keys, $timeout)
* @method array brpop(array $keys, $timeout)
* @method array brpoplpush($source, $destination, $timeout)
* @method string lindex($key, $index)
* @method int linsert($key, $whence, $pivot, $value)
* @method int llen($key)
* @method string lpop($key)
* @method int lpush($key, array $values)
* @method int lpushx($key, $value)
* @method array lrange($key, $start, $stop)
* @method int lrem($key, $count, $value)
* @method mixed lset($key, $index, $value)
* @method mixed ltrim($key, $start, $stop)
* @method string rpop($key)
* @method string rpoplpush($source, $destination)
* @method int rpush($key, array $values)
* @method int rpushx($key, $value)
* @method int sadd($key, array $members)
* @method int scard($key)
* @method array sdiff(array $keys)
* @method int sdiffstore($destination, array $keys)
* @method array sinter(array $keys)
* @method int sinterstore($destination, array $keys)
* @method int sismember($key, $member)
* @method array smembers($key)
* @method int smove($source, $destination, $member)
* @method string spop($key)
* @method string srandmember($key, $count = null)
* @method int srem($key, $member)
* @method array sscan($key, $cursor, array $options = null)
* @method array sunion(array $keys)
* @method int sunionstore($destination, array $keys)
* @method int zadd($key, array $membersAndScoresDictionary)
* @method int zcard($key)
* @method string zcount($key, $min, $max)
* @method string zincrby($key, $increment, $member)
* @method int zinterstore($destination, array $keys, array $options = null)
* @method array zrange($key, $start, $stop, array $options = null)
* @method array zrangebyscore($key, $min, $max, array $options = null)
* @method int zrank($key, $member)
* @method int zrem($key, $member)
* @method int zremrangebyrank($key, $start, $stop)
* @method int zremrangebyscore($key, $min, $max)
* @method array zrevrange($key, $start, $stop, array $options = null)
* @method array zrevrangebyscore($key, $min, $max, array $options = null)
* @method int zrevrank($key, $member)
* @method int zunionstore($destination, array $keys, array $options = null)
* @method string zscore($key, $member)
* @method array zscan($key, $cursor, array $options = null)
* @method array zrangebylex($key, $start, $stop, array $options = null)
* @method int zremrangebylex($key, $min, $max)
* @method int zlexcount($key, $min, $max)
* @method int pfadd($key, array $elements)
* @method mixed pfmerge($destinationKey, array $sourceKeys)
* @method int pfcount(array $keys)
* @method mixed pubsub($subcommand, $argument)
* @method int publish($channel, $message)
* @method mixed discard()
* @method array exec()
* @method mixed multi()
* @method mixed unwatch()
* @method mixed watch($key)
* @method mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method mixed evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method mixed script($subcommand, $argument = null)
* @method mixed auth($password)
* @method string echo($message)
* @method mixed ping($message = null)
* @method mixed select($database)
* @method mixed bgrewriteaof()
* @method mixed bgsave()
* @method mixed client($subcommand, $argument = null)
* @method mixed config($subcommand, $argument = null)
* @method int dbsize()
* @method mixed flushall()
* @method mixed flushdb()
* @method array info($section = null)
* @method int lastsave()
* @method mixed save()
* @method mixed slaveof($host, $port)
* @method mixed slowlog($subcommand, $argument = null)
* @method array time()
* @method array command()
* @method int copy(string $source, string $destination, int $db = -1, bool $replace = false)
* @method int del(string[]|string $keyOrKeys, string ...$keys = null)
* @method string|null dump(string $key)
* @method int exists(string $key)
* @method int expire(string $key, int $seconds, string $expireOption = '')
* @method int expireat(string $key, int $timestamp, string $expireOption = '')
* @method int expiretime(string $key)
* @method array keys(string $pattern)
* @method int move(string $key, int $db)
* @method mixed object($subcommand, string $key)
* @method int persist(string $key)
* @method int pexpire(string $key, int $milliseconds)
* @method int pexpireat(string $key, int $timestamp)
* @method int pttl(string $key)
* @method string|null randomkey()
* @method mixed rename(string $key, string $target)
* @method int renamenx(string $key, string $target)
* @method array scan($cursor, array $options = null)
* @method array sort(string $key, array $options = null)
* @method array sort_ro(string $key, ?string $byPattern = null, ?LimitOffsetCount $limit = null, array $getPatterns = [], ?string $sorting = null, bool $alpha = false)
* @method int ttl(string $key)
* @method mixed type(string $key)
* @method int append(string $key, $value)
* @method int bfadd(string $key, $item)
* @method int bfexists(string $key, $item)
* @method array bfinfo(string $key, string $modifier = '')
* @method array bfinsert(string $key, int $capacity = -1, float $error = -1, int $expansion = -1, bool $noCreate = false, bool $nonScaling = false, string ...$item)
* @method Status bfloadchunk(string $key, int $iterator, $data)
* @method array bfmadd(string $key, ...$item)
* @method array bfmexists(string $key, ...$item)
* @method Status bfreserve(string $key, float $errorRate, int $capacity, int $expansion = -1, bool $nonScaling = false)
* @method array bfscandump(string $key, int $iterator)
* @method int bitcount(string $key, $start = null, $end = null, string $index = 'byte')
* @method int bitop($operation, $destkey, $key)
* @method array|null bitfield(string $key, $subcommand, ...$subcommandArg)
* @method int bitpos(string $key, $bit, $start = null, $end = null, string $index = 'byte')
* @method array blmpop(int $timeout, array $keys, string $modifier = 'left', int $count = 1)
* @method array bzpopmax(array $keys, int $timeout)
* @method array bzpopmin(array $keys, int $timeout)
* @method array bzmpop(int $timeout, array $keys, string $modifier = 'min', int $count = 1)
* @method int cfadd(string $key, $item)
* @method int cfaddnx(string $key, $item)
* @method int cfcount(string $key, $item)
* @method int cfdel(string $key, $item)
* @method int cfexists(string $key, $item)
* @method Status cfloadchunk(string $key, int $iterator, $data)
* @method int cfmexists(string $key, ...$item)
* @method array cfinfo(string $key)
* @method array cfinsert(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
* @method array cfinsertnx(string $key, int $capacity = -1, bool $noCreate = false, string ...$item)
* @method Status cfreserve(string $key, int $capacity, int $bucketSize = -1, int $maxIterations = -1, int $expansion = -1)
* @method array cfscandump(string $key, int $iterator)
* @method array cmsincrby(string $key, string|int...$itemIncrementDictionary)
* @method array cmsinfo(string $key)
* @method Status cmsinitbydim(string $key, int $width, int $depth)
* @method Status cmsinitbyprob(string $key, float $errorRate, float $probability)
* @method Status cmsmerge(string $destination, array $sources, array $weights = [])
* @method array cmsquery(string $key, string ...$item)
* @method int decr(string $key)
* @method int decrby(string $key, int $decrement)
* @method Status failover(?To $to = null, bool $abort = false, int $timeout = -1)
* @method mixed fcall(string $function, array $keys, ...$args)
* @method mixed fcall_ro(string $function, array $keys, ...$args)
* @method array ftaggregate(string $index, string $query, ?AggregateArguments $arguments = null)
* @method Status ftaliasadd(string $alias, string $index)
* @method Status ftaliasdel(string $alias)
* @method Status ftaliasupdate(string $alias, string $index)
* @method Status ftalter(string $index, FieldInterface[] $schema, ?AlterArguments $arguments = null)
* @method Status ftcreate(string $index, FieldInterface[] $schema, ?CreateArguments $arguments = null)
* @method int ftdictadd(string $dict, ...$term)
* @method int ftdictdel(string $dict, ...$term)
* @method array ftdictdump(string $dict)
* @method Status ftdropindex(string $index, ?DropArguments $arguments = null)
* @method string ftexplain(string $index, string $query, ?ExplainArguments $arguments = null)
* @method array ftinfo(string $index)
* @method array ftprofile(string $index, ProfileArguments $arguments)
* @method array ftsearch(string $index, string $query, ?SearchArguments $arguments = null)
* @method array ftspellcheck(string $index, string $query, ?SearchArguments $arguments = null)
* @method int ftsugadd(string $key, string $string, float $score, ?SugAddArguments $arguments = null)
* @method int ftsugdel(string $key, string $string)
* @method array ftsugget(string $key, string $prefix, ?SugGetArguments $arguments = null)
* @method int ftsuglen(string $key)
* @method array ftsyndump(string $index)
* @method Status ftsynupdate(string $index, string $synonymGroupId, ?SynUpdateArguments $arguments = null, string ...$terms)
* @method array fttagvals(string $index, string $fieldName)
* @method string|null get(string $key)
* @method int getbit(string $key, $offset)
* @method int|null getex(string $key, $modifier = '', $value = false)
* @method string getrange(string $key, $start, $end)
* @method string getdel(string $key)
* @method string|null getset(string $key, $value)
* @method int incr(string $key)
* @method int incrby(string $key, int $increment)
* @method string incrbyfloat(string $key, int|float $increment)
* @method array mget(string[]|string $keyOrKeys, string ...$keys = null)
* @method mixed mset(array $dictionary)
* @method int msetnx(array $dictionary)
* @method Status psetex(string $key, $milliseconds, $value)
* @method Status set(string $key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
* @method int setbit(string $key, $offset, $value)
* @method Status setex(string $key, $seconds, $value)
* @method int setnx(string $key, $value)
* @method int setrange(string $key, $offset, $value)
* @method int strlen(string $key)
* @method int hdel(string $key, array $fields)
* @method int hexists(string $key, string $field)
* @method string|null hget(string $key, string $field)
* @method array hgetall(string $key)
* @method int hincrby(string $key, string $field, int $increment)
* @method string hincrbyfloat(string $key, string $field, int|float $increment)
* @method array hkeys(string $key)
* @method int hlen(string $key)
* @method array hmget(string $key, array $fields)
* @method mixed hmset(string $key, array $dictionary)
* @method array hrandfield(string $key, int $count = 1, bool $withValues = false)
* @method array hscan(string $key, $cursor, array $options = null)
* @method int hset(string $key, string $field, string $value)
* @method int hsetnx(string $key, string $field, string $value)
* @method array hvals(string $key)
* @method int hstrlen(string $key, string $field)
* @method array jsonarrappend(string $key, string $path = '$', ...$value)
* @method array jsonarrindex(string $key, string $path, string $value, int $start = 0, int $stop = 0)
* @method array jsonarrinsert(string $key, string $path, int $index, string ...$value)
* @method array jsonarrlen(string $key, string $path = '$')
* @method array jsonarrpop(string $key, string $path = '$', int $index = -1)
* @method int jsonclear(string $key, string $path = '$')
* @method array jsonarrtrim(string $key, string $path, int $start, int $stop)
* @method int jsondel(string $key, string $path = '$')
* @method int jsonforget(string $key, string $path = '$')
* @method string jsonget(string $key, string $indent = '', string $newline = '', string $space = '', string ...$paths)
* @method string jsonnumincrby(string $key, string $path, int $value)
* @method Status jsonmerge(string $key, string $path, string $value)
* @method array jsonmget(array $keys, string $path)
* @method Status jsonmset(string ...$keyPathValue)
* @method array jsonobjkeys(string $key, string $path = '$')
* @method array jsonobjlen(string $key, string $path = '$')
* @method array jsonresp(string $key, string $path = '$')
* @method string jsonset(string $key, string $path, string $value, ?string $subcommand = null)
* @method array jsonstrappend(string $key, string $path, string $value)
* @method array jsonstrlen(string $key, string $path = '$')
* @method array jsontoggle(string $key, string $path)
* @method array jsontype(string $key, string $path = '$')
* @method string blmove(string $source, string $destination, string $where, string $to, int $timeout)
* @method array|null blpop(array|string $keys, int|float $timeout)
* @method array|null brpop(array|string $keys, int|float $timeout)
* @method string|null brpoplpush(string $source, string $destination, int|float $timeout)
* @method mixed lcs(string $key1, string $key2, bool $len = false, bool $idx = false, int $minMatchLen = 0, bool $withMatchLen = false)
* @method string|null lindex(string $key, int $index)
* @method int linsert(string $key, $whence, $pivot, $value)
* @method int llen(string $key)
* @method string lmove(string $source, string $destination, string $where, string $to)
* @method array|null lmpop(array $keys, string $modifier = 'left', int $count = 1)
* @method string|null lpop(string $key)
* @method int lpush(string $key, array $values)
* @method int lpushx(string $key, array $values)
* @method string[] lrange(string $key, int $start, int $stop)
* @method int lrem(string $key, int $count, string $value)
* @method mixed lset(string $key, int $index, string $value)
* @method mixed ltrim(string $key, int $start, int $stop)
* @method string|null rpop(string $key)
* @method string|null rpoplpush(string $source, string $destination)
* @method int rpush(string $key, array $values)
* @method int rpushx(string $key, array $values)
* @method int sadd(string $key, array $members)
* @method int scard(string $key)
* @method string[] sdiff(array|string $keys)
* @method int sdiffstore(string $destination, array|string $keys)
* @method string[] sinter(array|string $keys)
* @method int sintercard(array $keys, int $limit = 0)
* @method int sinterstore(string $destination, array|string $keys)
* @method int sismember(string $key, string $member)
* @method string[] smembers(string $key)
* @method array smismember(string $key, string ...$members)
* @method int smove(string $source, string $destination, string $member)
* @method string|array|null spop(string $key, int $count = null)
* @method string|null srandmember(string $key, int $count = null)
* @method int srem(string $key, array|string $member)
* @method array sscan(string $key, int $cursor, array $options = null)
* @method string[] sunion(array|string $keys)
* @method int sunionstore(string $destination, array|string $keys)
* @method int touch(string[]|string $keyOrKeys, string ...$keys = null)
* @method Status tdigestadd(string $key, float ...$value)
* @method array tdigestbyrank(string $key, int ...$rank)
* @method array tdigestbyrevrank(string $key, int ...$reverseRank)
* @method array tdigestcdf(string $key, int ...$value)
* @method Status tdigestcreate(string $key, int $compression = 0)
* @method array tdigestinfo(string $key)
* @method string tdigestmax(string $key)
* @method Status tdigestmerge(string $destinationKey, array $sourceKeys, int $compression = 0, bool $override = false)
* @method string[] tdigestquantile(string $key, float ...$quantile)
* @method string tdigestmin(string $key)
* @method array tdigestrank(string $key, float ...$value)
* @method Status tdigestreset(string $key)
* @method array tdigestrevrank(string $key, float ...$value)
* @method string tdigesttrimmed_mean(string $key, float $lowCutQuantile, float $highCutQuantile)
* @method array topkadd(string $key, ...$items)
* @method array topkincrby(string $key, ...$itemIncrement)
* @method array topkinfo(string $key)
* @method array topklist(string $key, bool $withCount = false)
* @method array topkquery(string $key, ...$items)
* @method Status topkreserve(string $key, int $topK, int $width = 8, int $depth = 7, float $decay = 0.9)
* @method int tsadd(string $key, int $timestamp, float $value, ?AddArguments $arguments = null)
* @method Status tsalter(string $key, ?TSAlterArguments $arguments = null)
* @method Status tscreate(string $key, ?TSCreateArguments $arguments = null)
* @method Status tscreaterule(string $sourceKey, string $destKey, string $aggregator, int $bucketDuration, int $alignTimestamp = 0)
* @method int tsdecrby(string $key, float $value, ?DecrByArguments $arguments = null)
* @method int tsdel(string $key, int $fromTimestamp, int $toTimestamp)
* @method Status tsdeleterule(string $sourceKey, string $destKey)
* @method array tsget(string $key, GetArguments $arguments = null)
* @method int tsincrby(string $key, float $value, ?IncrByArguments $arguments = null)
* @method array tsinfo(string $key, ?InfoArguments $arguments = null)
* @method array tsmadd(mixed ...$keyTimestampValue)
* @method array tsmget(MGetArguments $arguments, string ...$filterExpression)
* @method array tsmrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method array tsmrevrange($fromTimestamp, $toTimestamp, MRangeArguments $arguments)
* @method array tsqueryindex(string ...$filterExpression)
* @method array tsrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method array tsrevrange(string $key, $fromTimestamp, $toTimestamp, ?RangeArguments $arguments = null)
* @method string xadd(string $key, array $dictionary, string $id = '*', array $options = null)
* @method int xdel(string $key, string ...$id)
* @method int xlen(string $key)
* @method array xrevrange(string $key, string $end, string $start, ?int $count = null)
* @method array xrange(string $key, string $start, string $end, ?int $count = null)
* @method string xtrim(string $key, array|string $strategy, string $threshold, array $options = null)
* @method int zadd(string $key, array $membersAndScoresDictionary)
* @method int zcard(string $key)
* @method string zcount(string $key, int|string $min, int|string $max)
* @method array zdiff(array $keys, bool $withScores = false)
* @method int zdiffstore(string $destination, array $keys)
* @method string zincrby(string $key, int $increment, string $member)
* @method int zintercard(array $keys, int $limit = 0)
* @method int zinterstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
* @method array zinter(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
* @method array zmpop(array $keys, string $modifier = 'min', int $count = 1)
* @method array zmscore(string $key, string ...$member)
* @method array zpopmin(string $key, int $count = 1)
* @method array zpopmax(string $key, int $count = 1)
* @method mixed zrandmember(string $key, int $count = 1, bool $withScores = false)
* @method array zrange(string $key, int|string $start, int|string $stop, array $options = null)
* @method array zrangebyscore(string $key, int|string $min, int|string $max, array $options = null)
* @method int zrangestore(string $destination, string $source, int|string $min, int|string $max, string|bool $by = false, bool $reversed = false, bool $limit = false, int $offset = 0, int $count = 0)
* @method int|null zrank(string $key, string $member)
* @method int zrem(string $key, string ...$member)
* @method int zremrangebyrank(string $key, int|string $start, int|string $stop)
* @method int zremrangebyscore(string $key, int|string $min, int|string $max)
* @method array zrevrange(string $key, int|string $start, int|string $stop, array $options = null)
* @method array zrevrangebyscore(string $key, int|string $max, int|string $min, array $options = null)
* @method int|null zrevrank(string $key, string $member)
* @method array zunion(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
* @method int zunionstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
* @method string|null zscore(string $key, string $member)
* @method array zscan(string $key, int $cursor, array $options = null)
* @method array zrangebylex(string $key, string $start, string $stop, array $options = null)
* @method array zrevrangebylex(string $key, string $start, string $stop, array $options = null)
* @method int zremrangebylex(string $key, string $min, string $max)
* @method int zlexcount(string $key, string $min, string $max)
* @method int pexpiretime(string $key)
* @method int pfadd(string $key, array $elements)
* @method mixed pfmerge(string $destinationKey, array|string $sourceKeys)
* @method int pfcount(string[]|string $keyOrKeys, string ...$keys = null)
* @method mixed pubsub($subcommand, $argument)
* @method int publish($channel, $message)
* @method mixed discard()
* @method array|null exec()
* @method mixed multi()
* @method mixed unwatch()
* @method array waitaof(int $numLocal, int $numReplicas, int $timeout)
* @method mixed watch(string $key)
* @method mixed eval(string $script, int $numkeys, string ...$keyOrArg = null)
* @method mixed eval_ro(string $script, array $keys, ...$argument)
* @method mixed evalsha(string $script, int $numkeys, string ...$keyOrArg = null)
* @method mixed evalsha_ro(string $sha1, array $keys, ...$argument)
* @method mixed script($subcommand, $argument = null)
* @method Status shutdown(bool $noSave = null, bool $now = false, bool $force = false, bool $abort = false)
* @method mixed auth(string $password)
* @method string echo(string $message)
* @method mixed ping(string $message = null)
* @method mixed select(int $database)
* @method mixed bgrewriteaof()
* @method mixed bgsave()
* @method mixed client($subcommand, $argument = null)
* @method mixed config($subcommand, $argument = null)
* @method int dbsize()
* @method mixed flushall()
* @method mixed flushdb()
* @method array info($section = null)
* @method int lastsave()
* @method mixed save()
* @method mixed slaveof(string $host, int $port)
* @method mixed slowlog($subcommand, $argument = null)
* @method array time()
* @method array command()
* @method int geoadd(string $key, $longitude, $latitude, $member)
* @method array geohash(string $key, array $members)
* @method array geopos(string $key, array $members)
* @method string|null geodist(string $key, $member1, $member2, $unit = null)
* @method array georadius(string $key, $longitude, $latitude, $radius, $unit, array $options = null)
* @method array georadiusbymember(string $key, $member, $radius, $unit, array $options = null)
* @method array geosearch(string $key, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $withCoord = false, bool $withDist = false, bool $withHash = false)
* @method int geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* Container commands
* @property CLUSTER $cluster
* @property FunctionContainer $function
* @property FTCONFIG $ftconfig
* @property FTCURSOR $ftcursor
* @property JSONDEBUG $jsondebug
* @property ACL $acl
*/
interface ClientInterface
{
/**
* Returns the server profile used by the client.
* Returns the command factory used by the client.
*
* @return ProfileInterface
* @return FactoryInterface
*/
public function getProfile();
public function getCommandFactory();
/**
* Returns the client options specified upon initialization.
@ -206,7 +407,7 @@ interface ClientInterface
*
* @return CommandInterface
*/
public function createCommand($method, $arguments = array());
public function createCommand($method, $arguments = []);
/**
* Executes the specified Redis command.

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -11,21 +12,17 @@
namespace Predis\Cluster;
use InvalidArgumentException;
use Predis\Command\CommandInterface;
use Predis\Command\ScriptCommand;
/**
* Common class implementing the logic needed to support clustering strategies.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
abstract class ClusterStrategy implements StrategyInterface
{
protected $commands;
/**
*
*/
public function __construct()
{
$this->commands = $this->getDefaultCommands();
@ -38,12 +35,12 @@ abstract class ClusterStrategy implements StrategyInterface
*/
protected function getDefaultCommands()
{
$getKeyFromFirstArgument = array($this, 'getKeyFromFirstArgument');
$getKeyFromAllArguments = array($this, 'getKeyFromAllArguments');
$getKeyFromFirstArgument = [$this, 'getKeyFromFirstArgument'];
$getKeyFromAllArguments = [$this, 'getKeyFromAllArguments'];
return array(
return [
/* commands operating on the key space */
'EXISTS' => $getKeyFromFirstArgument,
'EXISTS' => $getKeyFromAllArguments,
'DEL' => $getKeyFromAllArguments,
'TYPE' => $getKeyFromFirstArgument,
'EXPIRE' => $getKeyFromFirstArgument,
@ -53,9 +50,10 @@ abstract class ClusterStrategy implements StrategyInterface
'PEXPIREAT' => $getKeyFromFirstArgument,
'TTL' => $getKeyFromFirstArgument,
'PTTL' => $getKeyFromFirstArgument,
'SORT' => $getKeyFromFirstArgument, // TODO
'SORT' => [$this, 'getKeyFromSortCommand'],
'DUMP' => $getKeyFromFirstArgument,
'RESTORE' => $getKeyFromFirstArgument,
'FLUSHDB' => [$this, 'getFakeKey'],
/* commands operating on string values */
'APPEND' => $getKeyFromFirstArgument,
@ -72,14 +70,15 @@ abstract class ClusterStrategy implements StrategyInterface
'INCRBYFLOAT' => $getKeyFromFirstArgument,
'SETBIT' => $getKeyFromFirstArgument,
'SETEX' => $getKeyFromFirstArgument,
'MSET' => array($this, 'getKeyFromInterleavedArguments'),
'MSETNX' => array($this, 'getKeyFromInterleavedArguments'),
'MSET' => [$this, 'getKeyFromInterleavedArguments'],
'MSETNX' => [$this, 'getKeyFromInterleavedArguments'],
'SETNX' => $getKeyFromFirstArgument,
'SETRANGE' => $getKeyFromFirstArgument,
'STRLEN' => $getKeyFromFirstArgument,
'SUBSTR' => $getKeyFromFirstArgument,
'BITOP' => array($this, 'getKeyFromBitOp'),
'BITOP' => [$this, 'getKeyFromBitOp'],
'BITCOUNT' => $getKeyFromFirstArgument,
'BITFIELD' => $getKeyFromFirstArgument,
/* commands operating on lists */
'LINSERT' => $getKeyFromFirstArgument,
@ -88,9 +87,9 @@ abstract class ClusterStrategy implements StrategyInterface
'LPOP' => $getKeyFromFirstArgument,
'RPOP' => $getKeyFromFirstArgument,
'RPOPLPUSH' => $getKeyFromAllArguments,
'BLPOP' => array($this, 'getKeyFromBlockingListCommands'),
'BRPOP' => array($this, 'getKeyFromBlockingListCommands'),
'BRPOPLPUSH' => array($this, 'getKeyFromBlockingListCommands'),
'BLPOP' => [$this, 'getKeyFromBlockingListCommands'],
'BRPOP' => [$this, 'getKeyFromBlockingListCommands'],
'BRPOPLPUSH' => [$this, 'getKeyFromBlockingListCommands'],
'LPUSH' => $getKeyFromFirstArgument,
'LPUSHX' => $getKeyFromFirstArgument,
'RPUSH' => $getKeyFromFirstArgument,
@ -121,7 +120,7 @@ abstract class ClusterStrategy implements StrategyInterface
'ZCARD' => $getKeyFromFirstArgument,
'ZCOUNT' => $getKeyFromFirstArgument,
'ZINCRBY' => $getKeyFromFirstArgument,
'ZINTERSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZINTERSTORE' => [$this, 'getKeyFromZsetAggregationCommands'],
'ZRANGE' => $getKeyFromFirstArgument,
'ZRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZRANK' => $getKeyFromFirstArgument,
@ -132,7 +131,7 @@ abstract class ClusterStrategy implements StrategyInterface
'ZREVRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZREVRANK' => $getKeyFromFirstArgument,
'ZSCORE' => $getKeyFromFirstArgument,
'ZUNIONSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZUNIONSTORE' => [$this, 'getKeyFromZsetAggregationCommands'],
'ZSCAN' => $getKeyFromFirstArgument,
'ZLEXCOUNT' => $getKeyFromFirstArgument,
'ZRANGEBYLEX' => $getKeyFromFirstArgument,
@ -162,9 +161,23 @@ abstract class ClusterStrategy implements StrategyInterface
'PFMERGE' => $getKeyFromAllArguments,
/* scripting */
'EVAL' => array($this, 'getKeyFromScriptingCommands'),
'EVALSHA' => array($this, 'getKeyFromScriptingCommands'),
);
'EVAL' => [$this, 'getKeyFromScriptingCommands'],
'EVALSHA' => [$this, 'getKeyFromScriptingCommands'],
/* server */
'INFO' => [$this, 'getFakeKey'],
/* commands performing geospatial operations */
'GEOADD' => $getKeyFromFirstArgument,
'GEOHASH' => $getKeyFromFirstArgument,
'GEOPOS' => $getKeyFromFirstArgument,
'GEODIST' => $getKeyFromFirstArgument,
'GEORADIUS' => [$this, 'getKeyFromGeoradiusCommands'],
'GEORADIUSBYMEMBER' => [$this, 'getKeyFromGeoradiusCommands'],
/* cluster */
'CLUSTER' => [$this, 'getFakeKey'],
];
}
/**
@ -189,7 +202,7 @@ abstract class ClusterStrategy implements StrategyInterface
* @param string $commandID Command ID.
* @param mixed $callback A valid callable object, or NULL to unset the handler.
*
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public function setCommandHandler($commandID, $callback = null)
{
@ -202,7 +215,7 @@ abstract class ClusterStrategy implements StrategyInterface
}
if (!is_callable($callback)) {
throw new \InvalidArgumentException(
throw new InvalidArgumentException(
'The argument must be a callable object or NULL.'
);
}
@ -210,6 +223,16 @@ abstract class ClusterStrategy implements StrategyInterface
$this->commands[$commandID] = $callback;
}
/**
* Get fake key for commands with no key argument.
*
* @return string
*/
protected function getFakeKey(): string
{
return 'key';
}
/**
* Extracts the key from the first argument of a command instance.
*
@ -234,9 +257,11 @@ abstract class ClusterStrategy implements StrategyInterface
{
$arguments = $command->getArguments();
if ($this->checkSameSlotForKeys($arguments)) {
return $arguments[0];
if (!$this->checkSameSlotForKeys($arguments)) {
return null;
}
return $arguments[0];
}
/**
@ -250,15 +275,48 @@ abstract class ClusterStrategy implements StrategyInterface
protected function getKeyFromInterleavedArguments(CommandInterface $command)
{
$arguments = $command->getArguments();
$keys = array();
$keys = [];
for ($i = 0; $i < count($arguments); $i += 2) {
$keys[] = $arguments[$i];
}
if ($this->checkSameSlotForKeys($keys)) {
return $arguments[0];
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
return $arguments[0];
}
/**
* Extracts the key from SORT command.
*
* @param CommandInterface $command Command instance.
*
* @return string|null
*/
protected function getKeyFromSortCommand(CommandInterface $command)
{
$arguments = $command->getArguments();
$firstKey = $arguments[0];
if (1 === $argc = count($arguments)) {
return $firstKey;
}
$keys = [$firstKey];
for ($i = 1; $i < $argc; ++$i) {
if (strtoupper($arguments[$i]) === 'STORE') {
$keys[] = $arguments[++$i];
}
}
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
return $firstKey;
}
/**
@ -272,9 +330,11 @@ abstract class ClusterStrategy implements StrategyInterface
{
$arguments = $command->getArguments();
if ($this->checkSameSlotForKeys(array_slice($arguments, 0, count($arguments) - 1))) {
return $arguments[0];
if (!$this->checkSameSlotForKeys(array_slice($arguments, 0, count($arguments) - 1))) {
return null;
}
return $arguments[0];
}
/**
@ -288,9 +348,42 @@ abstract class ClusterStrategy implements StrategyInterface
{
$arguments = $command->getArguments();
if ($this->checkSameSlotForKeys(array_slice($arguments, 1, count($arguments)))) {
return $arguments[1];
if (!$this->checkSameSlotForKeys(array_slice($arguments, 1, count($arguments)))) {
return null;
}
return $arguments[1];
}
/**
* Extracts the key from GEORADIUS and GEORADIUSBYMEMBER commands.
*
* @param CommandInterface $command Command instance.
*
* @return string|null
*/
protected function getKeyFromGeoradiusCommands(CommandInterface $command)
{
$arguments = $command->getArguments();
$argc = count($arguments);
$startIndex = $command->getId() === 'GEORADIUS' ? 5 : 4;
if ($argc > $startIndex) {
$keys = [$arguments[0]];
for ($i = $startIndex; $i < $argc; ++$i) {
$argument = strtoupper($arguments[$i]);
if ($argument === 'STORE' || $argument === 'STOREDIST') {
$keys[] = $arguments[++$i];
}
}
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
}
return $arguments[0];
}
/**
@ -303,11 +396,13 @@ abstract class ClusterStrategy implements StrategyInterface
protected function getKeyFromZsetAggregationCommands(CommandInterface $command)
{
$arguments = $command->getArguments();
$keys = array_merge(array($arguments[0]), array_slice($arguments, 2, $arguments[1]));
$keys = array_merge([$arguments[0]], array_slice($arguments, 2, $arguments[1]));
if ($this->checkSameSlotForKeys($keys)) {
return $arguments[0];
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
return $arguments[0];
}
/**
@ -319,15 +414,15 @@ abstract class ClusterStrategy implements StrategyInterface
*/
protected function getKeyFromScriptingCommands(CommandInterface $command)
{
if ($command instanceof ScriptCommand) {
$keys = $command->getKeys();
} else {
$keys = array_slice($args = $command->getArguments(), 2, $args[1]);
$keys = $command instanceof ScriptCommand
? $command->getKeys()
: array_slice($args = $command->getArguments(), 2, $args[1]);
if (!$keys || !$this->checkSameSlotForKeys($keys)) {
return null;
}
if ($keys && $this->checkSameSlotForKeys($keys)) {
return $keys[0];
}
return $keys[0];
}
/**

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -16,8 +17,6 @@ use Predis\Cluster\Hash\HashGeneratorInterface;
/**
* A distributor implements the logic to automatically distribute keys among
* several nodes for client-side sharding.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface DistributorInterface
{

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -11,11 +12,11 @@
namespace Predis\Cluster\Distributor;
use Exception;
/**
* Exception class that identifies empty rings.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class EmptyRingException extends \Exception
class EmptyRingException extends Exception
{
}

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -17,21 +18,19 @@ use Predis\Cluster\Hash\HashGeneratorInterface;
* This class implements an hashring-based distributor that uses the same
* algorithm of memcache to distribute keys in a cluster using client-side
* sharding.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @author Lorenzo Castelli <lcastelli@gmail.com>
*/
class HashRing implements DistributorInterface, HashGeneratorInterface
{
const DEFAULT_REPLICAS = 128;
const DEFAULT_WEIGHT = 100;
public const DEFAULT_REPLICAS = 128;
public const DEFAULT_WEIGHT = 100;
private $ring;
private $ringKeys;
private $ringKeysCount;
private $replicas;
private $nodeHashCallback;
private $nodes = array();
private $nodes = [];
/**
* @param int $replicas Number of replicas in the ring.
@ -53,10 +52,10 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
{
// In case of collisions in the hashes of the nodes, the node added
// last wins, thus the order in which nodes are added is significant.
$this->nodes[] = array(
$this->nodes[] = [
'object' => $node,
'weight' => (int) $weight ?: $this::DEFAULT_WEIGHT,
);
];
$this->reset();
}
@ -131,7 +130,7 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
throw new EmptyRingException('Cannot initialize an empty hashring.');
}
$this->ring = array();
$this->ring = [];
$totalWeight = $this->computeTotalWeight();
$nodesCount = count($this->nodes);
@ -161,7 +160,7 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
$replicas = (int) round($weightRatio * $totalNodes * $replicas);
for ($i = 0; $i < $replicas; ++$i) {
$key = crc32("$nodeHash:$i");
$key = $this->hash("$nodeHash:$i");
$ring[$key] = $nodeObject;
}
}
@ -239,9 +238,8 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
public function get($value)
{
$hash = $this->hash($value);
$node = $this->getByHash($hash);
return $node;
return $this->getByHash($hash);
}
/**

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -15,13 +16,11 @@ namespace Predis\Cluster\Distributor;
* This class implements an hashring-based distributor that uses the same
* algorithm of libketama to distribute keys in a cluster using client-side
* sharding.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @author Lorenzo Castelli <lcastelli@gmail.com>
*/
class KetamaRing extends HashRing
{
const DEFAULT_REPLICAS = 160;
public const DEFAULT_REPLICAS = 160;
/**
* @param mixed $nodeHashCallback Callback returning a string used to calculate the hash of nodes.

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -13,12 +14,10 @@ namespace Predis\Cluster\Hash;
/**
* Hash generator implementing the CRC-CCITT-16 algorithm used by redis-cluster.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class CRC16 implements HashGeneratorInterface
{
private static $CCITT_16 = array(
private static $CCITT_16 = [
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
@ -51,7 +50,7 @@ class CRC16 implements HashGeneratorInterface
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0,
);
];
/**
* {@inheritdoc}
@ -61,6 +60,8 @@ class CRC16 implements HashGeneratorInterface
// CRC-CCITT-16 algorithm
$crc = 0;
$CCITT_16 = self::$CCITT_16;
$value = (string) $value;
$strlen = strlen($value);
for ($i = 0; $i < $strlen; ++$i) {

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -14,8 +15,6 @@ namespace Predis\Cluster\Hash;
/**
* An hash generator implements the logic used to calculate the hash of a key to
* distribute operations among Redis nodes.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface HashGeneratorInterface
{

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -16,8 +17,6 @@ use Predis\Cluster\Distributor\HashRing;
/**
* Default cluster strategy used by Predis to handle client-side sharding.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class PredisStrategy extends ClusterStrategy
{
@ -40,9 +39,8 @@ class PredisStrategy extends ClusterStrategy
{
$key = $this->extractKeyTag($key);
$hash = $this->distributor->hash($key);
$slot = $this->distributor->getSlot($hash);
return $slot;
return $this->distributor->getSlot($hash);
}
/**

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -18,8 +19,6 @@ use Predis\NotSupportedException;
/**
* Default class used by Predis to calculate hashes out of keys of
* commands supported by redis-cluster.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class RedisStrategy extends ClusterStrategy
{
@ -41,9 +40,8 @@ class RedisStrategy extends ClusterStrategy
public function getSlotByKey($key)
{
$key = $this->extractKeyTag($key);
$slot = $this->hashGenerator->hash($key) & 0x3FFF;
return $slot;
return $this->hashGenerator->hash($key) & 0x3FFF;
}
/**
@ -51,8 +49,7 @@ class RedisStrategy extends ClusterStrategy
*/
public function getDistributor()
{
throw new NotSupportedException(
'This cluster strategy does not provide an external distributor'
);
$class = get_class($this);
throw new NotSupportedException("$class does not provide an external distributor");
}
}

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -19,8 +20,6 @@ use Predis\Command\CommandInterface;
* keys extracted from supported commands.
*
* This is mostly useful to support clustering via client-side sharding.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface StrategyInterface
{
@ -30,7 +29,7 @@ interface StrategyInterface
*
* @param CommandInterface $command Command instance.
*
* @return int
* @return int|null
*/
public function getSlot(CommandInterface $command);
@ -40,7 +39,7 @@ interface StrategyInterface
*
* @param string $key Key string.
*
* @return int
* @return int|null
*/
public function getSlotByKey($key);

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -11,8 +12,10 @@
namespace Predis\Collection\Iterator;
use Iterator;
use Predis\ClientInterface;
use Predis\NotSupportedException;
use ReturnTypeWillChange;
/**
* Provides the base implementation for a fully-rewindable PHP iterator that can
@ -24,10 +27,8 @@ use Predis\NotSupportedException;
* can change several times during the iteration process.
*
* @see http://redis.io/commands/scan
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
abstract class CursorBasedIterator implements \Iterator
abstract class CursorBasedIterator implements Iterator
{
protected $client;
protected $match;
@ -65,8 +66,8 @@ abstract class CursorBasedIterator implements \Iterator
*/
protected function requiredCommand(ClientInterface $client, $commandID)
{
if (!$client->getProfile()->supportsCommand($commandID)) {
throw new NotSupportedException("The current profile does not support '$commandID'.");
if (!$client->getCommandFactory()->supports($commandID)) {
throw new NotSupportedException("'$commandID' is not supported by the current command factory.");
}
}
@ -77,7 +78,7 @@ abstract class CursorBasedIterator implements \Iterator
{
$this->valid = true;
$this->fetchmore = true;
$this->elements = array();
$this->elements = [];
$this->cursor = 0;
$this->position = -1;
$this->current = null;
@ -90,9 +91,9 @@ abstract class CursorBasedIterator implements \Iterator
*/
protected function getScanOptions()
{
$options = array();
$options = [];
if (strlen($this->match) > 0) {
if (strlen(strval($this->match)) > 0) {
$options['MATCH'] = $this->match;
}
@ -117,7 +118,7 @@ abstract class CursorBasedIterator implements \Iterator
*/
protected function fetch()
{
list($cursor, $elements) = $this->executeCommand();
[$cursor, $elements] = $this->executeCommand();
if (!$cursor) {
$this->fetchmore = false;
@ -137,8 +138,9 @@ abstract class CursorBasedIterator implements \Iterator
}
/**
* {@inheritdoc}
* @return void
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->reset();
@ -146,27 +148,30 @@ abstract class CursorBasedIterator implements \Iterator
}
/**
* {@inheritdoc}
* @return mixed
*/
#[ReturnTypeWillChange]
public function current()
{
return $this->current;
}
/**
* {@inheritdoc}
* @return int|null
*/
#[ReturnTypeWillChange]
public function key()
{
return $this->position;
}
/**
* {@inheritdoc}
* @return void
*/
#[ReturnTypeWillChange]
public function next()
{
tryFetch: {
tryFetch:
if (!$this->elements && $this->fetchmore) {
$this->fetch();
}
@ -178,12 +183,12 @@ abstract class CursorBasedIterator implements \Iterator
} else {
$this->valid = false;
}
}
}
/**
* {@inheritdoc}
* @return bool
*/
#[ReturnTypeWillChange]
public function valid()
{
return $this->valid;

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -17,9 +18,7 @@ use Predis\ClientInterface;
* Abstracts the iteration of fields and values of an hash by leveraging the
* HSCAN command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/scan
* @see http://redis.io/commands/scan
*/
class HashKey extends CursorBasedIterator
{
@ -51,6 +50,8 @@ class HashKey extends CursorBasedIterator
protected function extractNext()
{
$this->position = key($this->elements);
$this->current = array_shift($this->elements);
$this->current = current($this->elements);
unset($this->elements[$this->position]);
}
}

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -17,9 +18,7 @@ use Predis\ClientInterface;
* Abstracts the iteration of the keyspace on a Redis instance by leveraging the
* SCAN command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/scan
* @see http://redis.io/commands/scan
*/
class Keyspace extends CursorBasedIterator
{

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -11,8 +12,11 @@
namespace Predis\Collection\Iterator;
use InvalidArgumentException;
use Iterator;
use Predis\ClientInterface;
use Predis\NotSupportedException;
use ReturnTypeWillChange;
/**
* Abstracts the iteration of items stored in a list by leveraging the LRANGE
@ -24,11 +28,9 @@ use Predis\NotSupportedException;
* guarantees on the returned elements because the collection can change several
* times (trimmed, deleted, overwritten) during the iteration process.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/lrange
* @see http://redis.io/commands/lrange
*/
class ListKey implements \Iterator
class ListKey implements Iterator
{
protected $client;
protected $count;
@ -45,14 +47,14 @@ class ListKey implements \Iterator
* @param string $key Redis list key.
* @param int $count Number of items retrieved on each fetch operation.
*
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public function __construct(ClientInterface $client, $key, $count = 10)
{
$this->requiredCommand($client, 'LRANGE');
if ((false === $count = filter_var($count, FILTER_VALIDATE_INT)) || $count < 0) {
throw new \InvalidArgumentException('The $count argument must be a positive integer.');
throw new InvalidArgumentException('The $count argument must be a positive integer.');
}
$this->client = $client;
@ -73,8 +75,8 @@ class ListKey implements \Iterator
*/
protected function requiredCommand(ClientInterface $client, $commandID)
{
if (!$client->getProfile()->supportsCommand($commandID)) {
throw new NotSupportedException("The current profile does not support '$commandID'.");
if (!$client->getCommandFactory()->supports($commandID)) {
throw new NotSupportedException("'$commandID' is not supported by the current command factory.");
}
}
@ -85,7 +87,7 @@ class ListKey implements \Iterator
{
$this->valid = true;
$this->fetchmore = true;
$this->elements = array();
$this->elements = [];
$this->position = -1;
$this->current = null;
}
@ -126,8 +128,9 @@ class ListKey implements \Iterator
}
/**
* {@inheritdoc}
* @return void
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->reset();
@ -135,24 +138,27 @@ class ListKey implements \Iterator
}
/**
* {@inheritdoc}
* @return mixed
*/
#[ReturnTypeWillChange]
public function current()
{
return $this->current;
}
/**
* {@inheritdoc}
* @return int|null
*/
#[ReturnTypeWillChange]
public function key()
{
return $this->position;
}
/**
* {@inheritdoc}
* @return void
*/
#[ReturnTypeWillChange]
public function next()
{
if (!$this->elements && $this->fetchmore) {
@ -167,8 +173,9 @@ class ListKey implements \Iterator
}
/**
* {@inheritdoc}
* @return bool
*/
#[ReturnTypeWillChange]
public function valid()
{
return $this->valid;

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -17,9 +18,7 @@ use Predis\ClientInterface;
* Abstracts the iteration of members stored in a set by leveraging the SSCAN
* command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/scan
* @see http://redis.io/commands/scan
*/
class SetKey extends CursorBasedIterator
{

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -17,9 +18,7 @@ use Predis\ClientInterface;
* Abstracts the iteration of members stored in a sorted set by leveraging the
* ZSCAN command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/scan
* @see http://redis.io/commands/scan
*/
class SortedSetKey extends CursorBasedIterator
{
@ -50,11 +49,9 @@ class SortedSetKey extends CursorBasedIterator
*/
protected function extractNext()
{
if ($kv = each($this->elements)) {
$this->position = $kv[0];
$this->current = $kv[1];
$this->position = key($this->elements);
$this->current = current($this->elements);
unset($this->elements[$this->position]);
}
unset($this->elements[$this->position]);
}
}

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -13,32 +14,18 @@ namespace Predis\Command;
/**
* Base class for Redis commands.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
abstract class Command implements CommandInterface
{
private $slot;
private $arguments = array();
/**
* Returns a filtered array of the arguments.
*
* @param array $arguments List of arguments.
*
* @return array
*/
protected function filterArguments(array $arguments)
{
return $arguments;
}
private $arguments = [];
/**
* {@inheritdoc}
*/
public function setArguments(array $arguments)
{
$this->arguments = $this->filterArguments($arguments);
$this->arguments = $arguments;
unset($this->slot);
}
@ -82,9 +69,7 @@ abstract class Command implements CommandInterface
*/
public function getSlot()
{
if (isset($this->slot)) {
return $this->slot;
}
return $this->slot ?? null;
}
/**
@ -104,7 +89,7 @@ abstract class Command implements CommandInterface
*/
public static function normalizeArguments(array $arguments)
{
if (count($arguments) === 1 && is_array($arguments[0])) {
if (count($arguments) === 1 && isset($arguments[0]) && is_array($arguments[0])) {
return $arguments[0];
}
@ -121,9 +106,21 @@ abstract class Command implements CommandInterface
public static function normalizeVariadic(array $arguments)
{
if (count($arguments) === 2 && is_array($arguments[1])) {
return array_merge(array($arguments[0]), $arguments[1]);
return array_merge([$arguments[0]], $arguments[1]);
}
return $arguments;
}
/**
* Remove all false values from arguments.
*
* @return void
*/
public function filterArguments(): void
{
$this->arguments = array_filter($this->arguments, static function ($argument) {
return $argument !== false && $argument !== null;
});
}
}

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -13,8 +14,6 @@ namespace Predis\Command;
/**
* Defines an abstraction representing a Redis command.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface CommandInterface
{
@ -73,7 +72,7 @@ interface CommandInterface
/**
* Parses a raw response and returns a PHP object.
*
* @param string $data Binary string containing the whole response.
* @param string|array|null $data Binary string containing the whole response.
*
* @return mixed
*/

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/auth
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ConnectionAuth extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'AUTH';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/echo
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ConnectionEcho extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'ECHO';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/ping
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ConnectionPing extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PING';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/quit
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ConnectionQuit extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'QUIT';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/select
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ConnectionSelect extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'SELECT';
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hdel
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashDelete extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HDEL';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
return self::normalizeVariadic($arguments);
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hexists
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashExists extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HEXISTS';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return (bool) $data;
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hget
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashGet extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HGET';
}
}

View file

@ -1,42 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hgetall
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashGetAll extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HGETALL';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
$result = array();
for ($i = 0; $i < count($data); ++$i) {
$result[$data[$i]] = $data[++$i];
}
return $result;
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hmget
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashGetMultiple extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HMGET';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
return self::normalizeVariadic($arguments);
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hincrby
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashIncrementBy extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HINCRBY';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hincrbyfloat
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashIncrementByFloat extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HINCRBYFLOAT';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hkeys
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashKeys extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HKEYS';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hlen
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashLength extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HLEN';
}
}

View file

@ -1,85 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hscan
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashScan extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HSCAN';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
if (count($arguments) === 3 && is_array($arguments[2])) {
$options = $this->prepareOptions(array_pop($arguments));
$arguments = array_merge($arguments, $options);
}
return $arguments;
}
/**
* Returns a list of options and modifiers compatible with Redis.
*
* @param array $options List of options.
*
* @return array
*/
protected function prepareOptions($options)
{
$options = array_change_key_case($options, CASE_UPPER);
$normalized = array();
if (!empty($options['MATCH'])) {
$normalized[] = 'MATCH';
$normalized[] = $options['MATCH'];
}
if (!empty($options['COUNT'])) {
$normalized[] = 'COUNT';
$normalized[] = $options['COUNT'];
}
return $normalized;
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
if (is_array($data)) {
$fields = $data[1];
$result = array();
for ($i = 0; $i < count($fields); ++$i) {
$result[$fields[$i]] = $fields[++$i];
}
$data[1] = $result;
}
return $data;
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hset
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashSet extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HSET';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return (bool) $data;
}
}

View file

@ -1,48 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hmset
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashSetMultiple extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HMSET';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
if (count($arguments) === 2 && is_array($arguments[1])) {
$flattenedKVs = array($arguments[0]);
$args = $arguments[1];
foreach ($args as $k => $v) {
$flattenedKVs[] = $k;
$flattenedKVs[] = $v;
}
return $flattenedKVs;
}
return $arguments;
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hsetnx
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashSetPreserve extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HSETNX';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return (bool) $data;
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hstrlen
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashStringLength extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HSTRLEN';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/hvals
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashValues extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HVALS';
}
}

View file

@ -1,44 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/pfadd
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HyperLogLogAdd extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PFADD';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
return self::normalizeVariadic($arguments);
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return (bool) $data;
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/pfcount
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HyperLogLogCount extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PFCOUNT';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
return self::normalizeArguments($arguments);
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/pfmerge
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HyperLogLogMerge extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PFMERGE';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
return self::normalizeArguments($arguments);
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/del
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyDelete extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'DEL';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
return self::normalizeArguments($arguments);
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/dump
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyDump extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'DUMP';
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/exists
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyExists extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'EXISTS';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return (bool) $data;
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/expire
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyExpire extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'EXPIRE';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return (bool) $data;
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/expireat
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyExpireAt extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'EXPIREAT';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return (bool) $data;
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/keys
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyKeys extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'KEYS';
}
}

View file

@ -1,50 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/migrate
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyMigrate extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'MIGRATE';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
if (is_array(end($arguments))) {
foreach (array_pop($arguments) as $modifier => $value) {
$modifier = strtoupper($modifier);
if ($modifier === 'COPY' && $value == true) {
$arguments[] = $modifier;
}
if ($modifier === 'REPLACE' && $value == true) {
$arguments[] = $modifier;
}
}
}
return $arguments;
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/move
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyMove extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'MOVE';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return (bool) $data;
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/persist
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyPersist extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PERSIST';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return (bool) $data;
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/pexpire
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyPreciseExpire extends KeyExpire
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PEXPIRE';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/pexpireat
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyPreciseExpireAt extends KeyExpireAt
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PEXPIREAT';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/pttl
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyPreciseTimeToLive extends KeyTimeToLive
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PTTL';
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/randomkey
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyRandom extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'RANDOMKEY';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return $data !== '' ? $data : null;
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/rename
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyRename extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'RENAME';
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/renamenx
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyRenamePreserve extends KeyRename
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'RENAMENX';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return (bool) $data;
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/restore
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyRestore extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'RESTORE';
}
}

View file

@ -1,66 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/scan
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyScan extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'SCAN';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
if (count($arguments) === 2 && is_array($arguments[1])) {
$options = $this->prepareOptions(array_pop($arguments));
$arguments = array_merge($arguments, $options);
}
return $arguments;
}
/**
* Returns a list of options and modifiers compatible with Redis.
*
* @param array $options List of options.
*
* @return array
*/
protected function prepareOptions($options)
{
$options = array_change_key_case($options, CASE_UPPER);
$normalized = array();
if (!empty($options['MATCH'])) {
$normalized[] = 'MATCH';
$normalized[] = $options['MATCH'];
}
if (!empty($options['COUNT'])) {
$normalized[] = 'COUNT';
$normalized[] = $options['COUNT'];
}
return $normalized;
}
}

View file

@ -1,83 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/sort
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeySort extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'SORT';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
if (count($arguments) === 1) {
return $arguments;
}
$query = array($arguments[0]);
$sortParams = array_change_key_case($arguments[1], CASE_UPPER);
if (isset($sortParams['BY'])) {
$query[] = 'BY';
$query[] = $sortParams['BY'];
}
if (isset($sortParams['GET'])) {
$getargs = $sortParams['GET'];
if (is_array($getargs)) {
foreach ($getargs as $getarg) {
$query[] = 'GET';
$query[] = $getarg;
}
} else {
$query[] = 'GET';
$query[] = $getargs;
}
}
if (isset($sortParams['LIMIT']) &&
is_array($sortParams['LIMIT']) &&
count($sortParams['LIMIT']) == 2) {
$query[] = 'LIMIT';
$query[] = $sortParams['LIMIT'][0];
$query[] = $sortParams['LIMIT'][1];
}
if (isset($sortParams['SORT'])) {
$query[] = strtoupper($sortParams['SORT']);
}
if (isset($sortParams['ALPHA']) && $sortParams['ALPHA'] == true) {
$query[] = 'ALPHA';
}
if (isset($sortParams['STORE'])) {
$query[] = 'STORE';
$query[] = $sortParams['STORE'];
}
return $query;
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/ttl
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyTimeToLive extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'TTL';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/type
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyType extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'TYPE';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/lindex
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListIndex extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'LINDEX';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/linsert
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListInsert extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'LINSERT';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/llen
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListLength extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'LLEN';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/lpop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopFirst extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'LPOP';
}
}

View file

@ -1,41 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/blpop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopFirstBlocking extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'BLPOP';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
if (count($arguments) === 2 && is_array($arguments[0])) {
list($arguments, $timeout) = $arguments;
array_push($arguments, $timeout);
}
return $arguments;
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/rpop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopLast extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'RPOP';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/brpop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopLastBlocking extends ListPopFirstBlocking
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'BRPOP';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/rpoplpush
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopLastPushHead extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'RPOPLPUSH';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/brpoplpush
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopLastPushHeadBlocking extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'BRPOPLPUSH';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/lpush
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPushHead extends ListPushTail
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'LPUSH';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/lpushx
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPushHeadX extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'LPUSHX';
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/rpush
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPushTail extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'RPUSH';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
return self::normalizeVariadic($arguments);
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/rpushx
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPushTailX extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'RPUSHX';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/lrange
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListRange extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'LRANGE';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/lrem
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListRemove extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'LREM';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/lset
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListSet extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'LSET';
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/ltrim
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListTrim extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'LTRIM';
}
}

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -13,8 +14,6 @@ namespace Predis\Command;
/**
* Defines a command whose keys can be prefixed.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface PrefixableCommandInterface extends CommandInterface
{

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -11,14 +12,13 @@
namespace Predis\Command\Processor;
use InvalidArgumentException;
use Predis\Command\CommandInterface;
use Predis\Command\PrefixableCommandInterface;
/**
* Command processor capable of prefixing keys stored in the arguments of Redis
* commands supported.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyPrefixProcessor implements ProcessorInterface
{
@ -31,135 +31,270 @@ class KeyPrefixProcessor implements ProcessorInterface
public function __construct($prefix)
{
$this->prefix = $prefix;
$this->commands = array(
$prefixFirst = static::class . '::first';
$prefixAll = static::class . '::all';
$prefixInterleaved = static::class . '::interleaved';
$prefixSkipFirst = static::class . '::skipFirst';
$prefixSkipLast = static::class . '::skipLast';
$prefixSort = static::class . '::sort';
$prefixEvalKeys = static::class . '::evalKeys';
$prefixZsetStore = static::class . '::zsetStore';
$prefixMigrate = static::class . '::migrate';
$prefixGeoradius = static::class . '::georadius';
$this->commands = [
/* ---------------- Redis 1.2 ---------------- */
'EXISTS' => 'static::first',
'DEL' => 'static::all',
'TYPE' => 'static::first',
'KEYS' => 'static::first',
'RENAME' => 'static::all',
'RENAMENX' => 'static::all',
'EXPIRE' => 'static::first',
'EXPIREAT' => 'static::first',
'TTL' => 'static::first',
'MOVE' => 'static::first',
'SORT' => 'static::sort',
'DUMP' => 'static::first',
'RESTORE' => 'static::first',
'SET' => 'static::first',
'SETNX' => 'static::first',
'MSET' => 'static::interleaved',
'MSETNX' => 'static::interleaved',
'GET' => 'static::first',
'MGET' => 'static::all',
'GETSET' => 'static::first',
'INCR' => 'static::first',
'INCRBY' => 'static::first',
'DECR' => 'static::first',
'DECRBY' => 'static::first',
'RPUSH' => 'static::first',
'LPUSH' => 'static::first',
'LLEN' => 'static::first',
'LRANGE' => 'static::first',
'LTRIM' => 'static::first',
'LINDEX' => 'static::first',
'LSET' => 'static::first',
'LREM' => 'static::first',
'LPOP' => 'static::first',
'RPOP' => 'static::first',
'RPOPLPUSH' => 'static::all',
'SADD' => 'static::first',
'SREM' => 'static::first',
'SPOP' => 'static::first',
'SMOVE' => 'static::skipLast',
'SCARD' => 'static::first',
'SISMEMBER' => 'static::first',
'SINTER' => 'static::all',
'SINTERSTORE' => 'static::all',
'SUNION' => 'static::all',
'SUNIONSTORE' => 'static::all',
'SDIFF' => 'static::all',
'SDIFFSTORE' => 'static::all',
'SMEMBERS' => 'static::first',
'SRANDMEMBER' => 'static::first',
'ZADD' => 'static::first',
'ZINCRBY' => 'static::first',
'ZREM' => 'static::first',
'ZRANGE' => 'static::first',
'ZREVRANGE' => 'static::first',
'ZRANGEBYSCORE' => 'static::first',
'ZCARD' => 'static::first',
'ZSCORE' => 'static::first',
'ZREMRANGEBYSCORE' => 'static::first',
'EXISTS' => $prefixAll,
'DEL' => $prefixAll,
'TYPE' => $prefixFirst,
'KEYS' => $prefixFirst,
'RENAME' => $prefixAll,
'RENAMENX' => $prefixAll,
'EXPIRE' => $prefixFirst,
'EXPIREAT' => $prefixFirst,
'TTL' => $prefixFirst,
'MOVE' => $prefixFirst,
'SORT' => $prefixSort,
'DUMP' => $prefixFirst,
'RESTORE' => $prefixFirst,
'SET' => $prefixFirst,
'SETNX' => $prefixFirst,
'MSET' => $prefixInterleaved,
'MSETNX' => $prefixInterleaved,
'GET' => $prefixFirst,
'MGET' => $prefixAll,
'GETSET' => $prefixFirst,
'INCR' => $prefixFirst,
'INCRBY' => $prefixFirst,
'DECR' => $prefixFirst,
'DECRBY' => $prefixFirst,
'RPUSH' => $prefixFirst,
'LPUSH' => $prefixFirst,
'LLEN' => $prefixFirst,
'LRANGE' => $prefixFirst,
'LTRIM' => $prefixFirst,
'LINDEX' => $prefixFirst,
'LSET' => $prefixFirst,
'LREM' => $prefixFirst,
'LPOP' => $prefixFirst,
'RPOP' => $prefixFirst,
'RPOPLPUSH' => $prefixAll,
'SADD' => $prefixFirst,
'SREM' => $prefixFirst,
'SPOP' => $prefixFirst,
'SMOVE' => $prefixSkipLast,
'SCARD' => $prefixFirst,
'SISMEMBER' => $prefixFirst,
'SINTER' => $prefixAll,
'SINTERSTORE' => $prefixAll,
'SUNION' => $prefixAll,
'SUNIONSTORE' => $prefixAll,
'SDIFF' => $prefixAll,
'SDIFFSTORE' => $prefixAll,
'SMEMBERS' => $prefixFirst,
'SRANDMEMBER' => $prefixFirst,
'ZADD' => $prefixFirst,
'ZINCRBY' => $prefixFirst,
'ZREM' => $prefixFirst,
'ZRANGE' => $prefixFirst,
'ZREVRANGE' => $prefixFirst,
'ZRANGEBYSCORE' => $prefixFirst,
'ZCARD' => $prefixFirst,
'ZSCORE' => $prefixFirst,
'ZREMRANGEBYSCORE' => $prefixFirst,
/* ---------------- Redis 2.0 ---------------- */
'SETEX' => 'static::first',
'APPEND' => 'static::first',
'SUBSTR' => 'static::first',
'BLPOP' => 'static::skipLast',
'BRPOP' => 'static::skipLast',
'ZUNIONSTORE' => 'static::zsetStore',
'ZINTERSTORE' => 'static::zsetStore',
'ZCOUNT' => 'static::first',
'ZRANK' => 'static::first',
'ZREVRANK' => 'static::first',
'ZREMRANGEBYRANK' => 'static::first',
'HSET' => 'static::first',
'HSETNX' => 'static::first',
'HMSET' => 'static::first',
'HINCRBY' => 'static::first',
'HGET' => 'static::first',
'HMGET' => 'static::first',
'HDEL' => 'static::first',
'HEXISTS' => 'static::first',
'HLEN' => 'static::first',
'HKEYS' => 'static::first',
'HVALS' => 'static::first',
'HGETALL' => 'static::first',
'SUBSCRIBE' => 'static::all',
'UNSUBSCRIBE' => 'static::all',
'PSUBSCRIBE' => 'static::all',
'PUNSUBSCRIBE' => 'static::all',
'PUBLISH' => 'static::first',
'SETEX' => $prefixFirst,
'APPEND' => $prefixFirst,
'SUBSTR' => $prefixFirst,
'BLPOP' => $prefixSkipLast,
'BRPOP' => $prefixSkipLast,
'ZUNIONSTORE' => $prefixZsetStore,
'ZINTERSTORE' => $prefixZsetStore,
'ZCOUNT' => $prefixFirst,
'ZRANK' => $prefixFirst,
'ZREVRANK' => $prefixFirst,
'ZREMRANGEBYRANK' => $prefixFirst,
'HSET' => $prefixFirst,
'HSETNX' => $prefixFirst,
'HMSET' => $prefixFirst,
'HINCRBY' => $prefixFirst,
'HGET' => $prefixFirst,
'HMGET' => $prefixFirst,
'HDEL' => $prefixFirst,
'HEXISTS' => $prefixFirst,
'HLEN' => $prefixFirst,
'HKEYS' => $prefixFirst,
'HVALS' => $prefixFirst,
'HGETALL' => $prefixFirst,
'SUBSCRIBE' => $prefixAll,
'UNSUBSCRIBE' => $prefixAll,
'PSUBSCRIBE' => $prefixAll,
'PUNSUBSCRIBE' => $prefixAll,
'PUBLISH' => $prefixFirst,
/* ---------------- Redis 2.2 ---------------- */
'PERSIST' => 'static::first',
'STRLEN' => 'static::first',
'SETRANGE' => 'static::first',
'GETRANGE' => 'static::first',
'SETBIT' => 'static::first',
'GETBIT' => 'static::first',
'RPUSHX' => 'static::first',
'LPUSHX' => 'static::first',
'LINSERT' => 'static::first',
'BRPOPLPUSH' => 'static::skipLast',
'ZREVRANGEBYSCORE' => 'static::first',
'WATCH' => 'static::all',
'PERSIST' => $prefixFirst,
'STRLEN' => $prefixFirst,
'SETRANGE' => $prefixFirst,
'GETRANGE' => $prefixFirst,
'SETBIT' => $prefixFirst,
'GETBIT' => $prefixFirst,
'RPUSHX' => $prefixFirst,
'LPUSHX' => $prefixFirst,
'LINSERT' => $prefixFirst,
'BRPOPLPUSH' => $prefixSkipLast,
'ZREVRANGEBYSCORE' => $prefixFirst,
'WATCH' => $prefixAll,
/* ---------------- Redis 2.6 ---------------- */
'PTTL' => 'static::first',
'PEXPIRE' => 'static::first',
'PEXPIREAT' => 'static::first',
'PSETEX' => 'static::first',
'INCRBYFLOAT' => 'static::first',
'BITOP' => 'static::skipFirst',
'BITCOUNT' => 'static::first',
'HINCRBYFLOAT' => 'static::first',
'EVAL' => 'static::evalKeys',
'EVALSHA' => 'static::evalKeys',
'MIGRATE' => 'static::migrate',
'PTTL' => $prefixFirst,
'PEXPIRE' => $prefixFirst,
'PEXPIREAT' => $prefixFirst,
'PSETEX' => $prefixFirst,
'INCRBYFLOAT' => $prefixFirst,
'BITOP' => $prefixSkipFirst,
'BITCOUNT' => $prefixFirst,
'HINCRBYFLOAT' => $prefixFirst,
'EVAL' => $prefixEvalKeys,
'EVALSHA' => $prefixEvalKeys,
'MIGRATE' => $prefixMigrate,
/* ---------------- Redis 2.8 ---------------- */
'SSCAN' => 'static::first',
'ZSCAN' => 'static::first',
'HSCAN' => 'static::first',
'PFADD' => 'static::first',
'PFCOUNT' => 'static::all',
'PFMERGE' => 'static::all',
'ZLEXCOUNT' => 'static::first',
'ZRANGEBYLEX' => 'static::first',
'ZREMRANGEBYLEX' => 'static::first',
'ZREVRANGEBYLEX' => 'static::first',
'BITPOS' => 'static::first',
'SSCAN' => $prefixFirst,
'ZSCAN' => $prefixFirst,
'HSCAN' => $prefixFirst,
'PFADD' => $prefixFirst,
'PFCOUNT' => $prefixAll,
'PFMERGE' => $prefixAll,
'ZLEXCOUNT' => $prefixFirst,
'ZRANGEBYLEX' => $prefixFirst,
'ZREMRANGEBYLEX' => $prefixFirst,
'ZREVRANGEBYLEX' => $prefixFirst,
'BITPOS' => $prefixFirst,
/* ---------------- Redis 3.2 ---------------- */
'HSTRLEN' => 'static::first',
);
'HSTRLEN' => $prefixFirst,
'BITFIELD' => $prefixFirst,
'GEOADD' => $prefixFirst,
'GEOHASH' => $prefixFirst,
'GEOPOS' => $prefixFirst,
'GEODIST' => $prefixFirst,
'GEORADIUS' => $prefixGeoradius,
'GEORADIUSBYMEMBER' => $prefixGeoradius,
/* ---------------- Redis 5.0 ---------------- */
'XADD' => $prefixFirst,
'XRANGE' => $prefixFirst,
'XREVRANGE' => $prefixFirst,
'XDEL' => $prefixFirst,
'XLEN' => $prefixFirst,
'XACK' => $prefixFirst,
'XTRIM' => $prefixFirst,
/* ---------------- Redis 6.2 ---------------- */
'GETDEL' => $prefixFirst,
/* ---------------- Redis 7.0 ---------------- */
'EXPIRETIME' => $prefixFirst,
/* RedisJSON */
'JSON.ARRAPPEND' => $prefixFirst,
'JSON.ARRINDEX' => $prefixFirst,
'JSON.ARRINSERT' => $prefixFirst,
'JSON.ARRLEN' => $prefixFirst,
'JSON.ARRPOP' => $prefixFirst,
'JSON.ARRTRIM' => $prefixFirst,
'JSON.CLEAR' => $prefixFirst,
'JSON.DEBUG MEMORY' => $prefixFirst,
'JSON.DEL' => $prefixFirst,
'JSON.FORGET' => $prefixFirst,
'JSON.GET' => $prefixFirst,
'JSON.MGET' => $prefixAll,
'JSON.NUMINCRBY' => $prefixFirst,
'JSON.OBJKEYS' => $prefixFirst,
'JSON.OBJLEN' => $prefixFirst,
'JSON.RESP' => $prefixFirst,
'JSON.SET' => $prefixFirst,
'JSON.STRAPPEND' => $prefixFirst,
'JSON.STRLEN' => $prefixFirst,
'JSON.TOGGLE' => $prefixFirst,
'JSON.TYPE' => $prefixFirst,
/* RedisBloom */
'BF.ADD' => $prefixFirst,
'BF.EXISTS' => $prefixFirst,
'BF.INFO' => $prefixFirst,
'BF.INSERT' => $prefixFirst,
'BF.LOADCHUNK' => $prefixFirst,
'BF.MADD' => $prefixFirst,
'BF.MEXISTS' => $prefixFirst,
'BF.RESERVE' => $prefixFirst,
'BF.SCANDUMP' => $prefixFirst,
'CF.ADD' => $prefixFirst,
'CF.ADDNX' => $prefixFirst,
'CF.COUNT' => $prefixFirst,
'CF.DEL' => $prefixFirst,
'CF.EXISTS' => $prefixFirst,
'CF.INFO' => $prefixFirst,
'CF.INSERT' => $prefixFirst,
'CF.INSERTNX' => $prefixFirst,
'CF.LOADCHUNK' => $prefixFirst,
'CF.MEXISTS' => $prefixFirst,
'CF.RESERVE' => $prefixFirst,
'CF.SCANDUMP' => $prefixFirst,
'CMS.INCRBY' => $prefixFirst,
'CMS.INFO' => $prefixFirst,
'CMS.INITBYDIM' => $prefixFirst,
'CMS.INITBYPROB' => $prefixFirst,
'CMS.QUERY' => $prefixFirst,
'TDIGEST.ADD' => $prefixFirst,
'TDIGEST.BYRANK' => $prefixFirst,
'TDIGEST.BYREVRANK' => $prefixFirst,
'TDIGEST.CDF' => $prefixFirst,
'TDIGEST.CREATE' => $prefixFirst,
'TDIGEST.INFO' => $prefixFirst,
'TDIGEST.MAX' => $prefixFirst,
'TDIGEST.MIN' => $prefixFirst,
'TDIGEST.QUANTILE' => $prefixFirst,
'TDIGEST.RANK' => $prefixFirst,
'TDIGEST.RESET' => $prefixFirst,
'TDIGEST.REVRANK' => $prefixFirst,
'TDIGEST.TRIMMED_MEAN' => $prefixFirst,
'TOPK.ADD' => $prefixFirst,
'TOPK.INCRBY' => $prefixFirst,
'TOPK.INFO' => $prefixFirst,
'TOPK.LIST' => $prefixFirst,
'TOPK.QUERY' => $prefixFirst,
'TOPK.RESERVE' => $prefixFirst,
/* RediSearch */
'FT.AGGREGATE' => $prefixFirst,
'FT.ALTER' => $prefixFirst,
'FT.CREATE' => $prefixFirst,
'FT.CURSOR DEL' => $prefixFirst,
'FT.CURSOR READ' => $prefixFirst,
'FT.DROPINDEX' => $prefixFirst,
'FT.EXPLAIN' => $prefixFirst,
'FT.INFO' => $prefixFirst,
'FT.PROFILE' => $prefixFirst,
'FT.SEARCH' => $prefixFirst,
'FT.SPELLCHECK' => $prefixFirst,
'FT.SYNDUMP' => $prefixFirst,
'FT.SYNUPDATE' => $prefixFirst,
'FT.TAGVALS' => $prefixFirst,
/* Redis TimeSeries */
'TS.ADD' => $prefixFirst,
'TS.ALTER' => $prefixFirst,
'TS.CREATE' => $prefixFirst,
'TS.DECRBY' => $prefixFirst,
'TS.DEL' => $prefixFirst,
'TS.GET' => $prefixFirst,
'TS.INCRBY' => $prefixFirst,
'TS.INFO' => $prefixFirst,
'TS.MGET' => $prefixFirst,
'TS.MRANGE' => $prefixFirst,
'TS.MREVRANGE' => $prefixFirst,
'TS.QUERYINDEX' => $prefixFirst,
'TS.RANGE' => $prefixFirst,
'TS.REVRANGE' => $prefixFirst,
];
}
/**
@ -190,7 +325,7 @@ class KeyPrefixProcessor implements ProcessorInterface
if ($command instanceof PrefixableCommandInterface) {
$command->prefixKeys($this->prefix);
} elseif (isset($this->commands[$commandID = strtoupper($command->getId())])) {
call_user_func($this->commands[$commandID], $command, $this->prefix);
$this->commands[$commandID]($command, $this->prefix);
}
}
@ -208,7 +343,7 @@ class KeyPrefixProcessor implements ProcessorInterface
* @param string $commandID The ID of the command to be handled.
* @param mixed $callback A valid callable object or NULL.
*
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public function setCommandHandler($commandID, $callback = null)
{
@ -221,7 +356,7 @@ class KeyPrefixProcessor implements ProcessorInterface
}
if (!is_callable($callback)) {
throw new \InvalidArgumentException(
throw new InvalidArgumentException(
'Callback must be a valid callable object or NULL'
);
}
@ -338,7 +473,7 @@ class KeyPrefixProcessor implements ProcessorInterface
if (($count = count($arguments)) > 1) {
for ($i = 1; $i < $count; ++$i) {
switch ($arguments[$i]) {
switch (strtoupper($arguments[$i])) {
case 'BY':
case 'STORE':
$arguments[$i] = "$prefix{$arguments[++$i]}";
@ -351,7 +486,7 @@ class KeyPrefixProcessor implements ProcessorInterface
}
break;
case 'LIMIT';
case 'LIMIT':
$i += 2;
break;
}
@ -412,4 +547,31 @@ class KeyPrefixProcessor implements ProcessorInterface
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix to the key of a GEORADIUS command.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function georadius(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
$arguments[0] = "$prefix{$arguments[0]}";
$startIndex = $command->getId() === 'GEORADIUS' ? 5 : 4;
if (($count = count($arguments)) > $startIndex) {
for ($i = $startIndex; $i < $count; ++$i) {
switch (strtoupper($arguments[$i])) {
case 'STORE':
case 'STOREDIST':
$arguments[$i] = "$prefix{$arguments[++$i]}";
break;
}
}
}
$command->setRawArguments($arguments);
}
}
}

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -11,21 +12,24 @@
namespace Predis\Command\Processor;
use ArrayAccess;
use ArrayIterator;
use InvalidArgumentException;
use Predis\Command\CommandInterface;
use ReturnTypeWillChange;
use Traversable;
/**
* Default implementation of a command processors chain.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ProcessorChain implements \ArrayAccess, ProcessorInterface
class ProcessorChain implements ArrayAccess, ProcessorInterface
{
private $processors = array();
private $processors = [];
/**
* @param array $processors List of instances of ProcessorInterface.
*/
public function __construct($processors = array())
public function __construct($processors = [])
{
foreach ($processors as $processor) {
$this->add($processor);
@ -71,11 +75,11 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* Returns an iterator over the list of command processor in the chain.
*
* @return \ArrayIterator
* @return Traversable<int, ProcessorInterface>
*/
public function getIterator()
{
return new \ArrayIterator($this->processors);
return new ArrayIterator($this->processors);
}
/**
@ -89,30 +93,36 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
}
/**
* {@inheritdoc}
* @param int $index
* @return bool
*/
#[ReturnTypeWillChange]
public function offsetExists($index)
{
return isset($this->processors[$index]);
}
/**
* {@inheritdoc}
* @param int $index
* @return ProcessorInterface
*/
#[ReturnTypeWillChange]
public function offsetGet($index)
{
return $this->processors[$index];
}
/**
* {@inheritdoc}
* @param int $index
* @param ProcessorInterface $processor
* @return void
*/
#[ReturnTypeWillChange]
public function offsetSet($index, $processor)
{
if (!$processor instanceof ProcessorInterface) {
throw new \InvalidArgumentException(
'A processor chain accepts only instances of '.
"'Predis\Command\Processor\ProcessorInterface'."
throw new InvalidArgumentException(
'Processor chain accepts only instances of `Predis\Command\Processor\ProcessorInterface`'
);
}
@ -120,8 +130,10 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
}
/**
* {@inheritdoc}
* @param int $index
* @return void
*/
#[ReturnTypeWillChange]
public function offsetUnset($index)
{
unset($this->processors[$index]);

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -15,8 +16,6 @@ use Predis\Command\CommandInterface;
/**
* A command processor processes Redis commands before they are sent to Redis.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface ProcessorInterface
{

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/publish
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class PubSubPublish extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PUBLISH';
}
}

View file

@ -1,61 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/pubsub
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class PubSubPubsub extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PUBSUB';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
switch (strtolower($this->getArgument(0))) {
case 'numsub':
return self::processNumsub($data);
default:
return $data;
}
}
/**
* Returns the processed response to PUBSUB NUMSUB.
*
* @param array $channels List of channels
*
* @return array
*/
protected static function processNumsub(array $channels)
{
$processed = array();
$count = count($channels);
for ($i = 0; $i < $count; ++$i) {
$processed[$channels[$i]] = $channels[++$i];
}
return $processed;
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/subscribe
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class PubSubSubscribe extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'SUBSCRIBE';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
return self::normalizeArguments($arguments);
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/psubscribe
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class PubSubSubscribeByPattern extends PubSubSubscribe
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PSUBSCRIBE';
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/unsubscribe
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class PubSubUnsubscribe extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'UNSUBSCRIBE';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
return self::normalizeArguments($arguments);
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/punsubscribe
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class PubSubUnsubscribeByPattern extends PubSubUnsubscribe
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'PUNSUBSCRIBE';
}
}

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -12,52 +13,45 @@
namespace Predis\Command;
/**
* Class for generic "anonymous" Redis commands.
* Class representing a generic Redis command.
*
* This command class does not filter input arguments or parse responses, but
* can be used to leverage the standard Predis API to execute any command simply
* by providing the needed arguments following the command signature as defined
* by Redis in its documentation.
* Arguments and responses for these commands are not normalized and they follow
* what is defined by the Redis documentation.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* Raw commands can be useful when implementing higher level abstractions on top
* of Predis\Client or managing internals like Redis Sentinel or Cluster as they
* are not potentially subject to hijacking from third party libraries when they
* override command handlers for standard Redis commands.
*/
class RawCommand implements CommandInterface
final class RawCommand implements CommandInterface
{
private $slot;
private $commandID;
private $arguments;
/**
* @param array $arguments Command ID and its arguments.
*
* @throws \InvalidArgumentException
* @param string $commandID Command ID
* @param array $arguments Command arguments
*/
public function __construct(array $arguments)
public function __construct($commandID, array $arguments = [])
{
if (!$arguments) {
throw new \InvalidArgumentException(
'The arguments array must contain at least the command ID.'
);
}
$this->commandID = strtoupper(array_shift($arguments));
$this->arguments = $arguments;
$this->commandID = strtoupper($commandID);
$this->setArguments($arguments);
}
/**
* Creates a new raw command using a variadic method.
*
* @param string $commandID Redis command ID.
* @param string ... Arguments list for the command.
* @param string $commandID Redis command ID
* @param string ...$args Arguments list for the command
*
* @return CommandInterface
*/
public static function create($commandID /* [ $arg, ... */)
public static function create($commandID, ...$args)
{
$arguments = func_get_args();
$command = new self($arguments);
return $command;
return new static(array_shift($arguments), $arguments);
}
/**
@ -116,9 +110,7 @@ class RawCommand implements CommandInterface
*/
public function getSlot()
{
if (isset($this->slot)) {
return $this->slot;
}
return $this->slot ?? null;
}
/**

View file

@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@ -15,12 +16,18 @@ namespace Predis\Command;
* Base class used to implement an higher level abstraction for commands based
* on Lua scripting with EVAL and EVALSHA.
*
* @link http://redis.io/commands/eval
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @see http://redis.io/commands/eval
*/
abstract class ScriptCommand extends ServerEvalSHA
abstract class ScriptCommand extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'EVALSHA';
}
/**
* Gets the body of a Lua script.
*
@ -28,6 +35,16 @@ abstract class ScriptCommand extends ServerEvalSHA
*/
abstract public function getScript();
/**
* Calculates the SHA1 hash of the body of the script.
*
* @return string SHA1 hash.
*/
public function getScriptHash()
{
return sha1($this->getScript());
}
/**
* Specifies the number of arguments that should be considered as keys.
*
@ -55,16 +72,20 @@ abstract class ScriptCommand extends ServerEvalSHA
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
public function setArguments(array $arguments)
{
if (($numkeys = $this->getKeysCount()) && $numkeys < 0) {
$numkeys = count($arguments) + $numkeys;
}
return array_merge(array(sha1($this->getScript()), (int) $numkeys), $arguments);
$arguments = array_merge([$this->getScriptHash(), (int) $numkeys], $arguments);
parent::setArguments($arguments);
}
/**
* Returns arguments for EVAL command.
*
* @return array
*/
public function getEvalArguments()
@ -74,4 +95,14 @@ abstract class ScriptCommand extends ServerEvalSHA
return $arguments;
}
/**
* Returns the equivalent EVAL command as a raw command instance.
*
* @return RawCommand
*/
public function getEvalCommand()
{
return new RawCommand('EVAL', $this->getEvalArguments());
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/bgrewriteaof
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ServerBackgroundRewriteAOF extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'BGREWRITEAOF';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return $data == 'Background append only file rewriting started';
}
}

View file

@ -1,36 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/bgsave
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ServerBackgroundSave extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'BGSAVE';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return $data === 'Background saving started' ? true : $data;
}
}

View file

@ -1,74 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/client-list
* @link http://redis.io/commands/client-kill
* @link http://redis.io/commands/client-getname
* @link http://redis.io/commands/client-setname
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ServerClient extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'CLIENT';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
$args = array_change_key_case($this->getArguments(), CASE_UPPER);
switch (strtoupper($args[0])) {
case 'LIST':
return $this->parseClientList($data);
case 'KILL':
case 'GETNAME':
case 'SETNAME':
default:
return $data;
}
}
/**
* Parses the response to CLIENT LIST and returns a structured list.
*
* @param string $data Response buffer.
*
* @return array
*/
protected function parseClientList($data)
{
$clients = array();
foreach (explode("\n", $data, -1) as $clientData) {
$client = array();
foreach (explode(' ', $clientData) as $kv) {
@list($k, $v) = explode('=', $kv);
$client[$k] = $v;
}
$clients[] = $client;
}
return $clients;
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/command
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ServerCommand extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'COMMAND';
}
}

View file

@ -1,49 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/config-set
* @link http://redis.io/commands/config-get
* @link http://redis.io/commands/config-resetstat
* @link http://redis.io/commands/config-rewrite
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ServerConfig extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'CONFIG';
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
if (is_array($data)) {
$result = array();
for ($i = 0; $i < count($data); ++$i) {
$result[$data[$i]] = $data[++$i];
}
return $result;
}
return $data;
}
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/dbsize
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ServerDatabaseSize extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'DBSIZE';
}
}

Some files were not shown because too many files have changed in this diff Show more