mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-09-20 07:35:55 +08:00
Predis to v2.2.2
This commit is contained in:
parent
f6b440adef
commit
84ffe1e552
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
Loading…
Reference in a new issue