Explorar o código

Backported changes from the mainline library to the PHP 5.2 branch (up to commit bd961a7)

Daniele Alessandri %!s(int64=14) %!d(string=hai) anos
pai
achega
49e151a3d0
Modificáronse 4 ficheiros con 107 adicións e 27 borrados
  1. 23 12
      CHANGELOG
  2. 1 1
      VERSION
  3. 48 14
      lib/Predis.php
  4. 35 0
      test/RedisCommandsTest.php

+ 23 - 12
CHANGELOG

@@ -1,13 +1,21 @@
-v0.6.1 (2010-xx-xx)
+v0.6.1 (2010-07-11)
+  * Minor internal improvements and clean ups.
+
   * New commands available in the Redis v2.2 profile (dev):
       - Misc.  : WATCH, UNWATCH
 
-  * Minor internal improvements and clean ups.
+  * Optional modifiers for ZRANGE, ZREVRANGE and ZRANGEBYSCORE queries are
+    supported using an associative array passed as the last argument of their
+    respective methods.
 
-  * The constructor of Predis_Client::__construct now accepts also instances
-    of Predis_ConnectionParameters.
+  * The LIMIT modifier for ZRANGEBYSCORE can be specified using either:
+      - an indexed array: array($offset, $count)
+      - an associative array: array('offset' => $offset, 'count' => $count)
 
-  * Predis_MultiExecBlock and Predis_PubSubContext will throw an exception
+  * The method Predis_Client::__construct() now accepts also instances of
+    Predis_ConnectionParameters.
+
+  * Predis_MultiExecBlock and Predis_PubSubContext now throw an exception
     when trying to create their instances using a profile that does not
     support the required Redis commands or when the client is connected to
     a cluster of connections.
@@ -17,14 +25,17 @@ v0.6.1 (2010-xx-xx)
       - support for WATCH and UNWATCH when using the current development
         profile (Redis v2.2) and aborted transactions.
 
-  * New method signature for Predis_Client::multiExec(). Now it is able to
-    accept an array of options for the underlying Predis_MultiExecBlock, but
-    it is still backwards compatible with previous releases of Predis.
+  * New signature for Predis_Client::multiExec() which is now able to accept
+    an array of options for the underlying instance of Predis_MultiExecBlock.
+    Backwards compatibility with previous releases of Predis is ensured.
+
+  * New signature for Predis_Client::pipeline() which is now able to accept
+    an array of options for the underlying instance of Predis_CommandPipeline.
+    Backwards compatibility with previous releases of Predis is ensured.
+    The method Predis_Client::pipelineSafe() is to be considered deprecated.
 
-  * New method signature for Predis_Client::pipeline(). Now it is able to
-    accept an array of options for the underlying Predis_CommandPipeline,
-    but it is still backwards compatible with previous releases of Predis.
-    Predis_Client::pipelineSafe() is to be considered obsolete.
+  * FIX: The WEIGHT modifier for ZUNIONSTORE and ZINTERSTORE was handled
+    incorrectly with more than two weights specified.
 
 v0.6.0 (2010-05-24)
   * Switched to the new multi-bulk request protocol for all of the commands 

+ 1 - 1
VERSION

@@ -1 +1 @@
-0.6.0
+0.6.1

+ 48 - 14
lib/Predis.php

@@ -56,7 +56,7 @@ class Predis_Client {
             throw new Predis_ClientException('Missing connection parameters');
         }
 
-        return new Predis_Client($argc === 1 ? $argv[0] : $argv, $serverProfile);
+        return new Predis_Client($argc === 1 ? $argv[0] : $argv, $options);
     }
 
     private static function filterClientOptions($options) {
@@ -2546,8 +2546,9 @@ class Predis_Commands_ZSetUnionStore extends Predis_MultiBulkCommand {
         $finalizedOpts = array();
         if (isset($opts['WEIGHTS']) && is_array($opts['WEIGHTS'])) {
             $finalizedOpts[] = 'WEIGHTS';
-            $finalizedOpts[] = $opts['WEIGHTS'][0];
-            $finalizedOpts[] = $opts['WEIGHTS'][1];
+            foreach ($opts['WEIGHTS'] as $weight) {
+                $finalizedOpts[] = $weight;
+            }
         }
         if (isset($opts['AGGREGATE'])) {
             $finalizedOpts[] = 'AGGREGATE';
@@ -2562,21 +2563,43 @@ class Predis_Commands_ZSetIntersectionStore extends Predis_Commands_ZSetUnionSto
 }
 
 class Predis_Commands_ZSetRange extends Predis_MultiBulkCommand {
+    private $_withScores = false;
     public function getCommandId() { return 'ZRANGE'; }
-    public function parseResponse($data) {
-        $arguments = $this->getArguments();
+    public function filterArguments(Array $arguments) {
         if (count($arguments) === 4) {
-            if (strtolower($arguments[3]) === 'withscores') {
-                if ($data instanceof Iterator) {
-                    return new Predis_Shared_MultiBulkResponseKVIterator($data);
-                }
-                $result = array();
-                for ($i = 0; $i < count($data); $i++) {
-                    $result[] = array($data[$i], $data[++$i]);
-                }
-                return $result;
+            $lastType = gettype($arguments[3]);
+            if ($lastType === 'string' && strtolower($arguments[3]) === 'withscores') {
+                // used for compatibility with older versions
+                $arguments[3] = array('WITHSCORES' => true);
+                $lastType = 'array';
+            }
+            if ($lastType === 'array') {
+                $options = $this->prepareOptions(array_pop($arguments));
+                return array_merge($arguments, $options);
             }
         }
+        return $arguments;
+    }
+    protected function prepareOptions($options) {
+        $opts = array_change_key_case($options, CASE_UPPER);
+        $finalizedOpts = array();
+        if (isset($opts['WITHSCORES'])) {
+            $finalizedOpts[] = 'WITHSCORES';
+            $this->_withScores = true;
+        }
+        return $finalizedOpts;
+    }
+    public function parseResponse($data) {
+        if ($this->_withScores) {
+            if ($data instanceof Iterator) {
+                return new Predis_Shared_MultiBulkResponseKVIterator($data);
+            }
+            $result = array();
+            for ($i = 0; $i < count($data); $i++) {
+                $result[] = array($data[$i], $data[++$i]);
+            }
+            return $result;
+        }
         return $data;
     }
 }
@@ -2587,6 +2610,17 @@ class Predis_Commands_ZSetReverseRange extends Predis_Commands_ZSetRange {
 
 class Predis_Commands_ZSetRangeByScore extends Predis_Commands_ZSetRange {
     public function getCommandId() { return 'ZRANGEBYSCORE'; }
+    protected function prepareOptions($options) {
+        $opts = array_change_key_case($options, CASE_UPPER);
+        $finalizedOpts = array();
+        if (isset($opts['LIMIT']) && is_array($opts['LIMIT'])) {
+            $limit = array_change_key_case($opts['LIMIT'], CASE_UPPER);
+            $finalizedOpts[] = 'LIMIT';
+            $finalizedOpts[] = isset($limit['OFFSET']) ? $limit['OFFSET'] : $limit[0];
+            $finalizedOpts[] = isset($limit['COUNT']) ? $limit['COUNT'] : $limit[1];
+        }
+        return array_merge($finalizedOpts, parent::prepareOptions($options));
+    }
 }
 
 class Predis_Commands_ZSetCount extends Predis_MultiBulkCommand {

+ 35 - 0
test/RedisCommandsTest.php

@@ -1097,6 +1097,11 @@ class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
             $this->redis->zrange('zset', 0, 2, 'withscores')
         );
 
+        $this->assertEquals(
+            array(array('a', -10), array('b', 0), array('c', 10)), 
+            $this->redis->zrange('zset', 0, 2, array('withscores' => true))
+        );
+
         RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, p_anon("\$test", "
             \$test->redis->set('foo', 'bar');
             \$test->redis->zrange('foo', 0, -1);
@@ -1151,6 +1156,36 @@ class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
             $this->redis->zrevrange('zset', 0, 2, 'withscores')
         );
 
+        $this->assertEquals(
+            array(array('f', 30), array('e', 20), array('d', 20)), 
+            $this->redis->zrevrange('zset', 0, 2, array('withscores' => true))
+        );
+
+        $this->assertEquals(
+            array(array('c', 10), array('d', 20), array('e', 20)), 
+            $this->redis->zrangebyscore('zset', 10, 20, array('withscores' => true))
+        );
+
+        $this->assertEquals(
+            array('d', 'e'), 
+            $this->redis->zrangebyscore('zset', 10, 20, array('limit' => array(1, 2)))
+        );
+
+        $this->assertEquals(
+            array('d', 'e'), 
+            $this->redis->zrangebyscore('zset', 10, 20, array(
+                'limit' => array('offset' => 1, 'count' => 2)
+            ))
+        );
+
+        $this->assertEquals(
+            array(array('d', 20), array('e', 20)), 
+            $this->redis->zrangebyscore('zset', 10, 20, array(
+                'limit'      => array(1, 2), 
+                'withscores' => true, 
+            ))
+        );
+
         RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, p_anon("\$test", "
             \$test->redis->set('foo', 'bar');
             \$test->redis->zrevrange('foo', 0, -1);