Compare commits

...

71 Commits

Author SHA1 Message Date
Daniele Alessandri 84060b9034 Update CHANGELOG and bump VERSION.
Hotfix release targeting a severe regression on HHVM, see commit d4a7bd5.
2015-07-30 20:34:15 +02:00
Daniele Alessandri d4a7bd52be Fix severe regression on HHVM.
Apparently HHVM is more strict than PHP in stream_socket_client() and does not
like at all IPv4 addresses and hostnames eclosed in square brackets. Note that
it is not that weird as square brackets are mandatory only when IPv6 addresses
are embedded in URI strings, so it is more like a weird incompatiblity of HHVM
with the behaviour of the standard PHP interpreter. The connect() attempt fails
but not due to the server being unavailable or some connectivity issue.

The important lesson is: never rely on undocumented behaviours especially when
targeting different runtimes, and do not forget to run the test suite on every
platform right before release like I unfortunately did.

This commit fixes #269.
2015-07-30 20:23:45 +02:00
Daniele Alessandri 16a9d4e041 Back to development.
[ci skip]
2015-07-30 19:41:27 +02:00
Daniele Alessandri 0b92e8d156 Update CHANGELOG and bump VERSION. 2015-07-30 11:20:39 +02:00
Daniele Alessandri 1f7b534072 Preserve remainder of path in URI after database (redis scheme). 2015-07-30 11:13:42 +02:00
Daniele Alessandri 0c0cbbafff Use PHP_VERSION_ID constant. 2015-07-30 10:56:54 +02:00
Daniele Alessandri 8aec51b34f Implement full support for IPv6.
Using IPv6 with Predis was basically impossible due to various inconsistencies
and bugs through the library, now it is supported by all the connection classes.

Following the standard for IPv6 literal addresses in URI strings, the IP literal
must be enclosed within square brackets when passing the parameters as a string:

  $parameters = 'tcp://[2001:db8:0:f101::1]:6379';

See https://tools.ietf.org/html/rfc3986#section-3.2.2 for further details.

This commit also fixes #239 making redis-cluster usable with nodes using IPv6.
2015-07-29 23:09:52 +02:00
Daniele Alessandri eeb1e8b7a7 Reduce unneeded code duplication in URI parsing. 2015-07-29 17:04:34 +02:00
Daniele Alessandri c3a44b8e2e Strip brackets from host when parsing embedded IPv6 address.
I don't know why PHP's parse_url() does not do that, it does not make
sense when the IP is by itself so maybe it is a bug?
2015-07-29 17:01:19 +02:00
Daniele Alessandri 255beac137 Use static:: for invoking static methods in key prefix processor.
This trivial change makes it possible to use overridden static methods
when extending Predis\Command\Processor\KeyPrefixProcessor. PHP always
invokes the static methods of a parent class when using self:: even if
the extended classes override them.
2015-07-29 14:16:52 +02:00
Daniele Alessandri d473328a22 Update CHANGELOG. 2015-07-29 11:54:08 +02:00
Daniele Alessandri 0d25e7b0bb Add new command: HSTRLEN (Redis 3.2.0).
Also bump the unstable profile version to 3.2.
2015-07-29 11:52:55 +02:00
Daniele Alessandri be3b84ca14 Rephrase latest entries in CHANGELOG by using intelligible English.
[ci skip]
2015-07-26 22:27:57 +02:00
Daniele Alessandri 7d0597c62c Rephrase some parts of the README.
[ci skip]
2015-07-26 22:27:49 +02:00
Daniele Alessandri 833e46b79d [tests] Fix typo. 2015-07-25 21:59:08 +02:00
Daniele Alessandri a22858438d [tests] Require pcntl extension to run blocking PubSub\Consumer test. 2015-07-25 21:58:01 +02:00
Daniele Alessandri f221d0c81e Run php-cs-fixer. 2015-07-25 21:27:05 +02:00
Daniele Alessandri 0b5bfdfe33 [tests] Improve code-reuse in tests for the Predis\Connection namespace. 2015-07-25 21:27:02 +02:00
Daniele Alessandri 3700d48771 [tests] Share common test among connection classes. 2015-07-25 20:54:01 +02:00
Daniele Alessandri 653d3f08ab [tests] Use @requires annotation. 2015-07-25 20:52:01 +02:00
Daniele Alessandri 2d2de7837b [tests] Fix some tests methods names. 2015-07-25 10:07:58 +02:00
Daniele Alessandri fc18e6456a [tests] Apply small changes to commands tests with expirations. 2015-07-25 10:07:55 +02:00
Daniele Alessandri 6f2064ed90 [tests] Cover SET modifiers EX, PX, NX|XX (Redis >= 2.6.12). 2015-07-25 09:11:16 +02:00
Daniele Alessandri e2e645a8bd Update .gitattributes file.
[ci skip]
2015-07-24 23:31:04 +02:00
Daniele Alessandri 2219964b7e Restore alignment for a few equals symbols. 2015-07-24 23:21:23 +02:00
Daniele Alessandri 381e44b6e6 Run php-cs-fixer with new configuration. 2015-07-24 23:21:07 +02:00
Daniele Alessandri 808693bfbd Add .php_cs configuration file for php-cs-fixer. 2015-07-24 23:19:23 +02:00
Daniele Alessandri 33eab38314 Remove unneeded "use" imports. 2015-07-24 21:25:48 +02:00
Daniele Alessandri 82e404660e Run php-cs-fixer against codebase in src/ and tests/. 2015-07-24 17:58:56 +02:00
Daniele Alessandri 6d60a42400 [tests] Fix me being stupid here. 2015-07-24 17:35:53 +02:00
Daniele Alessandri 95624de5c4 [tests] Apply some fixes and improvements and remove old stuff. 2015-07-24 17:27:41 +02:00
Daniele Alessandri 2ee135099c Remove useless if condition. 2015-07-24 12:40:33 +02:00
Daniele Alessandri e26e3b423a Reverting stupid oversight after a merge from master branch.
The culprit is commit 3500371.
2015-07-24 10:49:14 +02:00
Daniele Alessandri 946fac4454 No need to check the scheme here.
Bug introduced in v1.0-dev after changes to support redis scheme.

Fixes #268
2015-07-24 10:45:12 +02:00
Daniele Alessandri 4e976a3eb6 Update CHANGELOG.
[ci skip]
2015-07-23 21:05:05 +02:00
Daniele Alessandri baaf26fe5b Add support for the 'redis://' scheme in URI strings.
The URI string will be handled following the rules as described by the
the provisional IANA registration document that can be found on IANA's
website: http://www.iana.org/assignments/uri-schemes/prov/redis.
2015-07-23 19:21:16 +02:00
Daniele Alessandri 6a0348fbea Add missing command: MIGRATE (Redis 2.6.0).
Fixes #209.
2015-07-23 19:21:03 +02:00
Daniele Alessandri 8365a6be77 [tests] Fix minor oversight. 2015-07-23 19:20:52 +02:00
Daniele Alessandri f028e428be Switch to container-based builds on Travis CI.
We do not need "sudo" anyway.
See http://docs.travis-ci.com/user/migrating-from-legacy/ for details.
2015-07-23 12:16:27 +02:00
Daniele Alessandri c13b82557d Update CHANGELOG. 2015-07-23 11:43:47 +02:00
Daniele Alessandri 30d01c40d4 [tests] Improve assert failure messages for replication stategy tests. 2015-07-23 11:40:52 +02:00
Daniele Alessandri 6459546e25 Fix missing BITPOS in replication strategy. 2015-07-23 11:40:39 +02:00
Daniele Alessandri dede828008 Add missing BITPOS command in key prefix processor.
See #265.
2015-07-23 11:40:27 +02:00
Daniele Alessandri 5c0716575e Exclude .php-version file.
[ci skip]
2015-07-19 13:05:40 +02:00
Richard Heelin 90bffb1a5a Emit socket error if ipredis connection has been lost/reset.
The current code is checking for a failure (return false) or an empty buffer string, however
neither of these will be the case if the connection has been reset or has errored. According
to the docs for socket_recv, $buffer will be set to null if the connection is reset or their
is no data. As currently null is not allowed for, we enter an infinite loop, to prevent this
I've added null to the things we check before we emit a socket error. This prevents the
infinite loop and correctly results in an Exception if the connection is lost/reset.

Conflicts:
	src/Connection/PhpiredisSocketConnection.php
2015-07-07 18:51:44 +02:00
Daniele Alessandri 64ee96c312 [tests] Fix base test case class to handle required Redis versions.
This change is needed due to some internal changes in one of the
latest minor releases of PHPUnit 4.x that essentially broke how we
were checking for the required Redis version from method annotations.
2015-07-07 18:05:55 +02:00
Daniele Alessandri bff5a9729e Update CHANGELOG. 2015-07-07 16:19:46 +02:00
Daniele Alessandri 5cd7b774c4 [tests] Adapt to internal encoding changes for lists in Redis 3.0. 2015-07-07 16:11:49 +02:00
Daniele Alessandri 354d1ef921 Support ZADD modifiers when using simplified command signature.
The NX|XX, CH and INCR modifiers for ZADD are available in Redis since
version 3.0.2. See http://redis.io/commands/ZADD for additional info.
2015-07-07 16:11:43 +02:00
Daniele Alessandri 9e3a8da94d Update CHANGELOG. 2015-07-07 15:01:00 +02:00
Daniele Alessandri 35003713a2 Merge remote-tracking branch 'github/pr/235' into v1.0
Conflicts:
	.travis.yml
	CHANGELOG.md
	VERSION
	package.ini
	src/Client.php
2015-07-07 14:52:09 +02:00
Daniele Alessandri cd991e6370 [tests] Remove hhvm-nightly from Travis CI configuration.
See https://github.com/travis-ci/travis-ci/issues/3788 for details.
2015-07-07 14:44:28 +02:00
Daniele Alessandri c59853afb8 [tests] It's 7.0 and not 5.7! 2015-07-07 14:44:08 +02:00
Daniele Alessandri d4982b6c43 [tests] Add PHP 5.7 to Travis CI configuration. 2015-07-07 13:22:59 +02:00
Daniele Alessandri 96f4af816d Minor tweak in .editorconfig file.
[ci skip]
2015-07-06 18:42:10 +02:00
Daniele Alessandri 22ff3ff992 Commit .editorconfig file.
See http://editorconfig.org for more info about EditorConfig

[ci skip]
2015-07-06 18:38:30 +02:00
Daniele Alessandri 77b75e0738 Fix wrong phpdoc.
Thanks @Aliance for spotting this oversight.
2015-07-03 12:11:45 +02:00
Daniele Alessandri eeea28b275 Update CHANGELOG. 2015-07-03 12:10:44 +02:00
Daniele Alessandri aa067d8fd9 [tests] Implement test for #257 to guard against regressions. 2015-07-03 12:03:15 +02:00
Dominic Scheirlinck ce17c5383a Don't check for __invoke on non-objects
`method_exists` will cause autoloading for strings. Fixes #257
2015-07-03 11:11:53 +02:00
Daniele Alessandri c4c36cae7a Back to development. 2015-01-02 13:54:29 +01:00
Daniele Alessandri 7a170b3d81 Update CHANGELOG and bump VERSION. 2015-01-02 13:51:34 +01:00
Daniele Alessandri 17e7bce22e Bump year in LICENSE.
[ci skip]
2015-01-02 13:45:19 +01:00
Daniele Alessandri 7a5d6bac3e Update CHANGELOG.
[ci skip]
2015-01-02 13:42:50 +01:00
Daniele Alessandri 9d6c031ead Merge remote-tracking branch 'srhnsn/v1.0' into v1.0 2015-01-02 13:33:10 +01:00
Daniele Alessandri 692718afb4 Merge remote-tracking branch 'blocktrail/hhvm-pubsub-blockingread-test-v1.0' into v1.0 2015-01-02 13:00:25 +01:00
Daniele Alessandri 0776377412 Temporarily allow failures for HHVM on Travis-CI.
[ci skip]
2015-01-02 12:56:48 +01:00
Daniele Alessandri e4b0512d42 No need to access a private field used by PHPUnit.
Fixes #207.
2015-01-02 12:20:00 +01:00
Daniele Alessandri 75ca2f8111 Add minimum required Redis version for BITPOS integration tests. 2015-01-02 12:14:05 +01:00
Daniele Alessandri 37b1c88115 Apply minor CS fixes and trim spurious spaces. 2015-01-02 12:13:58 +01:00
Daniele Alessandri a4e6130568 Merge remote-tracking branch 'nicchap/v1.0' into v1.0 2015-01-02 11:58:30 +01:00
348 changed files with 4312 additions and 3534 deletions
+17
View File
@@ -0,0 +1,17 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
[*.php]
trim_trailing_whitespace = true
max_line_length = 120
[*.{md,yml}]
indent_size = 2
+2
View File
@@ -1,8 +1,10 @@
* text=auto
/tests export-ignore
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.php_cs export-ignore
/.travis.yml export-ignore
/phpunit.xml.dist export-ignore
/phpunit.xml.travisci export-ignore
+2
View File
@@ -1,5 +1,7 @@
*.tgz
*.phar
.php-version
.php_cs.cache
phpunit.xml
package.xml
composer.lock
+34
View File
@@ -0,0 +1,34 @@
<?php
$PREDIS_HEADER = <<<EOS
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.
EOS;
Symfony\CS\Fixer\Contrib\HeaderCommentFixer::setHeader($PREDIS_HEADER);
return Symfony\CS\Config\Config::create()
->setUsingCache(true)
->level(Symfony\CS\FixerInterface::SYMFONY_LEVEL)
->fixers(array(
// Symfony
'-unalign_equals',
'-unalign_double_arrow',
// Contribs
'header_comment',
'ordered_use',
'phpdoc_order',
'long_array_syntax',
))
->finder(
Symfony\CS\Finder\DefaultFinder::create()
->in(__DIR__.'/bin')
->in(__DIR__.'/src')
->in(__DIR__.'/tests')
->in(__DIR__.'/examples')
);
+2 -2
View File
@@ -1,11 +1,12 @@
language: php
sudo: false
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
- hhvm-nightly
branches:
except:
- v0.5
@@ -21,5 +22,4 @@ script:
matrix:
allow_failures:
- php: hhvm
- php: hhvm-nightly
fast_finish: true
+31
View File
@@ -1,3 +1,34 @@
v1.0.3 (2015-07-30)
================================================================================
- __FIX__: the previous release introduced a severe regression on HHVM that made
the library unable to connect to Redis when using IPv4 addresses. Code running
on the standard PHP interpreter is not affected.
v1.0.2 (2015-07-30)
================================================================================
- IPv6 is now fully supported.
- Added `redis` as an accepted scheme for connection parameters. When using this
scheme, the rules used to parse URI strings match the provisional registration
[published by IANA](http://www.iana.org/assignments/uri-schemes/prov/redis).
- Added new or missing commands: `HSTRLEN` (>= 3.2), `ZREVRANGEBYLEX` (>= 2.8)
and `MIGRATE` (>= 2.6).
- Implemented support for the `ZADD` modifiers `NX|XX`, `CH`, `INCR` (Redis >=
3.0.2) using the simplified signature where scores and members are passed as
a named array.
- __FIX__: `Predis\Configuration\Options` must not trigger the autoloader when
option values are strings (ISSUE #257).
- __FIX__: `BITPOS` was not defined in the key-prefix processor (ISSUE #265) and
in the replication strategy.
v1.0.1 (2015-01-02)
================================================================================
+75 -73
View File
@@ -3,30 +3,30 @@
[![Latest Stable Version](https://poser.pugx.org/predis/predis/v/stable.png)](https://packagist.org/packages/predis/predis)
[![Total Downloads](https://poser.pugx.org/predis/predis/downloads.png)](https://packagist.org/packages/predis/predis)
[![License](https://poser.pugx.org/predis/predis/license.svg)](https://packagist.org/packages/predis/predis)
[![Build Status](https://travis-ci.org/nrk/predis.svg?branch=master)](https://travis-ci.org/nrk/predis)
[![Build Status](https://travis-ci.org/nrk/predis.svg?branch=v1.0)](https://travis-ci.org/nrk/predis)
[![HHVM Status](http://hhvm.h4cc.de/badge/predis/predis.png)](http://hhvm.h4cc.de/package/predis/predis)
Predis is a flexible and feature-complete [Redis](http://redis.io) client library for PHP >= 5.3.
By default Predis does not require any additional C extension, but it can be optionally paired with
[phpiredis](https://github.com/nrk/phpiredis) to lower the overhead of serializing and parsing the
Redis protocol. An asynchronous implementation of the client, albeit experimental, is also available
through [Predis\Async](https://github.com/nrk/predis-async).
By default this library does not require any additional C extension, but it can be optionally paired
with [phpiredis](https://github.com/nrk/phpiredis) to lower the overhead of serializing and parsing
the [Redis RESP Protocol](http://redis.io/topics/protocol). An asynchronous implementation of Predis
is available through [Predis\Async](https://github.com/nrk/predis-async) (__experimental__).
Predis can be used with [HHVM](http://www.hhvm.com) >= 2.3.0, but there are no guarantees you will
Predis can be used with [HHVM](http://www.hhvm.com) >= 2.3.0 but there are no guarantees you will
not run into unexpected issues (especially when the JIT compiler is enabled via `Eval.Jit = true`)
due to HHVM being still under heavy development, thus unstable and not yet 100% compatible with PHP.
due to HHVM being still under heavy development and not yet 100% compatible with the _standard_ PHP.
More details about the project can be found in our [frequently asked questions](FAQ.md) section or
on the online [wiki](https://github.com/nrk/predis/wiki).
More details about this project can be found on the [frequently asked questions](FAQ.md) and on the
[wiki](https://github.com/nrk/predis/wiki).
## Main features ##
- Wide range of Redis versions supported (from __2.0__ to __3.0__ and __unstable__) using profiles.
- Cluster of nodes via client-side sharding using consistent hashing or custom distributors.
- Support for a wide range of Redis versions (from __2.0__ to __3.0__) using profiles.
- Clustering via client-side sharding using consistent hashing or custom distributors.
- Smart support for [redis-cluster](http://redis.io/topics/cluster-tutorial) (Redis >= 3.0).
- Support for master-slave replication configurations (write on master, read from slaves).
- Support for master-slave replication (write operations on master, read operations on slaves).
- Transparent key prefixing for all known Redis commands using a customizable prefixing strategy.
- Command pipelining (works on both single nodes and aggregate connections).
- Abstraction for Redis transactions (Redis >= 2.0) supporting CAS operations (Redis >= 2.2).
@@ -34,15 +34,15 @@ on the online [wiki](https://github.com/nrk/predis/wiki).
- Abstraction for `SCAN`, `SSCAN`, `ZSCAN` and `HSCAN` (Redis >= 2.8) based on PHP iterators.
- Connections to Redis are established lazily by the client upon the first command.
- Support for both TCP/IP and UNIX domain sockets and persistent connections.
- Support for [Webdis](http://webd.is) (both `ext-curl` and `ext-phpiredis` are needed).
- Support for [Webdis](http://webd.is) (requires both `ext-curl` and `ext-phpiredis`).
- Support for custom connection classes for providing different network or protocol backends.
- Flexible system for defining and registering custom sets of supported commands or profiles.
- Flexible system for defining custom commands and server profiles.
## How to use Predis ##
Predis is available on [Packagist](http://packagist.org/packages/predis/predis) which allows a quick
installation using [Composer](http://packagist.org/about-composer). Alternatively, the library can
_installation_ using [Composer](http://packagist.org/about-composer). Alternatively, the library can
be found on our [own PEAR channel](http://pear.nrk.io) for a more traditional installation via PEAR.
Ultimately, archives of each release are [available on GitHub](https://github.com/nrk/predis/tags).
@@ -61,17 +61,17 @@ require 'Predis/Autoloader.php';
Predis\Autoloader::register();
```
It is possible to easily create a [phar](http://www.php.net/manual/en/intro.phar.php) archive from
the repository just by launching `bin/create-phar`. The generated phar contains a stub defining an
autoloader function for Predis, so you just need to require the phar to start using the library.
Alternatively it is possible to generate one single PHP file holding every class like older versions
of Predis by launching `bin/create-single-file`, but this practice __is not__ encouraged.
It is possible to create a [phar](http://www.php.net/manual/en/intro.phar.php) archive directly from
the repository by launching `bin/create-phar`. The phar contains a stub defining its own autoloader
so you just need to `require()` it to start using the library. Ultimately it is possible to generate
a single big PHP file containing all the source code simply by launching `bin/create-single-file`,
but this practice __is not__ encouraged.
### Connecting to Redis ###
When not specifying any connection parameter to create a new client, Predis assumes `127.0.0.1` and
`6379` as the default host and port with a connection timeout of 5 seconds:
When creating a client instance without passing any connection parameter, Predis assumes `127.0.0.1`
and `6379` as default host and port. The default timeout for the `connect()` operation is 5 seconds:
```php
$client = new Predis\Client();
@@ -79,22 +79,28 @@ $client->set('foo', 'bar');
$value = $client->get('foo');
```
Connection parameters can be supplied either in the form of URI strings or named arrays. While the
latter is the preferred way to supply parameters, URI strings can be useful for quick configurations
or when parameters are read from a non-structured source:
Connection parameters can be supplied either in the form of URI strings or named arrays. The latter
is the preferred way to supply parameters, but URI strings can be useful when parameters are read
from non-structured or partially-structured sources:
```php
// Named array of connection parameters:
// Parameters passed using a named array:
$client = new Predis\Client([
'scheme' => 'tcp',
'host' => '10.0.0.1',
'port' => 6379,
]);
// Same set of parameters, but using an URI string:
// Same set of parameters, passed using an URI string:
$client = new Predis\Client('tcp://10.0.0.1:6379');
```
Starting with Predis v1.0.2 the client also understands the `redis` scheme in URI strings as defined
by the [provisional IANA registration](http://www.iana.org/assignments/uri-schemes/prov/redis).
The actual list of supported connection parameters can vary depending on each connection backend so
it is recommended to refer to their specific documentation or implementation for details.
When an array of connection parameters is provided, Predis automatically works in cluster mode using
client-side sharding. Both named arrays and URI strings can be mixed when providing configurations
for each node:
@@ -106,8 +112,7 @@ $client = new Predis\Client([
]);
```
The actual list of supported connection parameters can vary depending on each connection backend so
it is recommended to refer to their specific documentation or implementation for details.
See the [aggregate connections](#aggregate-connections) section of this document for more details.
### Client configuration ###
@@ -116,14 +121,11 @@ Various aspects of the client can be configured simply by passing options to the
`Predis\Client::__construct()`:
```php
$client = new \Predis\Client(
$connection_parameters,
['profile' => '2.8', 'prefix' => 'sample:']
);
$client = new Predis\Client($parameters, ['profile' => '2.8', 'prefix' => 'sample:']);
```
Options are managed using a mini DI-alike container and their values
are usually lazily initialized only when needed. Predis by default supports the following options:
Options are managed through a mini DI-alike container while their values can be lazily initialized
only when needed. This is a list of the options supported by default:
- `profile`: which profile to use in order to match a specific version of Redis.
- `prefix`: a prefix string that is automatically applied to keys found in commands.
@@ -139,18 +141,18 @@ the options container for later use through the library.
### Aggregate connections ###
Predis is able to aggregate multiple connections which is the base for cluster and replication. By
default the client implements a cluster of nodes using either client-side sharding (default) or a
Redis-backed solution using [redis-cluster](http://redis.io/topics/cluster-tutorial).
Predis is able to aggregate multiple connections which is the base for clustering and replication.
By default the client implements a cluster of nodes using either client-side sharding (default) or
a Redis-backed solution using [redis-cluster](http://redis.io/topics/cluster-tutorial).
As for replication, Predis can handle a single-master and multiple-slaves setup by executing read
operations on slaves and switching to the master for write operations. The replication behavior is
fully configurable.
operations on slaves and switching to the master only for write operations. The replication behavior
is fully configurable.
#### Replication ####
The client can be configured to work in a master / slave replication setup by executing read-only
commands on slave nodes and automatically switch to the master node as soon as a command performing
a write operation is executed. This is the basic configuration needed to work with replication:
The client can be configured to operate in a master-slave setup by executing read-only commands on
slave nodes and automatically switch to the master node as soon as it detects a command that will
perform a write operation. This is the basic configuration needed to work with replication:
```php
// Parameters require one master node specifically marked with `alias=master`.
@@ -161,10 +163,10 @@ $client = new Predis\Client($parameters, $options);
```
While Predis is able to distinguish commands performing write and read-only operations, `EVAL` and
`EVALSHA` represent a corner case in which the client switches to the master node because it is not
able to tell when a Lua script is safe to be executed on slaves. While this is the default behavior,
`EVALSHA` represent a corner case in which the client switches to the master node because it cannot
tell when a Lua script is safe to be executed on slaves. While this is indeed the default behavior,
when certain Lua scripts do not perform write operations it is possible to provide an hint to tell
the client to stick with slaves for their execution.
the client to stick with slaves for their execution:
```php
$parameters = ['tcp://10.0.0.1?alias=master', 'tcp://10.0.0.2?alias=slave-01'];
@@ -182,7 +184,7 @@ $client->evalsha(sha1($LUA_SCRIPT), 0); // ... and `evalsha`, too.
```
The `examples` directory contains two complete scripts showing how replication can be configured for
[simple](examples/replication_simple.php) or [complex](examples/replication_complex.php) scenarios.
[basic](examples/replication_simple.php) and [complex](examples/replication_complex.php) scenarios.
#### Cluster ####
@@ -198,12 +200,12 @@ $options = ['cluster' => 'redis'];
$client = new Predis\Client($parameters, $options);
```
When using redis-cluster, it is not necessary to pass all of the nodes that compose your cluster but
you can simply specify only a few nodes: Predis will automatically fetch the full and updated slots
map directly from Redis by contacting one of the servers.
When using redis-cluster it is not necessary to pass all of the nodes that compose your cluster, you
can specify only a few nodes and the client will automatically fetch the full and updated slots map
directly from Redis by contacting one of the servers.
__NOTE__: our support for redis-cluster does not currently consider master / slave replication but
this feature will be added in a future release of this library.
this feature will be added in a future release of the library.
### Command pipelines ###
@@ -214,7 +216,7 @@ The client can execute the pipeline inside a callable block or return a pipeline
ability to chain commands thanks to its fluent interface:
```php
// Executes a pipeline inside a given callable block:
// Executes a pipeline inside the given callable block:
$responses = $client->pipeline(function ($pipe) {
for ($i = 0; $i < 1000; $i++) {
$pipe->set("key:$i", str_pad($i, 4, '0', 0));
@@ -222,7 +224,7 @@ $responses = $client->pipeline(function ($pipe) {
}
});
// Returns a pipeline instance with fluent interface:
// Returns a pipeline that can be chained thanks to its fluent interface:
$responses = $client->pipeline()->set('foo', 'bar')->get('foo')->execute();
```
@@ -233,13 +235,13 @@ The client provides an abstraction for Redis transactions based on `MULTI` and `
interface to command pipelines:
```php
// Executes a transaction inside a given callable block:
// Executes a transaction inside the given callable block:
$responses = $client->transaction(function ($tx) {
$tx->set('foo', 'bar');
$tx->get('foo');
});
// Returns a transaction instance with fluent interface:
// Returns a transaction that can be chained thanks to its fluent interface:
$responses = $client->transaction()->set('foo', 'bar')->get('foo')->execute();
```
@@ -251,9 +253,9 @@ of a transaction using CAS you can see [the following example](examples/transact
### Adding new commands ###
While we try to update Predis to stay up to date with all the commands available in Redis, you might
prefer to stick with an older version of the library or provide a different way to filter arguments
or parse responses for specific commands. To achieve that, Predis provides the ability to implement
new command classes to define or override commands in the server profiles used by the client:
prefer to stick with an old version of the library or provide a different way to filter arguments or
parse responses for specific commands. To achieve that, Predis provides the ability to implement new
command classes to define or override commands in the default server profiles used by the client:
```php
// Define a new command by extending Predis\Command\Command:
@@ -273,8 +275,8 @@ $response = $client->newcmd();
```
There is also a method to send raw commands without filtering their arguments or parsing responses.
Users must provide the arguments list as an array, following the command signatures as defined by
the [Redis documentation for commands](http://redis.io/commands):
Users must provide the list of arguments for the command as an array, following the signatures as
defined by the [Redis documentation for commands](http://redis.io/commands):
```php
$response = $client->executeRaw(['SET', 'foo', 'bar']);
@@ -284,16 +286,16 @@ $response = $client->executeRaw(['SET', 'foo', 'bar']);
### Script commands ###
While it is possible to leverage [Lua scripting](http://redis.io/commands/eval) on Redis 2.6+ using
[`EVAL`](http://redis.io/commands/eval) and [`EVALSHA`](http://redis.io/commands/evalsha), Predis
offers script commands as an higher level abstraction aiming to make things simple. Script commands
can be registered in the server profile used by the client and are accessible as if they were plain
Redis commands, but they define Lua scripts that get transmitted to the server for remote execution.
Internally they use [`EVALSHA`](http://redis.io/commands/evalsha) by default and identify a script
by its SHA1 hash to save bandwidth, but [`EVAL`](http://redis.io/commands/eval) is used as a fall
back when needed:
[`EVAL`](http://redis.io/commands/eval) and [`EVALSHA`](http://redis.io/commands/evalsha) directly,
Predis offers script commands as an higher level abstraction built upon them to make things simple.
Script commands can be registered in the server profile used by the client and are accessible as if
they were plain Redis commands, but they define Lua scripts that get transmitted to the server for
remote execution. Internally they use [`EVALSHA`](http://redis.io/commands/evalsha) by default and
identify a script by its SHA1 hash to save bandwidth, but [`EVAL`](http://redis.io/commands/eval)
is used as a fall back when needed:
```php
// Define a new scriptable command by extending Predis\Command\ScriptCommand:
// Define a new script command by extending Predis\Command\ScriptCommand:
class ListPushRandomValue extends Predis\Command\ScriptCommand
{
public function getKeysCount()
@@ -312,7 +314,7 @@ LUA;
}
}
// Inject your script command in the current profile:
// Inject the script command in the current profile:
$client = new Predis\Client();
$client->getProfile()->defineCommand('lpushrand', 'ListPushRandomValue');
@@ -325,19 +327,19 @@ $response = $client->lpushrand('random_values', $seed = mt_rand());
Predis can use different connection backends to connect to Redis. Two of them leverage a third party
extension such as [phpiredis](https://github.com/nrk/phpiredis) resulting in major performance gains
especially when dealing with big multibulk responses. While one is based on PHP streams, the other
is based on socket resources provided by `ext-socket`. Both support TCP/IP or UNIX domain sockets:
is based on socket resources provided by `ext-socket`. Both support TCP/IP and UNIX domain sockets:
```php
$client = new Predis\Client('tcp://127.0.0.1', [
'connections' => [
'tcp' => 'Predis\Connection\PhpiredisStreamConnection', // PHP streams
'unix' => 'Predis\Connection\PhpiredisSocketConnection', // ext-socket
'tcp' => 'Predis\Connection\PhpiredisStreamConnection', // PHP stream resources
'unix' => 'Predis\Connection\PhpiredisSocketConnection', // ext-socket resources
],
]);
```
Developers can create their own connection classes to support whole new network backends, extend
existing ones or provide completely different implementations. Connection classes must implement
existing classes or provide completely different implementations. Connection classes must implement
`Predis\Connection\NodeConnectionInterface` or extend `Predis\Connection\AbstractConnection`:
```php
+1 -1
View File
@@ -1 +1 @@
1.1.0-dev
1.0.3
+5 -5
View File
@@ -19,7 +19,7 @@
// files, but namespaces and classes definitions must follow a precise order
// when dealing with subclassing and inheritance.
//
// The current implementation is pretty naïve, but it should do for now.
// The current implementation is pretty naïve, but it should do for now.
// -------------------------------------------------------------------------- //
class CommandLine
@@ -27,10 +27,10 @@ class CommandLine
public static function getOptions()
{
$parameters = array(
's:' => 'source:',
'o:' => 'output:',
'e:' => 'exclude:',
'E:' => 'exclude-classes:',
's:' => 'source:',
'o:' => 'output:',
'e:' => 'exclude:',
'E:' => 'exclude-classes:',
);
$getops = getopt(implode(array_keys($parameters)), $parameters);
+1 -6
View File
@@ -16,7 +16,7 @@
}
],
"require": {
"php": ">=5.3.9"
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
@@ -27,10 +27,5 @@
},
"autoload": {
"psr-4": {"Predis\\": "src/"}
},
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
}
}
+3 -3
View File
@@ -15,9 +15,9 @@ require __DIR__.'/shared.php';
// their own distributors used by the client to distribute keys among a cluster
// of servers.
use Predis\Cluster\PredisStrategy;
use Predis\Cluster\Distributor\DistributorInterface;
use Predis\Cluster\Hash\HashGeneratorInterface;
use Predis\Cluster\PredisStrategy;
use Predis\Connection\Aggregate\PredisCluster;
class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
@@ -34,7 +34,7 @@ class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
public function add($node, $weight = null)
{
$this->nodes[] = $node;
$this->nodesCount++;
++$this->nodesCount;
}
public function remove($node)
@@ -99,7 +99,7 @@ $options = array(
$client = new Predis\Client($multiple_servers, $options);
for ($i = 0; $i < 100; $i++) {
for ($i = 0; $i < 100; ++$i) {
$client->set("key:$i", str_pad($i, 4, '0', 0));
$client->get("key:$i");
}
+2 -2
View File
@@ -26,7 +26,7 @@ var_export($response); echo PHP_EOL;
$mkv = array(
'uid:0001' => '1st user',
'uid:0002' => '2nd user',
'uid:0003' => '3rd user'
'uid:0003' => '3rd user',
);
$client->mset($mkv);
@@ -45,7 +45,7 @@ array (
// their arguments are not filtered nor responses coming from Redis are parsed.
$response = $client->executeRaw(array(
'MGET', 'uid:0001', 'uid:0002', 'uid:0003'
'MGET', 'uid:0001', 'uid:0002', 'uid:0003',
));
var_export($response); echo PHP_EOL;
+1 -1
View File
@@ -55,7 +55,7 @@ $client = new Predis\Client($single_server, array(
$profile->defineCommand('increxby', 'IncrementExistingKeysBy');
return $profile;
}
},
));
$client->mset('foo', 10, 'foobar', 100);
+1 -1
View File
@@ -28,7 +28,7 @@ foreach (($monitor = $client->monitor()) as $event) {
// If we notice a ECHO command with the message QUIT_MONITOR, we stop the
// monitor consumer and then break the loop.
if ($event->command === 'ECHO' && $event->arguments === '"QUIT_MONITOR"') {
echo "Exiting the monitor loop...", PHP_EOL;
echo 'Exiting the monitor loop...', PHP_EOL;
$monitor->stop();
break;
}
+1 -1
View File
@@ -36,7 +36,7 @@ foreach ($pubsub as $message) {
case 'message':
if ($message->channel == 'control_channel') {
if ($message->payload == 'quit_loop') {
echo "Aborting pubsub loop...", PHP_EOL;
echo 'Aborting pubsub loop...', PHP_EOL;
$pubsub->unsubscribe();
} else {
echo "Received an unrecognized command: {$message->payload}.", PHP_EOL;
+1 -1
View File
@@ -34,7 +34,7 @@ $client = new Predis\Client($single_server, array('profile' => '2.8'));
// Prepare some keys for our example
$client->del('predis:set', 'predis:zset', 'predis:hash');
for ($i = 0; $i < 5; $i++) {
for ($i = 0; $i < 5; ++$i) {
$client->sadd('predis:set', "member:$i");
$client->zadd('predis:zset', -$i, "member:$i");
$client->hset('predis:hash', "field:$i", "value:$i");
+1 -1
View File
@@ -81,5 +81,5 @@ $hashes = $client->hmgetall('metavars', 'servers');
$replication = $client->getConnection();
$stillOnSlave = $replication->getCurrent() === $replication->getConnectionById('slave');
echo "Is still on slave? ", $stillOnSlave ? 'YES!' : 'NO!', PHP_EOL;
echo 'Is still on slave? ', $stillOnSlave ? 'YES!' : 'NO!', PHP_EOL;
var_export($hashes);
+1 -1
View File
@@ -25,7 +25,7 @@ require __DIR__.'/shared.php';
//
if (!interface_exists('SessionHandlerInterface')) {
die("ATTENTION: the session handler implemented by Predis requires PHP >= 5.4.0 ".
die('ATTENTION: the session handler implemented by Predis requires PHP >= 5.4.0 '.
"or a polyfill for SessionHandlerInterface provided by an external package.\n");
}
+1 -1
View File
@@ -25,7 +25,7 @@ function redis_version($info)
$single_server = array(
'host' => '127.0.0.1',
'port' => 6379,
'database' => 15
'database' => 15,
);
$multiple_servers = array(
+1 -1
View File
@@ -49,4 +49,4 @@ function zpop($client, $key)
$client = new Predis\Client($single_server);
$zpopped = zpop($client, 'zset');
echo isset($zpopped) ? "ZPOPed $zpopped" : "Nothing to ZPOP!", PHP_EOL;
echo isset($zpopped) ? "ZPOPed $zpopped" : 'Nothing to ZPOP!', PHP_EOL;
+3 -3
View File
@@ -10,14 +10,14 @@ name = "Predis"
desc = "Flexible and feature-complete PHP client library for Redis"
homepage = "http://github.com/nrk/predis"
license = "MIT"
version = "1.1.0"
stability = "devel"
version = "1.0.3"
stability = "stable"
channel = "pear.nrk.io"
author = "Daniele Alessandri \"nrk\" <suppakilla@gmail.com>"
[require]
php = ">= 5.3.9"
php = ">= 5.3.2"
pearinstaller = "1.4.1"
[roles]
+6 -1
View File
@@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php" colors="true" strict="true">
<phpunit bootstrap="tests/bootstrap.php"
colors="true"
beStrictAboutTestSize="true"
checkForUnintentionallyCoveredCode="true"
beStrictAboutTestsThatDoNotTestAnything="true">
<testsuites>
<testsuite name="Predis Test Suite">
<directory>tests/Predis/</directory>
+6 -1
View File
@@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php" colors="true" strict="true">
<phpunit bootstrap="tests/bootstrap.php"
colors="true"
beStrictAboutTestSize="true"
checkForUnintentionallyCoveredCode="true"
beStrictAboutTestsThatDoNotTestAnything="true">
<testsuites>
<testsuite name="Predis Test Suite">
<directory>tests/Predis/</directory>
+3 -3
View File
@@ -29,7 +29,7 @@ class Autoloader
public function __construct($baseDirectory = __DIR__)
{
$this->directory = $baseDirectory;
$this->prefix = __NAMESPACE__ . '\\';
$this->prefix = __NAMESPACE__.'\\';
$this->prefixLength = strlen($this->prefix);
}
@@ -40,7 +40,7 @@ class Autoloader
*/
public static function register($prepend = false)
{
spl_autoload_register(array(new self, 'autoload'), true, $prepend);
spl_autoload_register(array(new self(), 'autoload'), true, $prepend);
}
/**
@@ -55,7 +55,7 @@ class Autoloader
$filepath = $this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.php';
if (is_file($filepath)) {
require($filepath);
require $filepath;
}
}
}
+16 -18
View File
@@ -11,15 +11,13 @@
namespace Predis;
use InvalidArgumentException;
use UnexpectedValueException;
use Predis\Command\CommandInterface;
use Predis\Command\RawCommand;
use Predis\Command\ScriptCommand;
use Predis\Configuration\Options;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Connection\AggregateConnectionInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Connection\ParametersInterface;
use Predis\Monitor\Consumer as MonitorConsumer;
use Predis\Pipeline\Pipeline;
@@ -42,7 +40,7 @@ use Predis\Transaction\MultiExec as MultiExecTransaction;
*/
class Client implements ClientInterface
{
const VERSION = '1.1.0-dev';
const VERSION = '1.0.3';
protected $connection;
protected $options;
@@ -66,9 +64,9 @@ class Client implements ClientInterface
*
* @param mixed $options Client options.
*
* @return OptionsInterface
*
* @throws \InvalidArgumentException
*
* @return OptionsInterface
*/
protected function createOptions($options)
{
@@ -80,7 +78,7 @@ class Client implements ClientInterface
return $options;
}
throw new InvalidArgumentException("Invalid type for client options.");
throw new \InvalidArgumentException('Invalid type for client options.');
}
/**
@@ -98,9 +96,9 @@ class Client implements ClientInterface
*
* @param mixed $parameters Connection parameters or connection instance.
*
* @return ConnectionInterface
*
* @throws \InvalidArgumentException
*
* @return ConnectionInterface
*/
protected function createConnection($parameters)
{
@@ -142,7 +140,7 @@ class Client implements ClientInterface
return $connection;
}
throw new InvalidArgumentException('Invalid type for connection parameters.');
throw new \InvalidArgumentException('Invalid type for connection parameters.');
}
/**
@@ -159,7 +157,7 @@ class Client implements ClientInterface
$connection = call_user_func_array($callable, func_get_args());
if (!$connection instanceof ConnectionInterface) {
throw new UnexpectedValueException(
throw new \UnexpectedValueException(
'The callable connection initializer returned an invalid type.'
);
}
@@ -191,14 +189,14 @@ class Client implements ClientInterface
*
* @param string $connectionID Identifier of a connection.
*
* @return Client
*
* @throws \InvalidArgumentException
*
* @return Client
*/
public function getClientFor($connectionID)
{
if (!$connection = $this->getConnectionById($connectionID)) {
throw new InvalidArgumentException("Invalid connection ID: $connectionID.");
throw new \InvalidArgumentException("Invalid connection ID: $connectionID.");
}
return new static($connection, $this->options);
@@ -255,9 +253,9 @@ class Client implements ClientInterface
*
* @param string $connectionID Index or alias of the single connection.
*
* @return Connection\NodeConnectionInterface
*
* @throws NotSupportedException
*
* @return Connection\NodeConnectionInterface
*/
public function getConnectionById($connectionID)
{
@@ -344,9 +342,9 @@ class Client implements ClientInterface
* @param CommandInterface $command Redis command that generated the error.
* @param ErrorResponseInterface $response Instance of the error response.
*
* @return mixed
*
* @throws ServerException
*
* @return mixed
*/
protected function onErrorResponse(CommandInterface $command, ErrorResponseInterface $response)
{
-1
View File
@@ -159,7 +159,6 @@ use Predis\Command\CommandInterface;
*/
interface ClientContextInterface
{
/**
* Sends the specified command instance to Redis.
*
+110 -110
View File
@@ -11,7 +11,6 @@
namespace Predis\Cluster;
use InvalidArgumentException;
use Predis\Command\CommandInterface;
use Predis\Command\ScriptCommand;
@@ -44,126 +43,127 @@ abstract class ClusterStrategy implements StrategyInterface
return array(
/* commands operating on the key space */
'EXISTS' => $getKeyFromFirstArgument,
'DEL' => $getKeyFromAllArguments,
'TYPE' => $getKeyFromFirstArgument,
'EXPIRE' => $getKeyFromFirstArgument,
'EXPIREAT' => $getKeyFromFirstArgument,
'PERSIST' => $getKeyFromFirstArgument,
'PEXPIRE' => $getKeyFromFirstArgument,
'PEXPIREAT' => $getKeyFromFirstArgument,
'TTL' => $getKeyFromFirstArgument,
'PTTL' => $getKeyFromFirstArgument,
'SORT' => $getKeyFromFirstArgument, // TODO
'DUMP' => $getKeyFromFirstArgument,
'RESTORE' => $getKeyFromFirstArgument,
'EXISTS' => $getKeyFromFirstArgument,
'DEL' => $getKeyFromAllArguments,
'TYPE' => $getKeyFromFirstArgument,
'EXPIRE' => $getKeyFromFirstArgument,
'EXPIREAT' => $getKeyFromFirstArgument,
'PERSIST' => $getKeyFromFirstArgument,
'PEXPIRE' => $getKeyFromFirstArgument,
'PEXPIREAT' => $getKeyFromFirstArgument,
'TTL' => $getKeyFromFirstArgument,
'PTTL' => $getKeyFromFirstArgument,
'SORT' => $getKeyFromFirstArgument, // TODO
'DUMP' => $getKeyFromFirstArgument,
'RESTORE' => $getKeyFromFirstArgument,
/* commands operating on string values */
'APPEND' => $getKeyFromFirstArgument,
'DECR' => $getKeyFromFirstArgument,
'DECRBY' => $getKeyFromFirstArgument,
'GET' => $getKeyFromFirstArgument,
'GETBIT' => $getKeyFromFirstArgument,
'MGET' => $getKeyFromAllArguments,
'SET' => $getKeyFromFirstArgument,
'GETRANGE' => $getKeyFromFirstArgument,
'GETSET' => $getKeyFromFirstArgument,
'INCR' => $getKeyFromFirstArgument,
'INCRBY' => $getKeyFromFirstArgument,
'INCRBYFLOAT' => $getKeyFromFirstArgument,
'SETBIT' => $getKeyFromFirstArgument,
'SETEX' => $getKeyFromFirstArgument,
'MSET' => array($this, 'getKeyFromInterleavedArguments'),
'MSETNX' => array($this, 'getKeyFromInterleavedArguments'),
'SETNX' => $getKeyFromFirstArgument,
'SETRANGE' => $getKeyFromFirstArgument,
'STRLEN' => $getKeyFromFirstArgument,
'SUBSTR' => $getKeyFromFirstArgument,
'BITOP' => array($this, 'getKeyFromBitOp'),
'BITCOUNT' => $getKeyFromFirstArgument,
'APPEND' => $getKeyFromFirstArgument,
'DECR' => $getKeyFromFirstArgument,
'DECRBY' => $getKeyFromFirstArgument,
'GET' => $getKeyFromFirstArgument,
'GETBIT' => $getKeyFromFirstArgument,
'MGET' => $getKeyFromAllArguments,
'SET' => $getKeyFromFirstArgument,
'GETRANGE' => $getKeyFromFirstArgument,
'GETSET' => $getKeyFromFirstArgument,
'INCR' => $getKeyFromFirstArgument,
'INCRBY' => $getKeyFromFirstArgument,
'INCRBYFLOAT' => $getKeyFromFirstArgument,
'SETBIT' => $getKeyFromFirstArgument,
'SETEX' => $getKeyFromFirstArgument,
'MSET' => array($this, 'getKeyFromInterleavedArguments'),
'MSETNX' => array($this, 'getKeyFromInterleavedArguments'),
'SETNX' => $getKeyFromFirstArgument,
'SETRANGE' => $getKeyFromFirstArgument,
'STRLEN' => $getKeyFromFirstArgument,
'SUBSTR' => $getKeyFromFirstArgument,
'BITOP' => array($this, 'getKeyFromBitOp'),
'BITCOUNT' => $getKeyFromFirstArgument,
/* commands operating on lists */
'LINSERT' => $getKeyFromFirstArgument,
'LINDEX' => $getKeyFromFirstArgument,
'LLEN' => $getKeyFromFirstArgument,
'LPOP' => $getKeyFromFirstArgument,
'RPOP' => $getKeyFromFirstArgument,
'RPOPLPUSH' => $getKeyFromAllArguments,
'BLPOP' => array($this, 'getKeyFromBlockingListCommands'),
'BRPOP' => array($this, 'getKeyFromBlockingListCommands'),
'BRPOPLPUSH' => array($this, 'getKeyFromBlockingListCommands'),
'LPUSH' => $getKeyFromFirstArgument,
'LPUSHX' => $getKeyFromFirstArgument,
'RPUSH' => $getKeyFromFirstArgument,
'RPUSHX' => $getKeyFromFirstArgument,
'LRANGE' => $getKeyFromFirstArgument,
'LREM' => $getKeyFromFirstArgument,
'LSET' => $getKeyFromFirstArgument,
'LTRIM' => $getKeyFromFirstArgument,
'LINSERT' => $getKeyFromFirstArgument,
'LINDEX' => $getKeyFromFirstArgument,
'LLEN' => $getKeyFromFirstArgument,
'LPOP' => $getKeyFromFirstArgument,
'RPOP' => $getKeyFromFirstArgument,
'RPOPLPUSH' => $getKeyFromAllArguments,
'BLPOP' => array($this, 'getKeyFromBlockingListCommands'),
'BRPOP' => array($this, 'getKeyFromBlockingListCommands'),
'BRPOPLPUSH' => array($this, 'getKeyFromBlockingListCommands'),
'LPUSH' => $getKeyFromFirstArgument,
'LPUSHX' => $getKeyFromFirstArgument,
'RPUSH' => $getKeyFromFirstArgument,
'RPUSHX' => $getKeyFromFirstArgument,
'LRANGE' => $getKeyFromFirstArgument,
'LREM' => $getKeyFromFirstArgument,
'LSET' => $getKeyFromFirstArgument,
'LTRIM' => $getKeyFromFirstArgument,
/* commands operating on sets */
'SADD' => $getKeyFromFirstArgument,
'SCARD' => $getKeyFromFirstArgument,
'SDIFF' => $getKeyFromAllArguments,
'SDIFFSTORE' => $getKeyFromAllArguments,
'SINTER' => $getKeyFromAllArguments,
'SINTERSTORE' => $getKeyFromAllArguments,
'SUNION' => $getKeyFromAllArguments,
'SUNIONSTORE' => $getKeyFromAllArguments,
'SISMEMBER' => $getKeyFromFirstArgument,
'SMEMBERS' => $getKeyFromFirstArgument,
'SSCAN' => $getKeyFromFirstArgument,
'SPOP' => $getKeyFromFirstArgument,
'SRANDMEMBER' => $getKeyFromFirstArgument,
'SREM' => $getKeyFromFirstArgument,
'SADD' => $getKeyFromFirstArgument,
'SCARD' => $getKeyFromFirstArgument,
'SDIFF' => $getKeyFromAllArguments,
'SDIFFSTORE' => $getKeyFromAllArguments,
'SINTER' => $getKeyFromAllArguments,
'SINTERSTORE' => $getKeyFromAllArguments,
'SUNION' => $getKeyFromAllArguments,
'SUNIONSTORE' => $getKeyFromAllArguments,
'SISMEMBER' => $getKeyFromFirstArgument,
'SMEMBERS' => $getKeyFromFirstArgument,
'SSCAN' => $getKeyFromFirstArgument,
'SPOP' => $getKeyFromFirstArgument,
'SRANDMEMBER' => $getKeyFromFirstArgument,
'SREM' => $getKeyFromFirstArgument,
/* commands operating on sorted sets */
'ZADD' => $getKeyFromFirstArgument,
'ZCARD' => $getKeyFromFirstArgument,
'ZCOUNT' => $getKeyFromFirstArgument,
'ZINCRBY' => $getKeyFromFirstArgument,
'ZINTERSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZRANGE' => $getKeyFromFirstArgument,
'ZRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZRANK' => $getKeyFromFirstArgument,
'ZREM' => $getKeyFromFirstArgument,
'ZREMRANGEBYRANK' => $getKeyFromFirstArgument,
'ZREMRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZREVRANGE' => $getKeyFromFirstArgument,
'ZREVRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZREVRANK' => $getKeyFromFirstArgument,
'ZSCORE' => $getKeyFromFirstArgument,
'ZUNIONSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZSCAN' => $getKeyFromFirstArgument,
'ZLEXCOUNT' => $getKeyFromFirstArgument,
'ZRANGEBYLEX' => $getKeyFromFirstArgument,
'ZREMRANGEBYLEX' => $getKeyFromFirstArgument,
'ZREVRANGEBYLEX' => $getKeyFromFirstArgument,
'ZADD' => $getKeyFromFirstArgument,
'ZCARD' => $getKeyFromFirstArgument,
'ZCOUNT' => $getKeyFromFirstArgument,
'ZINCRBY' => $getKeyFromFirstArgument,
'ZINTERSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZRANGE' => $getKeyFromFirstArgument,
'ZRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZRANK' => $getKeyFromFirstArgument,
'ZREM' => $getKeyFromFirstArgument,
'ZREMRANGEBYRANK' => $getKeyFromFirstArgument,
'ZREMRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZREVRANGE' => $getKeyFromFirstArgument,
'ZREVRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZREVRANK' => $getKeyFromFirstArgument,
'ZSCORE' => $getKeyFromFirstArgument,
'ZUNIONSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZSCAN' => $getKeyFromFirstArgument,
'ZLEXCOUNT' => $getKeyFromFirstArgument,
'ZRANGEBYLEX' => $getKeyFromFirstArgument,
'ZREMRANGEBYLEX' => $getKeyFromFirstArgument,
'ZREVRANGEBYLEX' => $getKeyFromFirstArgument,
/* commands operating on hashes */
'HDEL' => $getKeyFromFirstArgument,
'HEXISTS' => $getKeyFromFirstArgument,
'HGET' => $getKeyFromFirstArgument,
'HGETALL' => $getKeyFromFirstArgument,
'HMGET' => $getKeyFromFirstArgument,
'HMSET' => $getKeyFromFirstArgument,
'HINCRBY' => $getKeyFromFirstArgument,
'HINCRBYFLOAT' => $getKeyFromFirstArgument,
'HKEYS' => $getKeyFromFirstArgument,
'HLEN' => $getKeyFromFirstArgument,
'HSET' => $getKeyFromFirstArgument,
'HSETNX' => $getKeyFromFirstArgument,
'HVALS' => $getKeyFromFirstArgument,
'HSCAN' => $getKeyFromFirstArgument,
'HDEL' => $getKeyFromFirstArgument,
'HEXISTS' => $getKeyFromFirstArgument,
'HGET' => $getKeyFromFirstArgument,
'HGETALL' => $getKeyFromFirstArgument,
'HMGET' => $getKeyFromFirstArgument,
'HMSET' => $getKeyFromFirstArgument,
'HINCRBY' => $getKeyFromFirstArgument,
'HINCRBYFLOAT' => $getKeyFromFirstArgument,
'HKEYS' => $getKeyFromFirstArgument,
'HLEN' => $getKeyFromFirstArgument,
'HSET' => $getKeyFromFirstArgument,
'HSETNX' => $getKeyFromFirstArgument,
'HVALS' => $getKeyFromFirstArgument,
'HSCAN' => $getKeyFromFirstArgument,
'HSTRLEN' => $getKeyFromFirstArgument,
/* commands operating on HyperLogLog */
'PFADD' => $getKeyFromFirstArgument,
'PFCOUNT' => $getKeyFromAllArguments,
'PFMERGE' => $getKeyFromAllArguments,
'PFADD' => $getKeyFromFirstArgument,
'PFCOUNT' => $getKeyFromAllArguments,
'PFMERGE' => $getKeyFromAllArguments,
/* scripting */
'EVAL' => array($this, 'getKeyFromScriptingCommands'),
'EVALSHA' => array($this, 'getKeyFromScriptingCommands'),
'EVAL' => array($this, 'getKeyFromScriptingCommands'),
'EVALSHA' => array($this, 'getKeyFromScriptingCommands'),
);
}
@@ -202,8 +202,8 @@ abstract class ClusterStrategy implements StrategyInterface
}
if (!is_callable($callback)) {
throw new InvalidArgumentException(
"The argument must be a callable object or NULL."
throw new \InvalidArgumentException(
'The argument must be a callable object or NULL.'
);
}
@@ -364,7 +364,7 @@ abstract class ClusterStrategy implements StrategyInterface
$currentSlot = $this->getSlotByKey($keys[0]);
for ($i = 1; $i < $count; $i++) {
for ($i = 1; $i < $count; ++$i) {
$nextSlot = $this->getSlotByKey($keys[$i]);
if ($currentSlot !== $nextSlot) {
@@ -11,13 +11,11 @@
namespace Predis\Cluster\Distributor;
use Exception;
/**
* Exception class that identifies empty rings.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class EmptyRingException extends Exception
class EmptyRingException extends \Exception
{
}
+3 -3
View File
@@ -24,7 +24,7 @@ use Predis\Cluster\Hash\HashGeneratorInterface;
class HashRing implements DistributorInterface, HashGeneratorInterface
{
const DEFAULT_REPLICAS = 128;
const DEFAULT_WEIGHT = 100;
const DEFAULT_WEIGHT = 100;
private $ring;
private $ringKeys;
@@ -55,7 +55,7 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
// last wins, thus the order in which nodes are added is significant.
$this->nodes[] = array(
'object' => $node,
'weight' => (int) $weight ?: $this::DEFAULT_WEIGHT
'weight' => (int) $weight ?: $this::DEFAULT_WEIGHT,
);
$this->reset();
@@ -160,7 +160,7 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
$nodeHash = $this->getNodeHash($nodeObject);
$replicas = (int) round($weightRatio * $totalNodes * $replicas);
for ($i = 0; $i < $replicas; $i++) {
for ($i = 0; $i < $replicas; ++$i) {
$key = crc32("$nodeHash:$i");
$ring[$key] = $nodeObject;
}
+1 -1
View File
@@ -40,7 +40,7 @@ class KetamaRing extends HashRing
$nodeHash = $this->getNodeHash($nodeObject);
$replicas = (int) floor($weightRatio * $totalNodes * ($replicas / 4));
for ($i = 0; $i < $replicas; $i++) {
for ($i = 0; $i < $replicas; ++$i) {
$unpackedDigest = unpack('V4', md5("$nodeHash-$i", true));
foreach ($unpackedDigest as $key) {
+1 -1
View File
@@ -63,7 +63,7 @@ class CRC16 implements HashGeneratorInterface
$CCITT_16 = self::$CCITT_16;
$strlen = strlen($value);
for ($i = 0; $i < $strlen; $i++) {
for ($i = 0; $i < $strlen; ++$i) {
$crc = (($crc << 8) ^ $CCITT_16[($crc >> 8) ^ ord($value[$i])]) & 0xFFFF;
}
+1 -1
View File
@@ -56,7 +56,7 @@ class PredisStrategy extends ClusterStrategy
$currentKey = $this->extractKeyTag($keys[0]);
for ($i = 1; $i < $count; $i++) {
for ($i = 1; $i < $count; ++$i) {
$nextKey = $this->extractKeyTag($keys[$i]);
if ($currentKey !== $nextKey) {
+3 -3
View File
@@ -11,9 +11,9 @@
namespace Predis\Cluster;
use Predis\NotSupportedException;
use Predis\Cluster\Hash\HashGeneratorInterface;
use Predis\Cluster\Hash\CRC16;
use Predis\Cluster\Hash\HashGeneratorInterface;
use Predis\NotSupportedException;
/**
* Default class used by Predis to calculate hashes out of keys of
@@ -40,7 +40,7 @@ class RedisStrategy extends ClusterStrategy
*/
public function getSlotByKey($key)
{
$key = $this->extractKeyTag($key);
$key = $this->extractKeyTag($key);
$slot = $this->hashGenerator->hash($key) & 0x3FFF;
return $slot;
@@ -11,7 +11,6 @@
namespace Predis\Collection\Iterator;
use Iterator;
use Predis\ClientInterface;
use Predis\NotSupportedException;
@@ -28,7 +27,7 @@ use Predis\NotSupportedException;
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
abstract class CursorBasedIterator implements Iterator
abstract class CursorBasedIterator implements \Iterator
{
protected $client;
protected $match;
@@ -133,7 +132,7 @@ abstract class CursorBasedIterator implements Iterator
*/
protected function extractNext()
{
$this->position++;
++$this->position;
$this->current = array_shift($this->elements);
}
+1
View File
@@ -18,6 +18,7 @@ use Predis\ClientInterface;
* 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
+1
View File
@@ -18,6 +18,7 @@ use Predis\ClientInterface;
* 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
+4 -5
View File
@@ -11,8 +11,6 @@
namespace Predis\Collection\Iterator;
use InvalidArgumentException;
use Iterator;
use Predis\ClientInterface;
use Predis\NotSupportedException;
@@ -27,9 +25,10 @@ use Predis\NotSupportedException;
* times (trimmed, deleted, overwritten) during the iteration process.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/lrange
*/
class ListKey implements Iterator
class ListKey implements \Iterator
{
protected $client;
protected $count;
@@ -53,7 +52,7 @@ class ListKey implements Iterator
$this->requiredCommand($client, 'LRANGE');
if ((false === $count = filter_var($count, FILTER_VALIDATE_INT)) || $count < 0) {
throw new InvalidArgumentException('The $count argument must be a positive integer.');
throw new \InvalidArgumentException('The $count argument must be a positive integer.');
}
$this->client = $client;
@@ -122,7 +121,7 @@ class ListKey implements Iterator
*/
protected function extractNext()
{
$this->position++;
++$this->position;
$this->current = array_shift($this->elements);
}
+1
View File
@@ -18,6 +18,7 @@ use Predis\ClientInterface;
* 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
+1
View File
@@ -18,6 +18,7 @@ use Predis\ClientInterface;
* 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
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/auth
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ConnectionAuth extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/echo
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ConnectionEcho extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/ping
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ConnectionPing extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/quit
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ConnectionQuit extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/select
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ConnectionSelect extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hdel
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashDelete extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hexists
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashExists extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hget
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashGet extends Command
+2 -1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hgetall
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashGetAll extends Command
@@ -32,7 +33,7 @@ class HashGetAll extends Command
{
$result = array();
for ($i = 0; $i < count($data); $i++) {
for ($i = 0; $i < count($data); ++$i) {
$result[$data[$i]] = $data[++$i];
}
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hmget
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashGetMultiple extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hincrby
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashIncrementBy extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hincrbyfloat
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashIncrementByFloat extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hkeys
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashKeys extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hlen
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashLength extends Command
+2 -1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hscan
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashScan extends Command
@@ -72,7 +73,7 @@ class HashScan extends Command
$fields = $data[1];
$result = array();
for ($i = 0; $i < count($fields); $i++) {
for ($i = 0; $i < count($fields); ++$i) {
$result[$fields[$i]] = $fields[++$i];
}
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hset
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashSet extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hmset
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashSetMultiple extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hsetnx
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashSetPreserve extends Command
+28
View 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/hstrlen
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashStringLength extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'HSTRLEN';
}
}
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/hvals
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HashValues extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/pfadd
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HyperLogLogAdd extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/pfcount
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HyperLogLogCount extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/pfmerge
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class HyperLogLogMerge extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/del
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyDelete extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/dump
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyDump extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/exists
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyExists extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/expire
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyExpire extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/expireat
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyExpireAt extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/keys
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyKeys extends Command
+50
View File
@@ -0,0 +1,50 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command;
/**
* @link http://redis.io/commands/migrate
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyMigrate extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'MIGRATE';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(array $arguments)
{
if (is_array(end($arguments))) {
foreach (array_pop($arguments) as $modifier => $value) {
$modifier = strtoupper($modifier);
if ($modifier === 'COPY' && $value == true) {
$arguments[] = $modifier;
}
if ($modifier === 'REPLACE' && $value == true) {
$arguments[] = $modifier;
}
}
}
return $arguments;
}
}
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/move
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyMove extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/persist
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyPersist extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/pexpire
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyPreciseExpire extends KeyExpire
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/pexpireat
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyPreciseExpireAt extends KeyExpireAt
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/pttl
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyPreciseTimeToLive extends KeyTimeToLive
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/randomkey
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyRandom extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/rename
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyRename extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/renamenx
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyRenamePreserve extends KeyRename
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/restore
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyRestore extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/scan
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyScan extends Command
+1 -1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/sort
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeySort extends Command
@@ -59,7 +60,6 @@ class KeySort extends Command
if (isset($sortParams['LIMIT']) &&
is_array($sortParams['LIMIT']) &&
count($sortParams['LIMIT']) == 2) {
$query[] = 'LIMIT';
$query[] = $sortParams['LIMIT'][0];
$query[] = $sortParams['LIMIT'][1];
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/ttl
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyTimeToLive extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/type
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyType extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/lindex
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListIndex extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/linsert
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListInsert extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/llen
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListLength extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/lpop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopFirst extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/blpop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopFirstBlocking extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/rpop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopLast extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/brpop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopLastBlocking extends ListPopFirstBlocking
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/rpoplpush
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopLastPushHead extends Command
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/brpoplpush
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPopLastPushHeadBlocking extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/lpush
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPushHead extends ListPushTail
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/lpushx
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPushHeadX extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/rpush
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPushTail extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/rpushx
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListPushTailX extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/lrange
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListRange extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/lrem
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListRemove extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/lset
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListSet extends Command
+1
View File
@@ -13,6 +13,7 @@ namespace Predis\Command;
/**
* @link http://redis.io/commands/ltrim
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ListTrim extends Command
+143 -126
View File
@@ -11,7 +11,6 @@
namespace Predis\Command\Processor;
use InvalidArgumentException;
use Predis\Command\CommandInterface;
use Predis\Command\PrefixableCommandInterface;
@@ -34,128 +33,132 @@ class KeyPrefixProcessor implements ProcessorInterface
$this->prefix = $prefix;
$this->commands = array(
/* ---------------- Redis 1.2 ---------------- */
'EXISTS' => 'self::first',
'DEL' => 'self::all',
'TYPE' => 'self::first',
'KEYS' => 'self::first',
'RENAME' => 'self::all',
'RENAMENX' => 'self::all',
'EXPIRE' => 'self::first',
'EXPIREAT' => 'self::first',
'TTL' => 'self::first',
'MOVE' => 'self::first',
'SORT' => 'self::sort',
'DUMP' => 'self::first',
'RESTORE' => 'self::first',
'SET' => 'self::first',
'SETNX' => 'self::first',
'MSET' => 'self::interleaved',
'MSETNX' => 'self::interleaved',
'GET' => 'self::first',
'MGET' => 'self::all',
'GETSET' => 'self::first',
'INCR' => 'self::first',
'INCRBY' => 'self::first',
'DECR' => 'self::first',
'DECRBY' => 'self::first',
'RPUSH' => 'self::first',
'LPUSH' => 'self::first',
'LLEN' => 'self::first',
'LRANGE' => 'self::first',
'LTRIM' => 'self::first',
'LINDEX' => 'self::first',
'LSET' => 'self::first',
'LREM' => 'self::first',
'LPOP' => 'self::first',
'RPOP' => 'self::first',
'RPOPLPUSH' => 'self::all',
'SADD' => 'self::first',
'SREM' => 'self::first',
'SPOP' => 'self::first',
'SMOVE' => 'self::skipLast',
'SCARD' => 'self::first',
'SISMEMBER' => 'self::first',
'SINTER' => 'self::all',
'SINTERSTORE' => 'self::all',
'SUNION' => 'self::all',
'SUNIONSTORE' => 'self::all',
'SDIFF' => 'self::all',
'SDIFFSTORE' => 'self::all',
'SMEMBERS' => 'self::first',
'SRANDMEMBER' => 'self::first',
'ZADD' => 'self::first',
'ZINCRBY' => 'self::first',
'ZREM' => 'self::first',
'ZRANGE' => 'self::first',
'ZREVRANGE' => 'self::first',
'ZRANGEBYSCORE' => 'self::first',
'ZCARD' => 'self::first',
'ZSCORE' => 'self::first',
'ZREMRANGEBYSCORE' => 'self::first',
'EXISTS' => 'static::first',
'DEL' => 'static::all',
'TYPE' => 'static::first',
'KEYS' => 'static::first',
'RENAME' => 'static::all',
'RENAMENX' => 'static::all',
'EXPIRE' => 'static::first',
'EXPIREAT' => 'static::first',
'TTL' => 'static::first',
'MOVE' => 'static::first',
'SORT' => 'static::sort',
'DUMP' => 'static::first',
'RESTORE' => 'static::first',
'SET' => 'static::first',
'SETNX' => 'static::first',
'MSET' => 'static::interleaved',
'MSETNX' => 'static::interleaved',
'GET' => 'static::first',
'MGET' => 'static::all',
'GETSET' => 'static::first',
'INCR' => 'static::first',
'INCRBY' => 'static::first',
'DECR' => 'static::first',
'DECRBY' => 'static::first',
'RPUSH' => 'static::first',
'LPUSH' => 'static::first',
'LLEN' => 'static::first',
'LRANGE' => 'static::first',
'LTRIM' => 'static::first',
'LINDEX' => 'static::first',
'LSET' => 'static::first',
'LREM' => 'static::first',
'LPOP' => 'static::first',
'RPOP' => 'static::first',
'RPOPLPUSH' => 'static::all',
'SADD' => 'static::first',
'SREM' => 'static::first',
'SPOP' => 'static::first',
'SMOVE' => 'static::skipLast',
'SCARD' => 'static::first',
'SISMEMBER' => 'static::first',
'SINTER' => 'static::all',
'SINTERSTORE' => 'static::all',
'SUNION' => 'static::all',
'SUNIONSTORE' => 'static::all',
'SDIFF' => 'static::all',
'SDIFFSTORE' => 'static::all',
'SMEMBERS' => 'static::first',
'SRANDMEMBER' => 'static::first',
'ZADD' => 'static::first',
'ZINCRBY' => 'static::first',
'ZREM' => 'static::first',
'ZRANGE' => 'static::first',
'ZREVRANGE' => 'static::first',
'ZRANGEBYSCORE' => 'static::first',
'ZCARD' => 'static::first',
'ZSCORE' => 'static::first',
'ZREMRANGEBYSCORE' => 'static::first',
/* ---------------- Redis 2.0 ---------------- */
'SETEX' => 'self::first',
'APPEND' => 'self::first',
'SUBSTR' => 'self::first',
'BLPOP' => 'self::skipLast',
'BRPOP' => 'self::skipLast',
'ZUNIONSTORE' => 'self::zsetStore',
'ZINTERSTORE' => 'self::zsetStore',
'ZCOUNT' => 'self::first',
'ZRANK' => 'self::first',
'ZREVRANK' => 'self::first',
'ZREMRANGEBYRANK' => 'self::first',
'HSET' => 'self::first',
'HSETNX' => 'self::first',
'HMSET' => 'self::first',
'HINCRBY' => 'self::first',
'HGET' => 'self::first',
'HMGET' => 'self::first',
'HDEL' => 'self::first',
'HEXISTS' => 'self::first',
'HLEN' => 'self::first',
'HKEYS' => 'self::first',
'HVALS' => 'self::first',
'HGETALL' => 'self::first',
'SUBSCRIBE' => 'self::all',
'UNSUBSCRIBE' => 'self::all',
'PSUBSCRIBE' => 'self::all',
'PUNSUBSCRIBE' => 'self::all',
'PUBLISH' => 'self::first',
'SETEX' => 'static::first',
'APPEND' => 'static::first',
'SUBSTR' => 'static::first',
'BLPOP' => 'static::skipLast',
'BRPOP' => 'static::skipLast',
'ZUNIONSTORE' => 'static::zsetStore',
'ZINTERSTORE' => 'static::zsetStore',
'ZCOUNT' => 'static::first',
'ZRANK' => 'static::first',
'ZREVRANK' => 'static::first',
'ZREMRANGEBYRANK' => 'static::first',
'HSET' => 'static::first',
'HSETNX' => 'static::first',
'HMSET' => 'static::first',
'HINCRBY' => 'static::first',
'HGET' => 'static::first',
'HMGET' => 'static::first',
'HDEL' => 'static::first',
'HEXISTS' => 'static::first',
'HLEN' => 'static::first',
'HKEYS' => 'static::first',
'HVALS' => 'static::first',
'HGETALL' => 'static::first',
'SUBSCRIBE' => 'static::all',
'UNSUBSCRIBE' => 'static::all',
'PSUBSCRIBE' => 'static::all',
'PUNSUBSCRIBE' => 'static::all',
'PUBLISH' => 'static::first',
/* ---------------- Redis 2.2 ---------------- */
'PERSIST' => 'self::first',
'STRLEN' => 'self::first',
'SETRANGE' => 'self::first',
'GETRANGE' => 'self::first',
'SETBIT' => 'self::first',
'GETBIT' => 'self::first',
'RPUSHX' => 'self::first',
'LPUSHX' => 'self::first',
'LINSERT' => 'self::first',
'BRPOPLPUSH' => 'self::skipLast',
'ZREVRANGEBYSCORE' => 'self::first',
'WATCH' => 'self::all',
'PERSIST' => 'static::first',
'STRLEN' => 'static::first',
'SETRANGE' => 'static::first',
'GETRANGE' => 'static::first',
'SETBIT' => 'static::first',
'GETBIT' => 'static::first',
'RPUSHX' => 'static::first',
'LPUSHX' => 'static::first',
'LINSERT' => 'static::first',
'BRPOPLPUSH' => 'static::skipLast',
'ZREVRANGEBYSCORE' => 'static::first',
'WATCH' => 'static::all',
/* ---------------- Redis 2.6 ---------------- */
'PTTL' => 'self::first',
'PEXPIRE' => 'self::first',
'PEXPIREAT' => 'self::first',
'PSETEX' => 'self::first',
'INCRBYFLOAT' => 'self::first',
'BITOP' => 'self::skipFirst',
'BITCOUNT' => 'self::first',
'HINCRBYFLOAT' => 'self::first',
'EVAL' => 'self::evalKeys',
'EVALSHA' => 'self::evalKeys',
'PTTL' => 'static::first',
'PEXPIRE' => 'static::first',
'PEXPIREAT' => 'static::first',
'PSETEX' => 'static::first',
'INCRBYFLOAT' => 'static::first',
'BITOP' => 'static::skipFirst',
'BITCOUNT' => 'static::first',
'HINCRBYFLOAT' => 'static::first',
'EVAL' => 'static::evalKeys',
'EVALSHA' => 'static::evalKeys',
'MIGRATE' => 'static::migrate',
/* ---------------- Redis 2.8 ---------------- */
'SSCAN' => 'self::first',
'ZSCAN' => 'self::first',
'HSCAN' => 'self::first',
'PFADD' => 'self::first',
'PFCOUNT' => 'self::all',
'PFMERGE' => 'self::all',
'ZLEXCOUNT' => 'self::first',
'ZRANGEBYLEX' => 'self::first',
'ZREMRANGEBYLEX' => 'self::first',
'ZREVRANGEBYLEX' => 'self::first',
'SSCAN' => 'static::first',
'ZSCAN' => 'static::first',
'HSCAN' => 'static::first',
'PFADD' => 'static::first',
'PFCOUNT' => 'static::all',
'PFMERGE' => 'static::all',
'ZLEXCOUNT' => 'static::first',
'ZRANGEBYLEX' => 'static::first',
'ZREMRANGEBYLEX' => 'static::first',
'ZREVRANGEBYLEX' => 'static::first',
'BITPOS' => 'static::first',
/* ---------------- Redis 3.2 ---------------- */
'HSTRLEN' => 'static::first',
);
}
@@ -218,8 +221,8 @@ class KeyPrefixProcessor implements ProcessorInterface
}
if (!is_callable($callback)) {
throw new InvalidArgumentException(
"Callback must be a valid callable object or NULL"
throw new \InvalidArgumentException(
'Callback must be a valid callable object or NULL'
);
}
@@ -295,7 +298,7 @@ class KeyPrefixProcessor implements ProcessorInterface
if ($arguments = $command->getArguments()) {
$length = count($arguments);
for ($i = 1; $i < $length; $i++) {
for ($i = 1; $i < $length; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
@@ -314,7 +317,7 @@ class KeyPrefixProcessor implements ProcessorInterface
if ($arguments = $command->getArguments()) {
$length = count($arguments);
for ($i = 0; $i < $length - 1; $i++) {
for ($i = 0; $i < $length - 1; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
@@ -334,7 +337,7 @@ class KeyPrefixProcessor implements ProcessorInterface
$arguments[0] = "$prefix{$arguments[0]}";
if (($count = count($arguments)) > 1) {
for ($i = 1; $i < $count; $i++) {
for ($i = 1; $i < $count; ++$i) {
switch ($arguments[$i]) {
case 'BY':
case 'STORE':
@@ -368,7 +371,7 @@ class KeyPrefixProcessor implements ProcessorInterface
public static function evalKeys(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
for ($i = 2; $i < $arguments[1] + 2; $i++) {
for ($i = 2; $i < $arguments[1] + 2; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
@@ -388,11 +391,25 @@ class KeyPrefixProcessor implements ProcessorInterface
$arguments[0] = "$prefix{$arguments[0]}";
$length = ((int) $arguments[1]) + 2;
for ($i = 2; $i < $length; $i++) {
for ($i = 2; $i < $length; ++$i) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$command->setRawArguments($arguments);
}
}
/**
* Applies the specified prefix to the key of a MIGRATE command.
*
* @param CommandInterface $command Command instance.
* @param string $prefix Prefix string.
*/
public static function migrate(CommandInterface $command, $prefix)
{
if ($arguments = $command->getArguments()) {
$arguments[2] = "$prefix{$arguments[2]}";
$command->setRawArguments($arguments);
}
}
}

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