Retwis ported to modern Redis data types.
The example (and related documentation at redis.io) was not updated for 5 years. Redis had no sorted sets and hashes when the original code was written (!). An update was really needed. We also use a modern PHP client now: Predis. A copy is shipped within this repository to make life easier to newcomers trying Redis for the first time via this example.
This commit is contained in:
commit
c58f935fdc
277 changed files with 18503 additions and 0 deletions
62
Predis/Autoloader.php
Normal file
62
Predis/Autoloader.php
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Implements a lightweight PSR-0 compliant autoloader.
|
||||
*
|
||||
* @author Eric Naeseth <eric@thumbtack.com>
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class Autoloader
|
||||
{
|
||||
private $directory;
|
||||
private $prefix;
|
||||
private $prefixLength;
|
||||
|
||||
/**
|
||||
* @param string $baseDirectory Base directory where the source files are located.
|
||||
*/
|
||||
public function __construct($baseDirectory = __DIR__)
|
||||
{
|
||||
$this->directory = $baseDirectory;
|
||||
$this->prefix = __NAMESPACE__ . '\\';
|
||||
$this->prefixLength = strlen($this->prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the autoloader class with the PHP SPL autoloader.
|
||||
*
|
||||
* @param bool $prepend Prepend the autoloader on the stack instead of appending it.
|
||||
*/
|
||||
public static function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array(new self, 'autoload'), true, $prepend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a class from a file using its fully qualified name.
|
||||
*
|
||||
* @param string $className Fully qualified name of a class.
|
||||
*/
|
||||
public function autoload($className)
|
||||
{
|
||||
if (0 === strpos($className, $this->prefix)) {
|
||||
$parts = explode('\\', substr($className, $this->prefixLength));
|
||||
$filepath = $this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.php';
|
||||
|
||||
if (is_file($filepath)) {
|
||||
require($filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Predis/BasicClientInterface.php
Normal file
31
Predis/BasicClientInterface.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?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;
|
||||
|
||||
use Predis\Command\CommandInterface;
|
||||
|
||||
/**
|
||||
* Defines the interface of a basic client object or abstraction that
|
||||
* can send commands to Redis.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface BasicClientInterface
|
||||
{
|
||||
/**
|
||||
* Executes the specified Redis command.
|
||||
*
|
||||
* @param CommandInterface $command A Redis command.
|
||||
* @return mixed
|
||||
*/
|
||||
public function executeCommand(CommandInterface $command);
|
||||
}
|
||||
465
Predis/Client.php
Normal file
465
Predis/Client.php
Normal file
|
|
@ -0,0 +1,465 @@
|
|||
<?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;
|
||||
|
||||
use Predis\Command\CommandInterface;
|
||||
use Predis\Command\ScriptedCommand;
|
||||
use Predis\Connection\AggregatedConnectionInterface;
|
||||
use Predis\Connection\ConnectionInterface;
|
||||
use Predis\Connection\ConnectionFactoryInterface;
|
||||
use Predis\Monitor\MonitorContext;
|
||||
use Predis\Option\ClientOptions;
|
||||
use Predis\Option\ClientOptionsInterface;
|
||||
use Predis\Pipeline\PipelineContext;
|
||||
use Predis\PubSub\PubSubContext;
|
||||
use Predis\Transaction\MultiExecContext;
|
||||
|
||||
/**
|
||||
* Main class that exposes the most high-level interface to interact with Redis.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class Client implements ClientInterface
|
||||
{
|
||||
const VERSION = '0.8.5';
|
||||
|
||||
private $options;
|
||||
private $profile;
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* Initializes a new client with optional connection parameters and client options.
|
||||
*
|
||||
* @param mixed $parameters Connection parameters for one or multiple servers.
|
||||
* @param mixed $options Options that specify certain behaviours for the client.
|
||||
*/
|
||||
public function __construct($parameters = null, $options = null)
|
||||
{
|
||||
$this->options = $this->filterOptions($options);
|
||||
$this->profile = $this->options->profile;
|
||||
$this->connection = $this->initializeConnection($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of Predis\Option\ClientOptions from various types of
|
||||
* arguments (string, array, Predis\Profile\ServerProfile) or returns the
|
||||
* passed object if it is an instance of Predis\Option\ClientOptions.
|
||||
*
|
||||
* @param mixed $options Client options.
|
||||
* @return ClientOptions
|
||||
*/
|
||||
protected function filterOptions($options)
|
||||
{
|
||||
if (!isset($options)) {
|
||||
return new ClientOptions();
|
||||
}
|
||||
|
||||
if (is_array($options)) {
|
||||
return new ClientOptions($options);
|
||||
}
|
||||
|
||||
if ($options instanceof ClientOptionsInterface) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("Invalid type for client options");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes one or multiple connection (cluster) objects from various
|
||||
* types of arguments (string, array) or returns the passed object if it
|
||||
* implements Predis\Connection\ConnectionInterface.
|
||||
*
|
||||
* @param mixed $parameters Connection parameters or instance.
|
||||
* @return ConnectionInterface
|
||||
*/
|
||||
protected function initializeConnection($parameters)
|
||||
{
|
||||
if ($parameters instanceof ConnectionInterface) {
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
if (is_array($parameters) && isset($parameters[0])) {
|
||||
$options = $this->options;
|
||||
$replication = isset($options->replication) && $options->replication;
|
||||
$connection = $options->{$replication ? 'replication' : 'cluster'};
|
||||
|
||||
return $options->connections->createAggregated($connection, $parameters);
|
||||
}
|
||||
|
||||
if (is_callable($parameters)) {
|
||||
$connection = call_user_func($parameters, $this->options);
|
||||
|
||||
if (!$connection instanceof ConnectionInterface) {
|
||||
throw new \InvalidArgumentException(
|
||||
'Callable parameters must return instances of Predis\Connection\ConnectionInterface'
|
||||
);
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
return $this->options->connections->create($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getProfile()
|
||||
{
|
||||
return $this->profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection factory object used by the client.
|
||||
*
|
||||
* @return ConnectionFactoryInterface
|
||||
*/
|
||||
public function getConnectionFactory()
|
||||
{
|
||||
return $this->options->connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of a client for the specified connection when the
|
||||
* client is connected to a cluster. The new instance will use the same
|
||||
* options of the original client.
|
||||
*
|
||||
* @param string $connectionID Identifier for the connection.
|
||||
* @return Client
|
||||
*/
|
||||
public function getClientFor($connectionID)
|
||||
{
|
||||
if (!$connection = $this->getConnectionById($connectionID)) {
|
||||
throw new \InvalidArgumentException("Invalid connection ID: '$connectionID'");
|
||||
}
|
||||
|
||||
return new static($connection, $this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the connection to the server.
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
$this->connection->connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from the server.
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$this->connection->disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from the server.
|
||||
*
|
||||
* This method is an alias of disconnect().
|
||||
*/
|
||||
public function quit()
|
||||
{
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the underlying connection is connected to Redis.
|
||||
*
|
||||
* @return bool True means that the connection is open.
|
||||
* False means that the connection is closed.
|
||||
*/
|
||||
public function isConnected()
|
||||
{
|
||||
return $this->connection->isConnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a single connection out of an aggregated connections instance.
|
||||
*
|
||||
* @param string $connectionId Index or alias of the single connection.
|
||||
* @return Connection\SingleConnectionInterface
|
||||
*/
|
||||
public function getConnectionById($connectionId)
|
||||
{
|
||||
if (!$this->connection instanceof AggregatedConnectionInterface) {
|
||||
throw new NotSupportedException('Retrieving connections by ID is supported only when using aggregated connections');
|
||||
}
|
||||
|
||||
return $this->connection->getConnectionById($connectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Redis command with the specified arguments and sends a request
|
||||
* to the server.
|
||||
*
|
||||
* @param string $commandID Command ID.
|
||||
* @param array $arguments Arguments for the command.
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($commandID, $arguments)
|
||||
{
|
||||
$command = $this->createCommand($commandID, $arguments);
|
||||
$response = $this->executeCommand($command);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createCommand($commandID, $arguments = array())
|
||||
{
|
||||
return $this->profile->createCommand($commandID, $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function executeCommand(CommandInterface $command)
|
||||
{
|
||||
$response = $this->connection->executeCommand($command);
|
||||
|
||||
if ($response instanceof ResponseObjectInterface) {
|
||||
if ($response instanceof ResponseErrorInterface) {
|
||||
$response = $this->onResponseError($command, $response);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $command->parseResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles -ERR responses returned by Redis.
|
||||
*
|
||||
* @param CommandInterface $command The command that generated the error.
|
||||
* @param ResponseErrorInterface $response The error response instance.
|
||||
* @return mixed
|
||||
*/
|
||||
protected function onResponseError(CommandInterface $command, ResponseErrorInterface $response)
|
||||
{
|
||||
if ($command instanceof ScriptedCommand && $response->getErrorType() === 'NOSCRIPT') {
|
||||
$eval = $this->createCommand('eval');
|
||||
$eval->setRawArguments($command->getEvalArguments());
|
||||
|
||||
$response = $this->executeCommand($eval);
|
||||
|
||||
if (!$response instanceof ResponseObjectInterface) {
|
||||
$response = $command->parseResponse($response);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
if ($this->options->exceptions) {
|
||||
throw new ServerException($response->getMessage());
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the specified initializer method on $this with 0, 1 or 2 arguments.
|
||||
*
|
||||
* TODO: Invert $argv and $initializer.
|
||||
*
|
||||
* @param array $argv Arguments for the initializer.
|
||||
* @param string $initializer The initializer method.
|
||||
* @return mixed
|
||||
*/
|
||||
private function sharedInitializer($argv, $initializer)
|
||||
{
|
||||
switch (count($argv)) {
|
||||
case 0:
|
||||
return $this->$initializer();
|
||||
|
||||
case 1:
|
||||
list($arg0) = $argv;
|
||||
|
||||
return is_array($arg0) ? $this->$initializer($arg0) : $this->$initializer(null, $arg0);
|
||||
|
||||
case 2:
|
||||
list($arg0, $arg1) = $argv;
|
||||
|
||||
return $this->$initializer($arg0, $arg1);
|
||||
|
||||
default:
|
||||
return $this->$initializer($this, $argv);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new pipeline context and returns it, or returns the results of
|
||||
* a pipeline executed inside the optionally provided callable object.
|
||||
*
|
||||
* @param mixed ... Options for the context, a callable object, or both.
|
||||
* @return PipelineContext|array
|
||||
*/
|
||||
public function pipeline(/* arguments */)
|
||||
{
|
||||
return $this->sharedInitializer(func_get_args(), 'initPipeline');
|
||||
}
|
||||
|
||||
/**
|
||||
* Pipeline context initializer.
|
||||
*
|
||||
* @param array $options Options for the context.
|
||||
* @param mixed $callable Optional callable object used to execute the context.
|
||||
* @return PipelineContext|array
|
||||
*/
|
||||
protected function initPipeline(Array $options = null, $callable = null)
|
||||
{
|
||||
$executor = isset($options['executor']) ? $options['executor'] : null;
|
||||
|
||||
if (is_callable($executor)) {
|
||||
$executor = call_user_func($executor, $this, $options);
|
||||
}
|
||||
|
||||
$pipeline = new PipelineContext($this, $executor);
|
||||
$replies = $this->pipelineExecute($pipeline, $callable);
|
||||
|
||||
return $replies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a pipeline context when a callable object is passed.
|
||||
*
|
||||
* @param PipelineContext $pipeline Pipeline context instance.
|
||||
* @param mixed $callable Optional callable object used to execute the context.
|
||||
* @return PipelineContext|array
|
||||
*/
|
||||
private function pipelineExecute(PipelineContext $pipeline, $callable)
|
||||
{
|
||||
return isset($callable) ? $pipeline->execute($callable) : $pipeline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new transaction context and returns it, or returns the results of
|
||||
* a transaction executed inside the optionally provided callable object.
|
||||
*
|
||||
* @deprecated You should start using the new Client::transaction() method
|
||||
* as it will replace Client::multiExec() in the next major
|
||||
* version of the library.
|
||||
*
|
||||
* @param mixed ... Options for the context, a callable object, or both.
|
||||
* @return MultiExecContext|array
|
||||
*/
|
||||
public function multiExec(/* arguments */)
|
||||
{
|
||||
return $this->sharedInitializer(func_get_args(), 'initMultiExec');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new transaction context and returns it, or returns the results of
|
||||
* a transaction executed inside the optionally provided callable object.
|
||||
*
|
||||
* @param mixed ... Options for the context, a callable object, or both.
|
||||
* @return MultiExecContext|array
|
||||
*/
|
||||
public function transaction(/* arguments */)
|
||||
{
|
||||
return $this->sharedInitializer(func_get_args(), 'initMultiExec');
|
||||
}
|
||||
|
||||
/**
|
||||
* Transaction context initializer.
|
||||
*
|
||||
* @param array $options Options for the context.
|
||||
* @param mixed $callable Optional callable object used to execute the context.
|
||||
* @return MultiExecContext|array
|
||||
*/
|
||||
protected function initMultiExec(Array $options = null, $callable = null)
|
||||
{
|
||||
$transaction = new MultiExecContext($this, $options ?: array());
|
||||
|
||||
return isset($callable) ? $transaction->execute($callable) : $transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Publish / Subscribe context and returns it, or executes it
|
||||
* inside the optionally provided callable object.
|
||||
*
|
||||
* @deprecated This method will change in the next major release to support
|
||||
* the new PUBSUB command introduced in Redis 2.8. Please use
|
||||
* Client::pubSubLoop() to create Predis\PubSub\PubSubContext
|
||||
* instances from now on.
|
||||
*
|
||||
* @param mixed ... Options for the context, a callable object, or both.
|
||||
* @return PubSubContext|array
|
||||
*/
|
||||
public function pubSub(/* arguments */)
|
||||
{
|
||||
return call_user_func_array(array($this, 'pubSubLoop'), func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Publish / Subscribe context and returns it, or executes it
|
||||
* inside the optionally provided callable object.
|
||||
*
|
||||
* @param mixed ... Options for the context, a callable object, or both.
|
||||
* @return PubSubContext|array
|
||||
*/
|
||||
public function pubSubLoop(/* arguments */)
|
||||
{
|
||||
return $this->sharedInitializer(func_get_args(), 'initPubSub');
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish / Subscribe context initializer.
|
||||
*
|
||||
* @param array $options Options for the context.
|
||||
* @param mixed $callable Optional callable object used to execute the context.
|
||||
* @return PubSubContext
|
||||
*/
|
||||
protected function initPubSub(Array $options = null, $callable = null)
|
||||
{
|
||||
$pubsub = new PubSubContext($this, $options);
|
||||
|
||||
if (!isset($callable)) {
|
||||
return $pubsub;
|
||||
}
|
||||
|
||||
foreach ($pubsub as $message) {
|
||||
if (call_user_func($callable, $pubsub, $message) === false) {
|
||||
$pubsub->closeContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new monitor context.
|
||||
*
|
||||
* @return MonitorContext
|
||||
*/
|
||||
public function monitor()
|
||||
{
|
||||
return new MonitorContext($this);
|
||||
}
|
||||
}
|
||||
21
Predis/ClientException.php
Normal file
21
Predis/ClientException.php
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Exception class that identifies client-side errors.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ClientException extends PredisException
|
||||
{
|
||||
}
|
||||
66
Predis/ClientInterface.php
Normal file
66
Predis/ClientInterface.php
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<?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;
|
||||
|
||||
use Predis\Connection\ConnectionInterface;
|
||||
use Predis\Option\ClientOptionsInterface;
|
||||
use Predis\Profile\ServerProfileInterface;
|
||||
|
||||
/**
|
||||
* Interface defining the most important parts needed to create an
|
||||
* high-level Redis client object that can interact with other
|
||||
* building blocks of Predis.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface ClientInterface extends BasicClientInterface
|
||||
{
|
||||
/**
|
||||
* Returns the server profile used by the client.
|
||||
*
|
||||
* @return ServerProfileInterface
|
||||
*/
|
||||
public function getProfile();
|
||||
|
||||
/**
|
||||
* Returns the client options specified upon initialization.
|
||||
*
|
||||
* @return ClientOptionsInterface
|
||||
*/
|
||||
public function getOptions();
|
||||
|
||||
/**
|
||||
* Opens the connection to the server.
|
||||
*/
|
||||
public function connect();
|
||||
|
||||
/**
|
||||
* Disconnects from the server.
|
||||
*/
|
||||
public function disconnect();
|
||||
|
||||
/**
|
||||
* Returns the underlying connection instance.
|
||||
*
|
||||
* @return ConnectionInterface
|
||||
*/
|
||||
public function getConnection();
|
||||
|
||||
/**
|
||||
* Creates a new instance of the specified Redis command.
|
||||
*
|
||||
* @param string $method The name of a Redis command.
|
||||
* @param array $arguments The arguments for the command.
|
||||
* @return Command\CommandInterface
|
||||
*/
|
||||
public function createCommand($method, $arguments = array());
|
||||
}
|
||||
42
Predis/Cluster/CommandHashStrategyInterface.php
Normal file
42
Predis/Cluster/CommandHashStrategyInterface.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?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\Cluster;
|
||||
|
||||
use Predis\Command\CommandInterface;
|
||||
|
||||
/**
|
||||
* Interface for classes defining the strategy used to calculate an hash
|
||||
* out of keys extracted from supported commands.
|
||||
*
|
||||
* This is mostly useful to support clustering via client-side sharding.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface CommandHashStrategyInterface
|
||||
{
|
||||
/**
|
||||
* Returns the hash for the given command using the specified algorithm, or null
|
||||
* if the command cannot be hashed.
|
||||
*
|
||||
* @param CommandInterface $command Command to be hashed.
|
||||
* @return int
|
||||
*/
|
||||
public function getHash(CommandInterface $command);
|
||||
|
||||
/**
|
||||
* Returns the hash for the given key using the specified algorithm.
|
||||
*
|
||||
* @param string $key Key to be hashed.
|
||||
* @return string
|
||||
*/
|
||||
public function getKeyHash($key);
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<?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\Cluster\Distribution;
|
||||
|
||||
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 DistributionStrategyInterface
|
||||
{
|
||||
/**
|
||||
* Adds a node to the distributor with an optional weight.
|
||||
*
|
||||
* @param mixed $node Node object.
|
||||
* @param int $weight Weight for the node.
|
||||
*/
|
||||
public function add($node, $weight = null);
|
||||
|
||||
/**
|
||||
* Removes a node from the distributor.
|
||||
*
|
||||
* @param mixed $node Node object.
|
||||
*/
|
||||
public function remove($node);
|
||||
|
||||
/**
|
||||
* Gets a node from the distributor using the computed hash of a key.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key);
|
||||
|
||||
/**
|
||||
* Returns the underlying hash generator instance.
|
||||
*
|
||||
* @return HashGeneratorInterface
|
||||
*/
|
||||
public function getHashGenerator();
|
||||
}
|
||||
21
Predis/Cluster/Distribution/EmptyRingException.php
Normal file
21
Predis/Cluster/Distribution/EmptyRingException.php
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?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\Cluster\Distribution;
|
||||
|
||||
/**
|
||||
* Exception class that identifies empty rings.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class EmptyRingException extends \Exception
|
||||
{
|
||||
}
|
||||
246
Predis/Cluster/Distribution/HashRing.php
Normal file
246
Predis/Cluster/Distribution/HashRing.php
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
<?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\Cluster\Distribution;
|
||||
|
||||
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 DistributionStrategyInterface, HashGeneratorInterface
|
||||
{
|
||||
const DEFAULT_REPLICAS = 128;
|
||||
const DEFAULT_WEIGHT = 100;
|
||||
|
||||
private $ring;
|
||||
private $ringKeys;
|
||||
private $ringKeysCount;
|
||||
private $replicas;
|
||||
private $nodeHashCallback;
|
||||
private $nodes = array();
|
||||
|
||||
/**
|
||||
* @param int $replicas Number of replicas in the ring.
|
||||
* @param mixed $nodeHashCallback Callback returning the string used to calculate the hash of a node.
|
||||
*/
|
||||
public function __construct($replicas = self::DEFAULT_REPLICAS, $nodeHashCallback = null)
|
||||
{
|
||||
$this->replicas = $replicas;
|
||||
$this->nodeHashCallback = $nodeHashCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a node to the ring with an optional weight.
|
||||
*
|
||||
* @param mixed $node Node object.
|
||||
* @param int $weight Weight for the node.
|
||||
*/
|
||||
public function add($node, $weight = null)
|
||||
{
|
||||
// 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('object' => $node, 'weight' => (int) $weight ?: $this::DEFAULT_WEIGHT);
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function remove($node)
|
||||
{
|
||||
// A node is removed by resetting the ring so that it's recreated from
|
||||
// scratch, in order to reassign possible hashes with collisions to the
|
||||
// right node according to the order in which they were added in the
|
||||
// first place.
|
||||
for ($i = 0; $i < count($this->nodes); ++$i) {
|
||||
if ($this->nodes[$i]['object'] === $node) {
|
||||
array_splice($this->nodes, $i, 1);
|
||||
$this->reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the distributor.
|
||||
*/
|
||||
private function reset()
|
||||
{
|
||||
unset(
|
||||
$this->ring,
|
||||
$this->ringKeys,
|
||||
$this->ringKeysCount
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initialization status of the distributor.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isInitialized()
|
||||
{
|
||||
return isset($this->ringKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the total weight of all the nodes in the distributor.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function computeTotalWeight()
|
||||
{
|
||||
$totalWeight = 0;
|
||||
|
||||
foreach ($this->nodes as $node) {
|
||||
$totalWeight += $node['weight'];
|
||||
}
|
||||
|
||||
return $totalWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the distributor.
|
||||
*/
|
||||
private function initialize()
|
||||
{
|
||||
if ($this->isInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->nodes) {
|
||||
throw new EmptyRingException('Cannot initialize empty hashring');
|
||||
}
|
||||
|
||||
$this->ring = array();
|
||||
$totalWeight = $this->computeTotalWeight();
|
||||
$nodesCount = count($this->nodes);
|
||||
|
||||
foreach ($this->nodes as $node) {
|
||||
$weightRatio = $node['weight'] / $totalWeight;
|
||||
$this->addNodeToRing($this->ring, $node, $nodesCount, $this->replicas, $weightRatio);
|
||||
}
|
||||
|
||||
ksort($this->ring, SORT_NUMERIC);
|
||||
$this->ringKeys = array_keys($this->ring);
|
||||
$this->ringKeysCount = count($this->ringKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the logic needed to add a node to the hashring.
|
||||
*
|
||||
* @param array $ring Source hashring.
|
||||
* @param mixed $node Node object to be added.
|
||||
* @param int $totalNodes Total number of nodes.
|
||||
* @param int $replicas Number of replicas in the ring.
|
||||
* @param float $weightRatio Weight ratio for the node.
|
||||
*/
|
||||
protected function addNodeToRing(&$ring, $node, $totalNodes, $replicas, $weightRatio)
|
||||
{
|
||||
$nodeObject = $node['object'];
|
||||
$nodeHash = $this->getNodeHash($nodeObject);
|
||||
$replicas = (int) round($weightRatio * $totalNodes * $replicas);
|
||||
|
||||
for ($i = 0; $i < $replicas; $i++) {
|
||||
$key = crc32("$nodeHash:$i");
|
||||
$ring[$key] = $nodeObject;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNodeHash($nodeObject)
|
||||
{
|
||||
if ($this->nodeHashCallback === null) {
|
||||
return (string) $nodeObject;
|
||||
}
|
||||
|
||||
return call_user_func($this->nodeHashCallback, $nodeObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the hash for the specified value.
|
||||
*
|
||||
* @param string $value Input value.
|
||||
* @return int
|
||||
*/
|
||||
public function hash($value)
|
||||
{
|
||||
return crc32($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return $this->ring[$this->getNodeKey($key)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the corrisponding key of a node distributed in the hashring.
|
||||
*
|
||||
* @param int $key Computed hash of a key.
|
||||
* @return int
|
||||
*/
|
||||
private function getNodeKey($key)
|
||||
{
|
||||
$this->initialize();
|
||||
$ringKeys = $this->ringKeys;
|
||||
$upper = $this->ringKeysCount - 1;
|
||||
$lower = 0;
|
||||
|
||||
while ($lower <= $upper) {
|
||||
$index = ($lower + $upper) >> 1;
|
||||
$item = $ringKeys[$index];
|
||||
|
||||
if ($item > $key) {
|
||||
$upper = $index - 1;
|
||||
} elseif ($item < $key) {
|
||||
$lower = $index + 1;
|
||||
} else {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $ringKeys[$this->wrapAroundStrategy($upper, $lower, $this->ringKeysCount)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a strategy to deal with wrap-around errors during binary searches.
|
||||
*
|
||||
* @param int $upper
|
||||
* @param int $lower
|
||||
* @param int $ringKeysCount
|
||||
* @return int
|
||||
*/
|
||||
protected function wrapAroundStrategy($upper, $lower, $ringKeysCount)
|
||||
{
|
||||
// Binary search for the last item in ringkeys with a value less or
|
||||
// equal to the key. If no such item exists, return the last item.
|
||||
return $upper >= 0 ? $upper : $ringKeysCount - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHashGenerator()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
71
Predis/Cluster/Distribution/KetamaPureRing.php
Normal file
71
Predis/Cluster/Distribution/KetamaPureRing.php
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?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\Cluster\Distribution;
|
||||
|
||||
/**
|
||||
* 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 KetamaPureRing extends HashRing
|
||||
{
|
||||
const DEFAULT_REPLICAS = 160;
|
||||
|
||||
/**
|
||||
* @param mixed $nodeHashCallback Callback returning the string used to calculate the hash of a node.
|
||||
*/
|
||||
public function __construct($nodeHashCallback = null)
|
||||
{
|
||||
parent::__construct($this::DEFAULT_REPLICAS, $nodeHashCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function addNodeToRing(&$ring, $node, $totalNodes, $replicas, $weightRatio)
|
||||
{
|
||||
$nodeObject = $node['object'];
|
||||
$nodeHash = $this->getNodeHash($nodeObject);
|
||||
$replicas = (int) floor($weightRatio * $totalNodes * ($replicas / 4));
|
||||
|
||||
for ($i = 0; $i < $replicas; $i++) {
|
||||
$unpackedDigest = unpack('V4', md5("$nodeHash-$i", true));
|
||||
|
||||
foreach ($unpackedDigest as $key) {
|
||||
$ring[$key] = $nodeObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hash($value)
|
||||
{
|
||||
$hash = unpack('V', md5($value, true));
|
||||
|
||||
return $hash[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function wrapAroundStrategy($upper, $lower, $ringKeysCount)
|
||||
{
|
||||
// Binary search for the first item in _ringkeys with a value greater
|
||||
// or equal to the key. If no such item exists, return the first item.
|
||||
return $lower < $ringKeysCount ? $lower : 0;
|
||||
}
|
||||
}
|
||||
72
Predis/Cluster/Hash/CRC16HashGenerator.php
Normal file
72
Predis/Cluster/Hash/CRC16HashGenerator.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?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\Cluster\Hash;
|
||||
|
||||
/**
|
||||
* This class implements the CRC-CCITT-16 algorithm used by redis-cluster.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class CRC16HashGenerator implements HashGeneratorInterface
|
||||
{
|
||||
private static $CCITT_16 = array(
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
|
||||
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
|
||||
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
|
||||
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
|
||||
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
|
||||
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
|
||||
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
|
||||
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
|
||||
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
|
||||
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
|
||||
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
|
||||
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
|
||||
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
|
||||
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
|
||||
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
|
||||
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
|
||||
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
|
||||
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
|
||||
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
|
||||
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
|
||||
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}
|
||||
*/
|
||||
public function hash($value)
|
||||
{
|
||||
// CRC-CCITT-16 algorithm
|
||||
$crc = 0;
|
||||
$CCITT_16 = self::$CCITT_16;
|
||||
$strlen = strlen($value);
|
||||
|
||||
for ($i = 0; $i < $strlen; $i++) {
|
||||
$crc = (($crc << 8) ^ $CCITT_16[($crc >> 8) ^ ord($value[$i])]) & 0xFFFF;
|
||||
}
|
||||
|
||||
return $crc;
|
||||
}
|
||||
}
|
||||
29
Predis/Cluster/Hash/HashGeneratorInterface.php
Normal file
29
Predis/Cluster/Hash/HashGeneratorInterface.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?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\Cluster\Hash;
|
||||
|
||||
/**
|
||||
* A generator of node keys implements the logic used to calculate the hash of
|
||||
* a key to distribute the respective operations among nodes.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface HashGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* Generates an hash that is used by the distributor algorithm
|
||||
*
|
||||
* @param string $value Value used to generate the hash.
|
||||
* @return int
|
||||
*/
|
||||
public function hash($value);
|
||||
}
|
||||
389
Predis/Cluster/PredisClusterHashStrategy.php
Normal file
389
Predis/Cluster/PredisClusterHashStrategy.php
Normal file
|
|
@ -0,0 +1,389 @@
|
|||
<?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\Cluster;
|
||||
|
||||
use Predis\Cluster\Hash\HashGeneratorInterface;
|
||||
use Predis\Command\CommandInterface;
|
||||
use Predis\Command\ScriptedCommand;
|
||||
|
||||
/**
|
||||
* Default class used by Predis for client-side sharding to calculate
|
||||
* hashes out of keys of supported commands.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class PredisClusterHashStrategy implements CommandHashStrategyInterface
|
||||
{
|
||||
private $commands;
|
||||
private $hashGenerator;
|
||||
|
||||
/**
|
||||
* @param HashGeneratorInterface $hashGenerator Hash generator instance.
|
||||
*/
|
||||
public function __construct(HashGeneratorInterface $hashGenerator)
|
||||
{
|
||||
$this->commands = $this->getDefaultCommands();
|
||||
$this->hashGenerator = $hashGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default map of supported commands with their handlers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getDefaultCommands()
|
||||
{
|
||||
$keyIsFirstArgument = array($this, 'getKeyFromFirstArgument');
|
||||
$keysAreAllArguments = array($this, 'getKeyFromAllArguments');
|
||||
|
||||
return array(
|
||||
/* commands operating on the key space */
|
||||
'EXISTS' => $keyIsFirstArgument,
|
||||
'DEL' => $keysAreAllArguments,
|
||||
'TYPE' => $keyIsFirstArgument,
|
||||
'EXPIRE' => $keyIsFirstArgument,
|
||||
'EXPIREAT' => $keyIsFirstArgument,
|
||||
'PERSIST' => $keyIsFirstArgument,
|
||||
'PEXPIRE' => $keyIsFirstArgument,
|
||||
'PEXPIREAT' => $keyIsFirstArgument,
|
||||
'TTL' => $keyIsFirstArgument,
|
||||
'PTTL' => $keyIsFirstArgument,
|
||||
'SORT' => $keyIsFirstArgument, // TODO
|
||||
'DUMP' => $keyIsFirstArgument,
|
||||
'RESTORE' => $keyIsFirstArgument,
|
||||
|
||||
/* commands operating on string values */
|
||||
'APPEND' => $keyIsFirstArgument,
|
||||
'DECR' => $keyIsFirstArgument,
|
||||
'DECRBY' => $keyIsFirstArgument,
|
||||
'GET' => $keyIsFirstArgument,
|
||||
'GETBIT' => $keyIsFirstArgument,
|
||||
'MGET' => $keysAreAllArguments,
|
||||
'SET' => $keyIsFirstArgument,
|
||||
'GETRANGE' => $keyIsFirstArgument,
|
||||
'GETSET' => $keyIsFirstArgument,
|
||||
'INCR' => $keyIsFirstArgument,
|
||||
'INCRBY' => $keyIsFirstArgument,
|
||||
'SETBIT' => $keyIsFirstArgument,
|
||||
'SETEX' => $keyIsFirstArgument,
|
||||
'MSET' => array($this, 'getKeyFromInterleavedArguments'),
|
||||
'MSETNX' => array($this, 'getKeyFromInterleavedArguments'),
|
||||
'SETNX' => $keyIsFirstArgument,
|
||||
'SETRANGE' => $keyIsFirstArgument,
|
||||
'STRLEN' => $keyIsFirstArgument,
|
||||
'SUBSTR' => $keyIsFirstArgument,
|
||||
'BITOP' => array($this, 'getKeyFromBitOp'),
|
||||
'BITCOUNT' => $keyIsFirstArgument,
|
||||
|
||||
/* commands operating on lists */
|
||||
'LINSERT' => $keyIsFirstArgument,
|
||||
'LINDEX' => $keyIsFirstArgument,
|
||||
'LLEN' => $keyIsFirstArgument,
|
||||
'LPOP' => $keyIsFirstArgument,
|
||||
'RPOP' => $keyIsFirstArgument,
|
||||
'RPOPLPUSH' => $keysAreAllArguments,
|
||||
'BLPOP' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'BRPOP' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'BRPOPLPUSH' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'LPUSH' => $keyIsFirstArgument,
|
||||
'LPUSHX' => $keyIsFirstArgument,
|
||||
'RPUSH' => $keyIsFirstArgument,
|
||||
'RPUSHX' => $keyIsFirstArgument,
|
||||
'LRANGE' => $keyIsFirstArgument,
|
||||
'LREM' => $keyIsFirstArgument,
|
||||
'LSET' => $keyIsFirstArgument,
|
||||
'LTRIM' => $keyIsFirstArgument,
|
||||
|
||||
/* commands operating on sets */
|
||||
'SADD' => $keyIsFirstArgument,
|
||||
'SCARD' => $keyIsFirstArgument,
|
||||
'SDIFF' => $keysAreAllArguments,
|
||||
'SDIFFSTORE' => $keysAreAllArguments,
|
||||
'SINTER' => $keysAreAllArguments,
|
||||
'SINTERSTORE' => $keysAreAllArguments,
|
||||
'SUNION' => $keysAreAllArguments,
|
||||
'SUNIONSTORE' => $keysAreAllArguments,
|
||||
'SISMEMBER' => $keyIsFirstArgument,
|
||||
'SMEMBERS' => $keyIsFirstArgument,
|
||||
'SSCAN' => $keyIsFirstArgument,
|
||||
'SPOP' => $keyIsFirstArgument,
|
||||
'SRANDMEMBER' => $keyIsFirstArgument,
|
||||
'SREM' => $keyIsFirstArgument,
|
||||
|
||||
/* commands operating on sorted sets */
|
||||
'ZADD' => $keyIsFirstArgument,
|
||||
'ZCARD' => $keyIsFirstArgument,
|
||||
'ZCOUNT' => $keyIsFirstArgument,
|
||||
'ZINCRBY' => $keyIsFirstArgument,
|
||||
'ZINTERSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
|
||||
'ZRANGE' => $keyIsFirstArgument,
|
||||
'ZRANGEBYSCORE' => $keyIsFirstArgument,
|
||||
'ZRANK' => $keyIsFirstArgument,
|
||||
'ZREM' => $keyIsFirstArgument,
|
||||
'ZREMRANGEBYRANK' => $keyIsFirstArgument,
|
||||
'ZREMRANGEBYSCORE' => $keyIsFirstArgument,
|
||||
'ZREVRANGE' => $keyIsFirstArgument,
|
||||
'ZREVRANGEBYSCORE' => $keyIsFirstArgument,
|
||||
'ZREVRANK' => $keyIsFirstArgument,
|
||||
'ZSCORE' => $keyIsFirstArgument,
|
||||
'ZUNIONSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
|
||||
'ZSCAN' => $keyIsFirstArgument,
|
||||
|
||||
/* commands operating on hashes */
|
||||
'HDEL' => $keyIsFirstArgument,
|
||||
'HEXISTS' => $keyIsFirstArgument,
|
||||
'HGET' => $keyIsFirstArgument,
|
||||
'HGETALL' => $keyIsFirstArgument,
|
||||
'HMGET' => $keyIsFirstArgument,
|
||||
'HMSET' => $keyIsFirstArgument,
|
||||
'HINCRBY' => $keyIsFirstArgument,
|
||||
'HINCRBYFLOAT' => $keyIsFirstArgument,
|
||||
'HKEYS' => $keyIsFirstArgument,
|
||||
'HLEN' => $keyIsFirstArgument,
|
||||
'HSET' => $keyIsFirstArgument,
|
||||
'HSETNX' => $keyIsFirstArgument,
|
||||
'HVALS' => $keyIsFirstArgument,
|
||||
'HSCAN' => $keyIsFirstArgument,
|
||||
|
||||
/* scripting */
|
||||
'EVAL' => array($this, 'getKeyFromScriptingCommands'),
|
||||
'EVALSHA' => array($this, 'getKeyFromScriptingCommands'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of IDs for the supported commands.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSupportedCommands()
|
||||
{
|
||||
return array_keys($this->commands);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an handler for the specified command ID.
|
||||
*
|
||||
* The signature of the callback must have a single parameter
|
||||
* of type Predis\Command\CommandInterface.
|
||||
*
|
||||
* When the callback argument is omitted or NULL, the previously
|
||||
* associated handler for the specified command ID is removed.
|
||||
*
|
||||
* @param string $commandId The ID of the command to be handled.
|
||||
* @param mixed $callback A valid callable object or NULL.
|
||||
*/
|
||||
public function setCommandHandler($commandId, $callback = null)
|
||||
{
|
||||
$commandId = strtoupper($commandId);
|
||||
|
||||
if (!isset($callback)) {
|
||||
unset($this->commands[$commandId]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_callable($callback)) {
|
||||
throw new \InvalidArgumentException("Callback must be a valid callable object or NULL");
|
||||
}
|
||||
|
||||
$this->commands[$commandId] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from the first argument of a command instance.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromFirstArgument(CommandInterface $command)
|
||||
{
|
||||
return $command->getArgument(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from a command with multiple keys only when all keys
|
||||
* in the arguments array produce the same hash.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromAllArguments(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
|
||||
if ($this->checkSameHashForKeys($arguments)) {
|
||||
return $arguments[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from a command with multiple keys only when all keys
|
||||
* in the arguments array produce the same hash.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromInterleavedArguments(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
$keys = array();
|
||||
|
||||
for ($i = 0; $i < count($arguments); $i += 2) {
|
||||
$keys[] = $arguments[$i];
|
||||
}
|
||||
|
||||
if ($this->checkSameHashForKeys($keys)) {
|
||||
return $arguments[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from BLPOP and BRPOP commands.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromBlockingListCommands(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
|
||||
if ($this->checkSameHashForKeys(array_slice($arguments, 0, count($arguments) - 1))) {
|
||||
return $arguments[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from BITOP command.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromBitOp(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
|
||||
if ($this->checkSameHashForKeys(array_slice($arguments, 1, count($arguments)))) {
|
||||
return $arguments[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from ZINTERSTORE and ZUNIONSTORE commands.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromZsetAggregationCommands(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
$keys = array_merge(array($arguments[0]), array_slice($arguments, 2, $arguments[1]));
|
||||
|
||||
if ($this->checkSameHashForKeys($keys)) {
|
||||
return $arguments[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from EVAL and EVALSHA commands.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromScriptingCommands(CommandInterface $command)
|
||||
{
|
||||
if ($command instanceof ScriptedCommand) {
|
||||
$keys = $command->getKeys();
|
||||
} else {
|
||||
$keys = array_slice($args = $command->getArguments(), 2, $args[1]);
|
||||
}
|
||||
|
||||
if ($keys && $this->checkSameHashForKeys($keys)) {
|
||||
return $keys[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHash(CommandInterface $command)
|
||||
{
|
||||
$hash = $command->getHash();
|
||||
|
||||
if (!isset($hash) && isset($this->commands[$cmdID = $command->getId()])) {
|
||||
$key = call_user_func($this->commands[$cmdID], $command);
|
||||
|
||||
if (isset($key)) {
|
||||
$hash = $this->getKeyHash($key);
|
||||
$command->setHash($hash);
|
||||
}
|
||||
}
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getKeyHash($key)
|
||||
{
|
||||
$key = $this->extractKeyTag($key);
|
||||
$hash = $this->hashGenerator->hash($key);
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified array of keys will generate the same hash.
|
||||
*
|
||||
* @param array $keys Array of keys.
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkSameHashForKeys(Array $keys)
|
||||
{
|
||||
if (!$count = count($keys)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$currentKey = $this->extractKeyTag($keys[0]);
|
||||
|
||||
for ($i = 1; $i < $count; $i++) {
|
||||
$nextKey = $this->extractKeyTag($keys[$i]);
|
||||
|
||||
if ($currentKey !== $nextKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$currentKey = $nextKey;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns only the hashable part of a key (delimited by "{...}"), or the
|
||||
* whole key if a key tag is not found in the string.
|
||||
*
|
||||
* @param string $key A key.
|
||||
* @return string
|
||||
*/
|
||||
protected function extractKeyTag($key)
|
||||
{
|
||||
if (false !== $start = strpos($key, '{')) {
|
||||
if (false !== $end = strpos($key, '}', $start)) {
|
||||
$key = substr($key, ++$start, $end - $start);
|
||||
}
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
292
Predis/Cluster/RedisClusterHashStrategy.php
Normal file
292
Predis/Cluster/RedisClusterHashStrategy.php
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
<?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\Cluster;
|
||||
|
||||
use Predis\Cluster\Hash\CRC16HashGenerator;
|
||||
use Predis\Command\CommandInterface;
|
||||
use Predis\Command\ScriptedCommand;
|
||||
|
||||
/**
|
||||
* Default class used by Predis to calculate hashes out of keys of
|
||||
* commands supported by redis-cluster.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class RedisClusterHashStrategy implements CommandHashStrategyInterface
|
||||
{
|
||||
private $commands;
|
||||
private $hashGenerator;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->commands = $this->getDefaultCommands();
|
||||
$this->hashGenerator = new CRC16HashGenerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default map of supported commands with their handlers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getDefaultCommands()
|
||||
{
|
||||
$keyIsFirstArgument = array($this, 'getKeyFromFirstArgument');
|
||||
|
||||
return array(
|
||||
/* commands operating on the key space */
|
||||
'EXISTS' => $keyIsFirstArgument,
|
||||
'DEL' => array($this, 'getKeyFromAllArguments'),
|
||||
'TYPE' => $keyIsFirstArgument,
|
||||
'EXPIRE' => $keyIsFirstArgument,
|
||||
'EXPIREAT' => $keyIsFirstArgument,
|
||||
'PERSIST' => $keyIsFirstArgument,
|
||||
'PEXPIRE' => $keyIsFirstArgument,
|
||||
'PEXPIREAT' => $keyIsFirstArgument,
|
||||
'TTL' => $keyIsFirstArgument,
|
||||
'PTTL' => $keyIsFirstArgument,
|
||||
'SORT' => $keyIsFirstArgument, // TODO
|
||||
|
||||
/* commands operating on string values */
|
||||
'APPEND' => $keyIsFirstArgument,
|
||||
'DECR' => $keyIsFirstArgument,
|
||||
'DECRBY' => $keyIsFirstArgument,
|
||||
'GET' => $keyIsFirstArgument,
|
||||
'GETBIT' => $keyIsFirstArgument,
|
||||
'MGET' => array($this, 'getKeyFromAllArguments'),
|
||||
'SET' => $keyIsFirstArgument,
|
||||
'GETRANGE' => $keyIsFirstArgument,
|
||||
'GETSET' => $keyIsFirstArgument,
|
||||
'INCR' => $keyIsFirstArgument,
|
||||
'INCRBY' => $keyIsFirstArgument,
|
||||
'SETBIT' => $keyIsFirstArgument,
|
||||
'SETEX' => $keyIsFirstArgument,
|
||||
'MSET' => array($this, 'getKeyFromInterleavedArguments'),
|
||||
'MSETNX' => array($this, 'getKeyFromInterleavedArguments'),
|
||||
'SETNX' => $keyIsFirstArgument,
|
||||
'SETRANGE' => $keyIsFirstArgument,
|
||||
'STRLEN' => $keyIsFirstArgument,
|
||||
'SUBSTR' => $keyIsFirstArgument,
|
||||
'BITCOUNT' => $keyIsFirstArgument,
|
||||
|
||||
/* commands operating on lists */
|
||||
'LINSERT' => $keyIsFirstArgument,
|
||||
'LINDEX' => $keyIsFirstArgument,
|
||||
'LLEN' => $keyIsFirstArgument,
|
||||
'LPOP' => $keyIsFirstArgument,
|
||||
'RPOP' => $keyIsFirstArgument,
|
||||
'BLPOP' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'BRPOP' => array($this, 'getKeyFromBlockingListCommands'),
|
||||
'LPUSH' => $keyIsFirstArgument,
|
||||
'LPUSHX' => $keyIsFirstArgument,
|
||||
'RPUSH' => $keyIsFirstArgument,
|
||||
'RPUSHX' => $keyIsFirstArgument,
|
||||
'LRANGE' => $keyIsFirstArgument,
|
||||
'LREM' => $keyIsFirstArgument,
|
||||
'LSET' => $keyIsFirstArgument,
|
||||
'LTRIM' => $keyIsFirstArgument,
|
||||
|
||||
/* commands operating on sets */
|
||||
'SADD' => $keyIsFirstArgument,
|
||||
'SCARD' => $keyIsFirstArgument,
|
||||
'SISMEMBER' => $keyIsFirstArgument,
|
||||
'SMEMBERS' => $keyIsFirstArgument,
|
||||
'SSCAN' => $keyIsFirstArgument,
|
||||
'SPOP' => $keyIsFirstArgument,
|
||||
'SRANDMEMBER' => $keyIsFirstArgument,
|
||||
'SREM' => $keyIsFirstArgument,
|
||||
|
||||
/* commands operating on sorted sets */
|
||||
'ZADD' => $keyIsFirstArgument,
|
||||
'ZCARD' => $keyIsFirstArgument,
|
||||
'ZCOUNT' => $keyIsFirstArgument,
|
||||
'ZINCRBY' => $keyIsFirstArgument,
|
||||
'ZRANGE' => $keyIsFirstArgument,
|
||||
'ZRANGEBYSCORE' => $keyIsFirstArgument,
|
||||
'ZRANK' => $keyIsFirstArgument,
|
||||
'ZREM' => $keyIsFirstArgument,
|
||||
'ZREMRANGEBYRANK' => $keyIsFirstArgument,
|
||||
'ZREMRANGEBYSCORE' => $keyIsFirstArgument,
|
||||
'ZREVRANGE' => $keyIsFirstArgument,
|
||||
'ZREVRANGEBYSCORE' => $keyIsFirstArgument,
|
||||
'ZREVRANK' => $keyIsFirstArgument,
|
||||
'ZSCORE' => $keyIsFirstArgument,
|
||||
'ZSCAN' => $keyIsFirstArgument,
|
||||
|
||||
/* commands operating on hashes */
|
||||
'HDEL' => $keyIsFirstArgument,
|
||||
'HEXISTS' => $keyIsFirstArgument,
|
||||
'HGET' => $keyIsFirstArgument,
|
||||
'HGETALL' => $keyIsFirstArgument,
|
||||
'HMGET' => $keyIsFirstArgument,
|
||||
'HMSET' => $keyIsFirstArgument,
|
||||
'HINCRBY' => $keyIsFirstArgument,
|
||||
'HINCRBYFLOAT' => $keyIsFirstArgument,
|
||||
'HKEYS' => $keyIsFirstArgument,
|
||||
'HLEN' => $keyIsFirstArgument,
|
||||
'HSET' => $keyIsFirstArgument,
|
||||
'HSETNX' => $keyIsFirstArgument,
|
||||
'HVALS' => $keyIsFirstArgument,
|
||||
'HSCAN' => $keyIsFirstArgument,
|
||||
|
||||
/* scripting */
|
||||
'EVAL' => array($this, 'getKeyFromScriptingCommands'),
|
||||
'EVALSHA' => array($this, 'getKeyFromScriptingCommands'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of IDs for the supported commands.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSupportedCommands()
|
||||
{
|
||||
return array_keys($this->commands);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an handler for the specified command ID.
|
||||
*
|
||||
* The signature of the callback must have a single parameter
|
||||
* of type Predis\Command\CommandInterface.
|
||||
*
|
||||
* When the callback argument is omitted or NULL, the previously
|
||||
* associated handler for the specified command ID is removed.
|
||||
*
|
||||
* @param string $commandId The ID of the command to be handled.
|
||||
* @param mixed $callback A valid callable object or NULL.
|
||||
*/
|
||||
public function setCommandHandler($commandId, $callback = null)
|
||||
{
|
||||
$commandId = strtoupper($commandId);
|
||||
|
||||
if (!isset($callback)) {
|
||||
unset($this->commands[$commandId]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_callable($callback)) {
|
||||
throw new \InvalidArgumentException("Callback must be a valid callable object or NULL");
|
||||
}
|
||||
|
||||
$this->commands[$commandId] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from the first argument of a command instance.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromFirstArgument(CommandInterface $command)
|
||||
{
|
||||
return $command->getArgument(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from a command that can accept multiple keys ensuring
|
||||
* that only one key is actually specified to comply with redis-cluster.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromAllArguments(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
|
||||
if (count($arguments) === 1) {
|
||||
return $arguments[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from a command that can accept multiple keys ensuring
|
||||
* that only one key is actually specified to comply with redis-cluster.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromInterleavedArguments(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
|
||||
if (count($arguments) === 2) {
|
||||
return $arguments[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from BLPOP and BRPOP commands ensuring that only one key
|
||||
* is actually specified to comply with redis-cluster.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromBlockingListCommands(CommandInterface $command)
|
||||
{
|
||||
$arguments = $command->getArguments();
|
||||
|
||||
if (count($arguments) === 2) {
|
||||
return $arguments[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the key from EVAL and EVALSHA commands.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @return string
|
||||
*/
|
||||
protected function getKeyFromScriptingCommands(CommandInterface $command)
|
||||
{
|
||||
if ($command instanceof ScriptedCommand) {
|
||||
$keys = $command->getKeys();
|
||||
} else {
|
||||
$keys = array_slice($args = $command->getArguments(), 2, $args[1]);
|
||||
}
|
||||
|
||||
if (count($keys) === 1) {
|
||||
return $keys[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHash(CommandInterface $command)
|
||||
{
|
||||
$hash = $command->getHash();
|
||||
|
||||
if (!isset($hash) && isset($this->commands[$cmdID = $command->getId()])) {
|
||||
$key = call_user_func($this->commands[$cmdID], $command);
|
||||
|
||||
if (isset($key)) {
|
||||
$hash = $this->hashGenerator->hash($key);
|
||||
$command->setHash($hash);
|
||||
}
|
||||
}
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getKeyHash($key)
|
||||
{
|
||||
return $this->hashGenerator->hash($key);
|
||||
}
|
||||
}
|
||||
189
Predis/Collection/Iterator/CursorBasedIterator.php
Normal file
189
Predis/Collection/Iterator/CursorBasedIterator.php
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
<?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\Collection\Iterator;
|
||||
|
||||
use Iterator;
|
||||
use Predis\ClientInterface;
|
||||
use Predis\NotSupportedException;
|
||||
|
||||
/**
|
||||
* Provides the base implementation for a fully-rewindable PHP iterator
|
||||
* that can incrementally iterate over cursor-based collections stored
|
||||
* on Redis using commands in the `SCAN` family.
|
||||
*
|
||||
* Given their incremental nature with multiple fetches, these kind of
|
||||
* iterators offer limited guarantees about the returned elements because
|
||||
* the collection 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
|
||||
{
|
||||
protected $client;
|
||||
protected $match;
|
||||
protected $count;
|
||||
|
||||
protected $valid;
|
||||
protected $fetchmore;
|
||||
protected $elements;
|
||||
protected $cursor;
|
||||
protected $position;
|
||||
protected $current;
|
||||
|
||||
/**
|
||||
* @param ClientInterface $client Client connected to Redis.
|
||||
* @param string $match Pattern to match during the server-side iteration.
|
||||
* @param int $count Hints used by Redis to compute the number of results per iteration.
|
||||
*/
|
||||
public function __construct(ClientInterface $client, $match = null, $count = null)
|
||||
{
|
||||
$this->client = $client;
|
||||
$this->match = $match;
|
||||
$this->count = $count;
|
||||
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the client instance supports the specified Redis
|
||||
* command required to fetch elements from the server to perform
|
||||
* the iteration.
|
||||
*
|
||||
* @param ClientInterface $client Client connected to Redis.
|
||||
* @param string $commandID Command ID.
|
||||
*/
|
||||
protected function requiredCommand(ClientInterface $client, $commandID)
|
||||
{
|
||||
if (!$client->getProfile()->supportsCommand($commandID)) {
|
||||
throw new NotSupportedException("The specified server profile does not support the `$commandID` command.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the inner state of the iterator.
|
||||
*/
|
||||
protected function reset()
|
||||
{
|
||||
$this->valid = true;
|
||||
$this->fetchmore = true;
|
||||
$this->elements = array();
|
||||
$this->cursor = 0;
|
||||
$this->position = -1;
|
||||
$this->current = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of options for the `SCAN` command.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getScanOptions()
|
||||
{
|
||||
$options = array();
|
||||
|
||||
if (strlen($this->match) > 0) {
|
||||
$options['MATCH'] = $this->match;
|
||||
}
|
||||
|
||||
if ($this->count > 0) {
|
||||
$options['COUNT'] = $this->count;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a new set of elements from the remote collection,
|
||||
* effectively advancing the iteration process.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function executeCommand();
|
||||
|
||||
/**
|
||||
* Populates the local buffer of elements fetched from the
|
||||
* server during the iteration.
|
||||
*/
|
||||
protected function fetch()
|
||||
{
|
||||
list($cursor, $elements) = $this->executeCommand();
|
||||
|
||||
if (!$cursor) {
|
||||
$this->fetchmore = false;
|
||||
}
|
||||
|
||||
$this->cursor = $cursor;
|
||||
$this->elements = $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts next values for key() and current().
|
||||
*/
|
||||
protected function extractNext()
|
||||
{
|
||||
$this->position++;
|
||||
$this->current = array_shift($this->elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
$this->reset();
|
||||
$this->next();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return $this->current;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
if (!$this->elements && $this->fetchmore) {
|
||||
$this->fetch();
|
||||
}
|
||||
|
||||
if ($this->elements) {
|
||||
$this->extractNext();
|
||||
} elseif ($this->cursor) {
|
||||
$this->next();
|
||||
} else {
|
||||
$this->valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return $this->valid;
|
||||
}
|
||||
}
|
||||
56
Predis/Collection/Iterator/HashKey.php
Normal file
56
Predis/Collection/Iterator/HashKey.php
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<?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\Collection\Iterator;
|
||||
|
||||
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
|
||||
*/
|
||||
class HashKey extends CursorBasedIterator
|
||||
{
|
||||
protected $key;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(ClientInterface $client, $key, $match = null, $count = null)
|
||||
{
|
||||
$this->requiredCommand($client, 'HSCAN');
|
||||
|
||||
parent::__construct($client, $match, $count);
|
||||
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function executeCommand()
|
||||
{
|
||||
return $this->client->hscan($this->key, $this->cursor, $this->getScanOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function extractNext()
|
||||
{
|
||||
$this->position = key($this->elements);
|
||||
$this->current = array_shift($this->elements);
|
||||
}
|
||||
}
|
||||
43
Predis/Collection/Iterator/Keyspace.php
Normal file
43
Predis/Collection/Iterator/Keyspace.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?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\Collection\Iterator;
|
||||
|
||||
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
|
||||
*/
|
||||
class Keyspace extends CursorBasedIterator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(ClientInterface $client, $match = null, $count = null)
|
||||
{
|
||||
$this->requiredCommand($client, 'SCAN');
|
||||
|
||||
parent::__construct($client, $match, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function executeCommand()
|
||||
{
|
||||
return $this->client->scan($this->cursor, $this->getScanOptions());
|
||||
}
|
||||
}
|
||||
174
Predis/Collection/Iterator/ListKey.php
Normal file
174
Predis/Collection/Iterator/ListKey.php
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
<?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\Collection\Iterator;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Iterator;
|
||||
use Predis\ClientInterface;
|
||||
use Predis\NotSupportedException;
|
||||
|
||||
/**
|
||||
* Abstracts the iteration of items stored in a list by leveraging the LRANGE
|
||||
* command wrapped in a fully-rewindable PHP iterator.
|
||||
*
|
||||
* This iterator tries to emulate the behaviour of cursor-based iterators based
|
||||
* on the SCAN-family of commands introduced in Redis <= 2.8, meaning that due
|
||||
* to its incremental nature with multiple fetches it can only offer limited
|
||||
* 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
|
||||
*/
|
||||
class ListKey implements Iterator
|
||||
{
|
||||
protected $client;
|
||||
protected $count;
|
||||
protected $key;
|
||||
|
||||
protected $valid;
|
||||
protected $fetchmore;
|
||||
protected $elements;
|
||||
protected $position;
|
||||
protected $current;
|
||||
|
||||
/**
|
||||
* @param ClientInterface $client Client connected to Redis.
|
||||
* @param string $key Redis list key.
|
||||
* @param int $count Number of items retrieved on each fetch operation.
|
||||
*/
|
||||
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.');
|
||||
}
|
||||
|
||||
$this->client = $client;
|
||||
$this->key = $key;
|
||||
$this->count = $count;
|
||||
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the client instance supports the specified Redis
|
||||
* command required to fetch elements from the server to perform
|
||||
* the iteration.
|
||||
*
|
||||
* @param ClientInterface $client Client connected to Redis.
|
||||
* @param string $commandID Command ID.
|
||||
*/
|
||||
protected function requiredCommand(ClientInterface $client, $commandID)
|
||||
{
|
||||
if (!$client->getProfile()->supportsCommand($commandID)) {
|
||||
throw new NotSupportedException("The specified server profile does not support the `$commandID` command.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the inner state of the iterator.
|
||||
*/
|
||||
protected function reset()
|
||||
{
|
||||
$this->valid = true;
|
||||
$this->fetchmore = true;
|
||||
$this->elements = array();
|
||||
$this->position = -1;
|
||||
$this->current = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a new set of elements from the remote collection,
|
||||
* effectively advancing the iteration process.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function executeCommand()
|
||||
{
|
||||
return $this->client->lrange($this->key, $this->position + 1, $this->position + $this->count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the local buffer of elements fetched from the
|
||||
* server during the iteration.
|
||||
*/
|
||||
protected function fetch()
|
||||
{
|
||||
$elements = $this->executeCommand();
|
||||
|
||||
if (count($elements) < $this->count) {
|
||||
$this->fetchmore = false;
|
||||
}
|
||||
|
||||
$this->elements = $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts next values for key() and current().
|
||||
*/
|
||||
protected function extractNext()
|
||||
{
|
||||
$this->position++;
|
||||
$this->current = array_shift($this->elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
$this->reset();
|
||||
$this->next();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return $this->current;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
if (!$this->elements && $this->fetchmore) {
|
||||
$this->fetch();
|
||||
}
|
||||
|
||||
if ($this->elements) {
|
||||
$this->extractNext();
|
||||
} else {
|
||||
$this->valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return $this->valid;
|
||||
}
|
||||
}
|
||||
47
Predis/Collection/Iterator/SetKey.php
Normal file
47
Predis/Collection/Iterator/SetKey.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?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\Collection\Iterator;
|
||||
|
||||
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
|
||||
*/
|
||||
class SetKey extends CursorBasedIterator
|
||||
{
|
||||
protected $key;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(ClientInterface $client, $key, $match = null, $count = null)
|
||||
{
|
||||
$this->requiredCommand($client, 'SSCAN');
|
||||
|
||||
parent::__construct($client, $match, $count);
|
||||
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function executeCommand()
|
||||
{
|
||||
return $this->client->sscan($this->key, $this->cursor, $this->getScanOptions());
|
||||
}
|
||||
}
|
||||
58
Predis/Collection/Iterator/SortedSetKey.php
Normal file
58
Predis/Collection/Iterator/SortedSetKey.php
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?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\Collection\Iterator;
|
||||
|
||||
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
|
||||
*/
|
||||
class SortedSetKey extends CursorBasedIterator
|
||||
{
|
||||
protected $key;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(ClientInterface $client, $key, $match = null, $count = null)
|
||||
{
|
||||
$this->requiredCommand($client, 'ZSCAN');
|
||||
|
||||
parent::__construct($client, $match, $count);
|
||||
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function executeCommand()
|
||||
{
|
||||
return $this->client->zscan($this->key, $this->cursor, $this->getScanOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function extractNext()
|
||||
{
|
||||
$element = array_shift($this->elements);
|
||||
|
||||
$this->position = $element[0];
|
||||
$this->current = $element[1];
|
||||
}
|
||||
}
|
||||
158
Predis/Command/AbstractCommand.php
Normal file
158
Predis/Command/AbstractCommand.php
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Base class for Redis commands.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
abstract class AbstractCommand implements CommandInterface
|
||||
{
|
||||
private $hash;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(Array $arguments)
|
||||
{
|
||||
$this->arguments = $this->filterArguments($arguments);
|
||||
unset($this->hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRawArguments(Array $arguments)
|
||||
{
|
||||
$this->arguments = $arguments;
|
||||
unset($this->hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArgument($index)
|
||||
{
|
||||
if (isset($this->arguments[$index])) {
|
||||
return $this->arguments[$index];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setHash($hash)
|
||||
{
|
||||
$this->hash = $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHash()
|
||||
{
|
||||
if (isset($this->hash)) {
|
||||
return $this->hash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function used to reduce a list of arguments to a string.
|
||||
*
|
||||
* @param string $accumulator Temporary string.
|
||||
* @param string $argument Current argument.
|
||||
* @return string
|
||||
*/
|
||||
protected function toStringArgumentReducer($accumulator, $argument)
|
||||
{
|
||||
if (strlen($argument) > 32) {
|
||||
$argument = substr($argument, 0, 32) . '[...]';
|
||||
}
|
||||
|
||||
$accumulator .= " $argument";
|
||||
|
||||
return $accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a partial string representation of the command with its arguments.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return array_reduce(
|
||||
$this->getArguments(),
|
||||
array($this, 'toStringArgumentReducer'),
|
||||
$this->getId()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the arguments array passed to a Redis command.
|
||||
*
|
||||
* @param array $arguments Arguments for a command.
|
||||
* @return array
|
||||
*/
|
||||
public static function normalizeArguments(Array $arguments)
|
||||
{
|
||||
if (count($arguments) === 1 && is_array($arguments[0])) {
|
||||
return $arguments[0];
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the arguments array passed to a variadic Redis command.
|
||||
*
|
||||
* @param array $arguments Arguments for a command.
|
||||
* @return array
|
||||
*/
|
||||
public static function normalizeVariadic(Array $arguments)
|
||||
{
|
||||
if (count($arguments) === 2 && is_array($arguments[1])) {
|
||||
return array_merge(array($arguments[0]), $arguments[1]);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
77
Predis/Command/CommandInterface.php
Normal file
77
Predis/Command/CommandInterface.php
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Defines an abstraction representing a Redis command.
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface CommandInterface
|
||||
{
|
||||
/**
|
||||
* Gets the ID of a Redis command.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId();
|
||||
|
||||
/**
|
||||
* Set the hash for the command.
|
||||
*
|
||||
* @param int $hash Calculated hash.
|
||||
*/
|
||||
public function setHash($hash);
|
||||
|
||||
/**
|
||||
* Returns the hash of the command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHash();
|
||||
|
||||
/**
|
||||
* Sets the arguments for the command.
|
||||
*
|
||||
* @param array $arguments List of arguments.
|
||||
*/
|
||||
public function setArguments(Array $arguments);
|
||||
|
||||
/**
|
||||
* Sets the raw arguments for the command without processing them.
|
||||
*
|
||||
* @param array $arguments List of arguments.
|
||||
*/
|
||||
public function setRawArguments(Array $arguments);
|
||||
|
||||
/**
|
||||
* Gets the arguments of the command.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getArguments();
|
||||
|
||||
/**
|
||||
* Gets the argument of the command at the specified index.
|
||||
*
|
||||
* @param int $index Index of the desired argument.
|
||||
* @return mixed
|
||||
*/
|
||||
public function getArgument($index);
|
||||
|
||||
/**
|
||||
* Parses a reply buffer and returns a PHP object.
|
||||
*
|
||||
* @param string $data Binary string containing the whole reply.
|
||||
* @return mixed
|
||||
*/
|
||||
public function parseResponse($data);
|
||||
}
|
||||
27
Predis/Command/ConnectionAuth.php
Normal file
27
Predis/Command/ConnectionAuth.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'AUTH';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ConnectionEcho.php
Normal file
27
Predis/Command/ConnectionEcho.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'ECHO';
|
||||
}
|
||||
}
|
||||
35
Predis/Command/ConnectionPing.php
Normal file
35
Predis/Command/ConnectionPing.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'PING';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return $data === 'PONG' ? true : false;
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ConnectionQuit.php
Normal file
27
Predis/Command/ConnectionQuit.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'QUIT';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ConnectionSelect.php
Normal file
27
Predis/Command/ConnectionSelect.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'SELECT';
|
||||
}
|
||||
}
|
||||
35
Predis/Command/HashDelete.php
Normal file
35
Predis/Command/HashDelete.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HDEL';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return self::normalizeVariadic($arguments);
|
||||
}
|
||||
}
|
||||
35
Predis/Command/HashExists.php
Normal file
35
Predis/Command/HashExists.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HEXISTS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
27
Predis/Command/HashGet.php
Normal file
27
Predis/Command/HashGet.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HGET';
|
||||
}
|
||||
}
|
||||
41
Predis/Command/HashGetAll.php
Normal file
41
Predis/Command/HashGetAll.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@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;
|
||||
}
|
||||
}
|
||||
35
Predis/Command/HashGetMultiple.php
Normal file
35
Predis/Command/HashGetMultiple.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HMGET';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return self::normalizeVariadic($arguments);
|
||||
}
|
||||
}
|
||||
27
Predis/Command/HashIncrementBy.php
Normal file
27
Predis/Command/HashIncrementBy.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HINCRBY';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/HashIncrementByFloat.php
Normal file
27
Predis/Command/HashIncrementByFloat.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HINCRBYFLOAT';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/HashKeys.php
Normal file
27
Predis/Command/HashKeys.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HKEYS';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/HashLength.php
Normal file
27
Predis/Command/HashLength.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HLEN';
|
||||
}
|
||||
}
|
||||
84
Predis/Command/HashScan.php
Normal file
84
Predis/Command/HashScan.php
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@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)) {
|
||||
$data[0] = (int) $data[0];
|
||||
$fields = $data[1];
|
||||
$result = array();
|
||||
|
||||
for ($i = 0; $i < count($fields); $i++) {
|
||||
$result[$fields[$i]] = $fields[++$i];
|
||||
}
|
||||
|
||||
$data[1] = $result;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
35
Predis/Command/HashSet.php
Normal file
35
Predis/Command/HashSet.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HSET';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
47
Predis/Command/HashSetMultiple.php
Normal file
47
Predis/Command/HashSetMultiple.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@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;
|
||||
}
|
||||
}
|
||||
35
Predis/Command/HashSetPreserve.php
Normal file
35
Predis/Command/HashSetPreserve.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HSETNX';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
27
Predis/Command/HashValues.php
Normal file
27
Predis/Command/HashValues.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'HVALS';
|
||||
}
|
||||
}
|
||||
43
Predis/Command/KeyDelete.php
Normal file
43
Predis/Command/KeyDelete.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?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 AbstractCommand implements PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'DEL';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return self::normalizeArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::all($this, $prefix);
|
||||
}
|
||||
}
|
||||
27
Predis/Command/KeyDump.php
Normal file
27
Predis/Command/KeyDump.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'DUMP';
|
||||
}
|
||||
}
|
||||
35
Predis/Command/KeyExists.php
Normal file
35
Predis/Command/KeyExists.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'EXISTS';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
35
Predis/Command/KeyExpire.php
Normal file
35
Predis/Command/KeyExpire.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'EXPIRE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
35
Predis/Command/KeyExpireAt.php
Normal file
35
Predis/Command/KeyExpireAt.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'EXPIREAT';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
27
Predis/Command/KeyKeys.php
Normal file
27
Predis/Command/KeyKeys.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'KEYS';
|
||||
}
|
||||
}
|
||||
28
Predis/Command/KeyKeysV12x.php
Normal file
28
Predis/Command/KeyKeysV12x.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?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>
|
||||
* @deprecated
|
||||
*/
|
||||
class KeyKeysV12x extends KeyKeys
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return explode(' ', $data);
|
||||
}
|
||||
}
|
||||
35
Predis/Command/KeyMove.php
Normal file
35
Predis/Command/KeyMove.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'MOVE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
35
Predis/Command/KeyPersist.php
Normal file
35
Predis/Command/KeyPersist.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'PERSIST';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return (bool) $data;
|
||||
}
|
||||
}
|
||||
27
Predis/Command/KeyPreciseExpire.php
Normal file
27
Predis/Command/KeyPreciseExpire.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/KeyPreciseExpireAt.php
Normal file
27
Predis/Command/KeyPreciseExpireAt.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/KeyPreciseTimeToLive.php
Normal file
27
Predis/Command/KeyPreciseTimeToLive.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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';
|
||||
}
|
||||
}
|
||||
35
Predis/Command/KeyRandom.php
Normal file
35
Predis/Command/KeyRandom.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RANDOMKEY';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return $data !== '' ? $data : null;
|
||||
}
|
||||
}
|
||||
35
Predis/Command/KeyRename.php
Normal file
35
Predis/Command/KeyRename.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 AbstractCommand implements PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RENAME';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::all($this, $prefix);
|
||||
}
|
||||
}
|
||||
35
Predis/Command/KeyRenamePreserve.php
Normal file
35
Predis/Command/KeyRenamePreserve.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
||||
27
Predis/Command/KeyRestore.php
Normal file
27
Predis/Command/KeyRestore.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RESTORE';
|
||||
}
|
||||
}
|
||||
76
Predis/Command/KeyScan.php
Normal file
76
Predis/Command/KeyScan.php
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
$data[0] = (int) $data[0];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
117
Predis/Command/KeySort.php
Normal file
117
Predis/Command/KeySort.php
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
<?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 AbstractCommand implements PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* {@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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
if ($arguments = $this->getArguments()) {
|
||||
$arguments[0] = "$prefix{$arguments[0]}";
|
||||
|
||||
if (($count = count($arguments)) > 1) {
|
||||
for ($i = 1; $i < $count; $i++) {
|
||||
switch ($arguments[$i]) {
|
||||
case 'BY':
|
||||
case 'STORE':
|
||||
$arguments[$i] = "$prefix{$arguments[++$i]}";
|
||||
break;
|
||||
|
||||
case 'GET':
|
||||
$value = $arguments[++$i];
|
||||
if ($value !== '#') {
|
||||
$arguments[$i] = "$prefix$value";
|
||||
}
|
||||
break;
|
||||
|
||||
case 'LIMIT';
|
||||
$i += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Predis/Command/KeyTimeToLive.php
Normal file
27
Predis/Command/KeyTimeToLive.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'TTL';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/KeyType.php
Normal file
27
Predis/Command/KeyType.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'TYPE';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListIndex.php
Normal file
27
Predis/Command/ListIndex.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LINDEX';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListInsert.php
Normal file
27
Predis/Command/ListInsert.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LINSERT';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListLength.php
Normal file
27
Predis/Command/ListLength.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LLEN';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListPopFirst.php
Normal file
27
Predis/Command/ListPopFirst.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LPOP';
|
||||
}
|
||||
}
|
||||
48
Predis/Command/ListPopFirstBlocking.php
Normal file
48
Predis/Command/ListPopFirstBlocking.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?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 AbstractCommand implements PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* {@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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::skipLast($this, $prefix);
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListPopLast.php
Normal file
27
Predis/Command/ListPopLast.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RPOP';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListPopLastBlocking.php
Normal file
27
Predis/Command/ListPopLastBlocking.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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';
|
||||
}
|
||||
}
|
||||
35
Predis/Command/ListPopLastPushHead.php
Normal file
35
Predis/Command/ListPopLastPushHead.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 AbstractCommand implements PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RPOPLPUSH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::all($this, $prefix);
|
||||
}
|
||||
}
|
||||
35
Predis/Command/ListPopLastPushHeadBlocking.php
Normal file
35
Predis/Command/ListPopLastPushHeadBlocking.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 AbstractCommand implements PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'BRPOPLPUSH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::skipLast($this, $prefix);
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListPushHead.php
Normal file
27
Predis/Command/ListPushHead.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListPushHeadX.php
Normal file
27
Predis/Command/ListPushHeadX.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LPUSHX';
|
||||
}
|
||||
}
|
||||
35
Predis/Command/ListPushTail.php
Normal file
35
Predis/Command/ListPushTail.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RPUSH';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return self::normalizeVariadic($arguments);
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListPushTailX.php
Normal file
27
Predis/Command/ListPushTailX.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'RPUSHX';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListRange.php
Normal file
27
Predis/Command/ListRange.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LRANGE';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListRemove.php
Normal file
27
Predis/Command/ListRemove.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LREM';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListSet.php
Normal file
27
Predis/Command/ListSet.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LSET';
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ListTrim.php
Normal file
27
Predis/Command/ListTrim.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'LTRIM';
|
||||
}
|
||||
}
|
||||
108
Predis/Command/PrefixHelpers.php
Normal file
108
Predis/Command/PrefixHelpers.php
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Class that defines a few helpers method for prefixing keys.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class PrefixHelpers
|
||||
{
|
||||
/**
|
||||
* Applies the specified prefix only the first argument.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function first(CommandInterface $command, $prefix)
|
||||
{
|
||||
if ($arguments = $command->getArguments()) {
|
||||
$arguments[0] = "$prefix{$arguments[0]}";
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified prefix to all the arguments.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function all(CommandInterface $command, $prefix)
|
||||
{
|
||||
if ($arguments = $command->getArguments()) {
|
||||
foreach ($arguments as &$key) {
|
||||
$key = "$prefix$key";
|
||||
}
|
||||
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified prefix only to even arguments in the list.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function interleaved(CommandInterface $command, $prefix)
|
||||
{
|
||||
if ($arguments = $command->getArguments()) {
|
||||
$length = count($arguments);
|
||||
|
||||
for ($i = 0; $i < $length; $i += 2) {
|
||||
$arguments[$i] = "$prefix{$arguments[$i]}";
|
||||
}
|
||||
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified prefix to all the arguments but the first one.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function skipFirst(CommandInterface $command, $prefix)
|
||||
{
|
||||
if ($arguments = $command->getArguments()) {
|
||||
$length = count($arguments);
|
||||
|
||||
for ($i = 1; $i < $length; $i++) {
|
||||
$arguments[$i] = "$prefix{$arguments[$i]}";
|
||||
}
|
||||
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified prefix to all the arguments but the last one.
|
||||
*
|
||||
* @param CommandInterface $command Command instance.
|
||||
* @param string $prefix Prefix string.
|
||||
*/
|
||||
public static function skipLast(CommandInterface $command, $prefix)
|
||||
{
|
||||
if ($arguments = $command->getArguments()) {
|
||||
$length = count($arguments);
|
||||
|
||||
for ($i = 0; $i < $length - 1; $i++) {
|
||||
$arguments[$i] = "$prefix{$arguments[$i]}";
|
||||
}
|
||||
|
||||
$command->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Predis/Command/PrefixableCommand.php
Normal file
31
Predis/Command/PrefixableCommand.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Base class for Redis commands with prefixable keys.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
abstract class PrefixableCommand extends AbstractCommand implements PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
if ($arguments = $this->getArguments()) {
|
||||
$arguments[0] = "$prefix{$arguments[0]}";
|
||||
$this->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Predis/Command/PrefixableCommandInterface.php
Normal file
27
Predis/Command/PrefixableCommandInterface.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Defines a command whose keys can be prefixed.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* Prefixes all the keys found in the arguments of the command.
|
||||
*
|
||||
* @param string $prefix String used to prefix the keys.
|
||||
*/
|
||||
public function prefixKeys($prefix);
|
||||
}
|
||||
34
Predis/Command/Processor/CommandProcessingInterface.php
Normal file
34
Predis/Command/Processor/CommandProcessingInterface.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?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\Processor;
|
||||
|
||||
/**
|
||||
* Defines an object that can process commands using command processors.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface CommandProcessingInterface
|
||||
{
|
||||
/**
|
||||
* Associates a command processor.
|
||||
*
|
||||
* @param CommandProcessorInterface $processor The command processor.
|
||||
*/
|
||||
public function setProcessor(CommandProcessorInterface $processor);
|
||||
|
||||
/**
|
||||
* Returns the associated command processor.
|
||||
*
|
||||
* @return CommandProcessorInterface
|
||||
*/
|
||||
public function getProcessor();
|
||||
}
|
||||
42
Predis/Command/Processor/CommandProcessorChainInterface.php
Normal file
42
Predis/Command/Processor/CommandProcessorChainInterface.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?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\Processor;
|
||||
|
||||
/**
|
||||
* A command processor chain processes a command using multiple chained command
|
||||
* processor before it is sent to Redis.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface CommandProcessorChainInterface extends CommandProcessorInterface, \IteratorAggregate, \Countable
|
||||
{
|
||||
/**
|
||||
* Adds a command processor.
|
||||
*
|
||||
* @param CommandProcessorInterface $processor A command processor.
|
||||
*/
|
||||
public function add(CommandProcessorInterface $processor);
|
||||
|
||||
/**
|
||||
* Removes a command processor from the chain.
|
||||
*
|
||||
* @param CommandProcessorInterface $processor A command processor.
|
||||
*/
|
||||
public function remove(CommandProcessorInterface $processor);
|
||||
|
||||
/**
|
||||
* Returns an ordered list of the command processors in the chain.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProcessors();
|
||||
}
|
||||
29
Predis/Command/Processor/CommandProcessorInterface.php
Normal file
29
Predis/Command/Processor/CommandProcessorInterface.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?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\Processor;
|
||||
|
||||
use Predis\Command\CommandInterface;
|
||||
|
||||
/**
|
||||
* A command processor processes commands before they are sent to Redis.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
interface CommandProcessorInterface
|
||||
{
|
||||
/**
|
||||
* Processes a Redis command.
|
||||
*
|
||||
* @param CommandInterface $command Redis command.
|
||||
*/
|
||||
public function process(CommandInterface $command);
|
||||
}
|
||||
72
Predis/Command/Processor/KeyPrefixProcessor.php
Normal file
72
Predis/Command/Processor/KeyPrefixProcessor.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?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\Processor;
|
||||
|
||||
use Predis\Command\CommandInterface;
|
||||
use Predis\Command\PrefixableCommandInterface;
|
||||
|
||||
/**
|
||||
* Command processor that is used to prefix the keys contained in the arguments
|
||||
* of a Redis command.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class KeyPrefixProcessor implements CommandProcessorInterface
|
||||
{
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* @param string $prefix Prefix for the keys.
|
||||
*/
|
||||
public function __construct($prefix)
|
||||
{
|
||||
$this->setPrefix($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a prefix that is applied to all the keys.
|
||||
*
|
||||
* @param string $prefix Prefix for the keys.
|
||||
*/
|
||||
public function setPrefix($prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current prefix.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPrefix()
|
||||
{
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(CommandInterface $command)
|
||||
{
|
||||
if ($command instanceof PrefixableCommandInterface && $command->getArguments()) {
|
||||
$command->prefixKeys($this->prefix);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getPrefix();
|
||||
}
|
||||
}
|
||||
130
Predis/Command/Processor/ProcessorChain.php
Normal file
130
Predis/Command/Processor/ProcessorChain.php
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
<?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\Processor;
|
||||
|
||||
use Predis\Command\CommandInterface;
|
||||
|
||||
/**
|
||||
* Default implementation of a command processors chain.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ProcessorChain implements CommandProcessorChainInterface, \ArrayAccess
|
||||
{
|
||||
private $processors = array();
|
||||
|
||||
/**
|
||||
* @param array $processors List of instances of CommandProcessorInterface.
|
||||
*/
|
||||
public function __construct($processors = array())
|
||||
{
|
||||
foreach ($processors as $processor) {
|
||||
$this->add($processor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add(CommandProcessorInterface $processor)
|
||||
{
|
||||
$this->processors[] = $processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function remove(CommandProcessorInterface $processor)
|
||||
{
|
||||
if (false !== $index = array_search($processor, $this->processors, true)) {
|
||||
unset($this[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(CommandInterface $command)
|
||||
{
|
||||
for ($i = 0; $i < $count = count($this->processors); $i++) {
|
||||
$this->processors[$i]->process($command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getProcessors()
|
||||
{
|
||||
return $this->processors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the list of command processor in the chain.
|
||||
*
|
||||
* @return \ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->processors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of command processors in the chain.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->processors);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetExists($index)
|
||||
{
|
||||
return isset($this->processors[$index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetGet($index)
|
||||
{
|
||||
return $this->processors[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetSet($index, $processor)
|
||||
{
|
||||
if (!$processor instanceof CommandProcessorInterface) {
|
||||
throw new \InvalidArgumentException(
|
||||
'A processor chain can hold only instances of classes implementing '.
|
||||
'the Predis\Command\Processor\CommandProcessorInterface interface'
|
||||
);
|
||||
}
|
||||
|
||||
$this->processors[$index] = $processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetUnset($index)
|
||||
{
|
||||
unset($this->processors[$index]);
|
||||
$this->processors = array_values($this->processors);
|
||||
}
|
||||
}
|
||||
27
Predis/Command/PubSubPublish.php
Normal file
27
Predis/Command/PubSubPublish.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 PrefixableCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'PUBLISH';
|
||||
}
|
||||
}
|
||||
43
Predis/Command/PubSubSubscribe.php
Normal file
43
Predis/Command/PubSubSubscribe.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?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 AbstractCommand implements PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'SUBSCRIBE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return self::normalizeArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::all($this, $prefix);
|
||||
}
|
||||
}
|
||||
27
Predis/Command/PubSubSubscribeByPattern.php
Normal file
27
Predis/Command/PubSubSubscribeByPattern.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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';
|
||||
}
|
||||
}
|
||||
43
Predis/Command/PubSubUnsubscribe.php
Normal file
43
Predis/Command/PubSubUnsubscribe.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?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 AbstractCommand implements PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'UNSUBSCRIBE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
return self::normalizeArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
PrefixHelpers::all($this, $prefix);
|
||||
}
|
||||
}
|
||||
27
Predis/Command/PubSubUnsubscribeByPattern.php
Normal file
27
Predis/Command/PubSubUnsubscribeByPattern.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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';
|
||||
}
|
||||
}
|
||||
157
Predis/Command/RawCommand.php
Normal file
157
Predis/Command/RawCommand.php
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
<?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;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class for generic "anonymous" Redis commands.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class RawCommand implements CommandInterface
|
||||
{
|
||||
private $hash;
|
||||
private $commandID;
|
||||
private $arguments;
|
||||
|
||||
public function __construct(array $arguments)
|
||||
{
|
||||
if (!$arguments) {
|
||||
throw new InvalidArgumentException("Arguments array is missing the command ID");
|
||||
}
|
||||
|
||||
$this->commandID = strtoupper(array_shift($arguments));
|
||||
$this->arguments = $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new raw command using a variadic method.
|
||||
*
|
||||
* @param string $commandID Redis command ID.
|
||||
* @param string ... Arguments list for the command.
|
||||
* @return CommandInterface
|
||||
*/
|
||||
public static function create($commandID /* [ $arg, ... */)
|
||||
{
|
||||
$arguments = func_get_args();
|
||||
$command = new self($arguments);
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->commandID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$this->arguments = $arguments;
|
||||
unset($this->hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRawArguments(array $arguments)
|
||||
{
|
||||
$this->setArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArgument($index)
|
||||
{
|
||||
if (isset($this->arguments[$index])) {
|
||||
return $this->arguments[$index];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setHash($hash)
|
||||
{
|
||||
$this->hash = $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHash()
|
||||
{
|
||||
if (isset($this->hash)) {
|
||||
return $this->hash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function used to reduce a list of arguments to a string.
|
||||
*
|
||||
* @param string $accumulator Temporary string.
|
||||
* @param string $argument Current argument.
|
||||
* @return string
|
||||
*/
|
||||
protected function toStringArgumentReducer($accumulator, $argument)
|
||||
{
|
||||
if (strlen($argument) > 32) {
|
||||
$argument = substr($argument, 0, 32) . '[...]';
|
||||
}
|
||||
|
||||
$accumulator .= " $argument";
|
||||
|
||||
return $accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a partial string representation of the command with its arguments.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return array_reduce(
|
||||
$this->getArguments(),
|
||||
array($this, 'toStringArgumentReducer'),
|
||||
$this->getId()
|
||||
);
|
||||
}
|
||||
}
|
||||
76
Predis/Command/ScriptedCommand.php
Normal file
76
Predis/Command/ScriptedCommand.php
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Base class used to implement an higher level abstraction for "virtual"
|
||||
* commands based on EVAL.
|
||||
*
|
||||
* @link http://redis.io/commands/eval
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
abstract class ScriptedCommand extends ServerEvalSHA
|
||||
{
|
||||
/**
|
||||
* Gets the body of a Lua script.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getScript();
|
||||
|
||||
/**
|
||||
* Specifies the number of arguments that should be considered as keys.
|
||||
*
|
||||
* The default behaviour for the base class is to return 0 to indicate that
|
||||
* all the elements of the arguments array should be considered as keys, but
|
||||
* subclasses can enforce a static number of keys.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getKeysCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the elements from the arguments that are identified as keys.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getKeys()
|
||||
{
|
||||
return array_slice($this->getArguments(), 2, $this->getKeysCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function filterArguments(Array $arguments)
|
||||
{
|
||||
if (($numkeys = $this->getKeysCount()) && $numkeys < 0) {
|
||||
$numkeys = count($arguments) + $numkeys;
|
||||
}
|
||||
|
||||
return array_merge(array(sha1($this->getScript()), (int) $numkeys), $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getEvalArguments()
|
||||
{
|
||||
$arguments = $this->getArguments();
|
||||
$arguments[0] = $this->getScript();
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
35
Predis/Command/ServerBackgroundRewriteAOF.php
Normal file
35
Predis/Command/ServerBackgroundRewriteAOF.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'BGREWRITEAOF';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return $data == 'Background append only file rewriting started';
|
||||
}
|
||||
}
|
||||
35
Predis/Command/ServerBackgroundSave.php
Normal file
35
Predis/Command/ServerBackgroundSave.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'BGSAVE';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parseResponse($data)
|
||||
{
|
||||
return $data === 'Background saving started' ? true : $data;
|
||||
}
|
||||
}
|
||||
73
Predis/Command/ServerClient.php
Normal file
73
Predis/Command/ServerClient.php
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@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 reply buffer and returns the list of clients returned by
|
||||
* the CLIENT LIST command.
|
||||
*
|
||||
* @param string $data Reply 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;
|
||||
}
|
||||
}
|
||||
48
Predis/Command/ServerConfig.php
Normal file
48
Predis/Command/ServerConfig.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@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;
|
||||
}
|
||||
}
|
||||
27
Predis/Command/ServerDatabaseSize.php
Normal file
27
Predis/Command/ServerDatabaseSize.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?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 AbstractCommand
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'DBSIZE';
|
||||
}
|
||||
}
|
||||
51
Predis/Command/ServerEval.php
Normal file
51
Predis/Command/ServerEval.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?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/eval
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerEval extends AbstractCommand implements PrefixableCommandInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'EVAL';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prefixKeys($prefix)
|
||||
{
|
||||
if ($arguments = $this->getArguments()) {
|
||||
for ($i = 2; $i < $arguments[1] + 2; $i++) {
|
||||
$arguments[$i] = "$prefix{$arguments[$i]}";
|
||||
}
|
||||
|
||||
$this->setRawArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the SHA1 hash of the body of the script.
|
||||
*
|
||||
* @return string SHA1 hash.
|
||||
*/
|
||||
public function getScriptHash()
|
||||
{
|
||||
return sha1($this->getArgument(0));
|
||||
}
|
||||
}
|
||||
37
Predis/Command/ServerEvalSHA.php
Normal file
37
Predis/Command/ServerEvalSHA.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?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/evalsha
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
*/
|
||||
class ServerEvalSHA extends ServerEval
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'EVALSHA';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SHA1 hash of the body of the script.
|
||||
*
|
||||
* @return string SHA1 hash.
|
||||
*/
|
||||
public function getScriptHash()
|
||||
{
|
||||
return $this->getArgument(0);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue