diff --git a/README.md b/README.md index 51144d7..250b22e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Add this line in your `composer.json` : ```json { "require": { - "m6web/redis-mock": "~1.2" + "m6web/redis-mock": "~2.0" } } ``` @@ -88,7 +88,10 @@ $factory = new \M6Web\Component\RedisMock\RedisMockFactory(); $myRedisMock = $factory->getAdapter('My\Redis\Library'); ``` -**WARNING !** *RedisMock doesn't implement all Redis features and commands. The mock can have undesired behavior if your parent class uses unsupported features.* +**WARNING !** + + * *RedisMock doesn't implement all Redis features and commands. The mock can have undesired behavior if your parent class uses unsupported features.* + * *Storage is static and therefore shared by all instances.* *Note : the factory will throw an exception by default if your parent class implements unsupported commands. If you want even so partially use the mock, you can specify the second parameter when you build it `$factory->getAdapter('My\Redis\Library', true)`. The exception will then thrown only when the command is called.* diff --git a/src/M6Web/Component/RedisMock/RedisMock.php b/src/M6Web/Component/RedisMock/RedisMock.php index d1768eb..e097da0 100644 --- a/src/M6Web/Component/RedisMock/RedisMock.php +++ b/src/M6Web/Component/RedisMock/RedisMock.php @@ -10,53 +10,53 @@ */ class RedisMock { - protected $data = array(); - protected $dataTypes = array(); - protected $dataTtl = array(); - protected $pipeline = false; - protected $savedPipeline = false; - protected $pipedInfo = array(); + protected static $data = array(); + protected static $dataTypes = array(); + protected static $dataTtl = array(); + protected $pipeline = false; + protected $savedPipeline = false; + protected $pipedInfo = array(); public function reset() { - $this->data = array(); + self::$data = array(); return $this; } public function getData() { - return $this->data; + return self::$data; } public function getDataTtl() { - return $this->dataTtl; + return self::$dataTtl; } public function getDataTypes() { - return $this->dataTypes; + return self::$dataTypes; } // Strings public function get($key) { - if (!isset($this->data[$key]) || is_array($this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || is_array(self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(null); } - return $this->returnPipedInfo($this->data[$key]); + return $this->returnPipedInfo(self::$data[$key]); } public function set($key, $value, $seconds = null) { - $this->data[$key] = $value; - $this->dataTypes[$key] = 'string'; + self::$data[$key] = $value; + self::$dataTypes[$key] = 'string'; if (!is_null($seconds)) { - $this->dataTtl[$key] = time() + $seconds; + self::$dataTtl[$key] = time() + $seconds; } return $this->returnPipedInfo('OK'); @@ -78,24 +78,24 @@ public function setnx($key, $value) public function ttl($key) { - if (!array_key_exists($key, $this->data) || $this->deleteOnTtlExpired($key)) { + if (!array_key_exists($key, self::$data) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(-2); } - if (!array_key_exists($key, $this->dataTtl)) { + if (!array_key_exists($key, self::$dataTtl)) { return $this->returnPipedInfo(-1); } - return $this->returnPipedInfo($this->dataTtl[$key] - time()); + return $this->returnPipedInfo(self::$dataTtl[$key] - time()); } public function expire($key, $seconds) { - if (!array_key_exists($key, $this->data) || $this->deleteOnTtlExpired($key)) { + if (!array_key_exists($key, self::$data) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(0); } - $this->dataTtl[$key] = time() + $seconds; + self::$dataTtl[$key] = time() + $seconds; return $this->returnPipedInfo(1); } @@ -109,17 +109,17 @@ public function incrby($key, $increment) { $this->deleteOnTtlExpired($key); - if (!isset($this->data[$key])) { - $this->data[$key] = (int) $increment; - } elseif (!is_integer($this->data[$key])) { + if (!isset(self::$data[$key])) { + self::$data[$key] = (int) $increment; + } elseif (!is_integer(self::$data[$key])) { return $this->returnPipedInfo(null); } else { - $this->data[$key] += (int) $increment; + self::$data[$key] += (int) $increment; } - $this->dataTypes[$key] = 'string'; + self::$dataTypes[$key] = 'string'; - return $this->returnPipedInfo($this->data[$key]); + return $this->returnPipedInfo(self::$data[$key]); } public function decr($key) @@ -131,17 +131,17 @@ public function decrby($key, $decrement) { $this->deleteOnTtlExpired($key); - if (!isset($this->data[$key])) { - $this->data[$key] = 0; - } elseif (!is_integer($this->data[$key])) { + if (!isset(self::$data[$key])) { + self::$data[$key] = 0; + } elseif (!is_integer(self::$data[$key])) { return $this->returnPipedInfo(null); } - $this->data[$key] -= (int) $decrement; + self::$data[$key] -= (int) $decrement; - $this->dataTypes[$key] = 'string'; + self::$dataTypes[$key] = 'string'; - return $this->returnPipedInfo($this->data[$key]); + return $this->returnPipedInfo(self::$data[$key]); } // Keys @@ -152,8 +152,8 @@ public function type($key) return $this->returnPipedInfo('none'); } - if (array_key_exists($key, $this->dataTypes)) { - return $this->returnPipedInfo($this->dataTypes[$key]); + if (array_key_exists($key, self::$dataTypes)) { + return $this->returnPipedInfo(self::$dataTypes[$key]); } else { return $this->returnPipedInfo('none'); } @@ -165,7 +165,7 @@ public function exists($key) return $this->returnPipedInfo(false); } - return $this->returnPipedInfo(array_key_exists($key, $this->data)); + return $this->returnPipedInfo(array_key_exists($key, self::$data)); } public function del($key) @@ -178,12 +178,12 @@ public function del($key) $deletedKeyCount = 0; foreach ( $keys as $k ) { - if ( isset($this->data[$k]) ) { - $deletedKeyCount += count($this->data[$k]); - unset($this->data[$k]); - unset($this->dataTypes[$k]); - if (array_key_exists($k, $this->dataTtl)) { - unset($this->dataTtl[$k]); + if ( isset(self::$data[$k]) ) { + $deletedKeyCount += count(self::$data[$k]); + unset(self::$data[$k]); + unset(self::$dataTypes[$k]); + if (array_key_exists($k, self::$dataTtl)) { + unset(self::$dataTtl[$k]); } } } @@ -196,7 +196,7 @@ public function keys($pattern) $pattern = preg_replace(array('#\*#', '#\?#', '#(\[[^\]]+\])#'), array('.*', '.', '$1+'), $pattern); $results = array(); - foreach ($this->data as $key => $value) { + foreach (self::$data as $key => $value) { if (preg_match('#^' . $pattern . '$#', $key) and !$this->deleteOnTtlExpired($key)) { $results[] = $key; } @@ -215,20 +215,20 @@ public function sadd($key, $member) $this->deleteOnTtlExpired($key); - if (isset($this->data[$key]) && !is_array($this->data[$key])) { + if (isset(self::$data[$key]) && !is_array(self::$data[$key])) { return $this->returnPipedInfo(null); } - $isNew = !isset($this->data[$key]) || !in_array($member, $this->data[$key]); + $isNew = !isset(self::$data[$key]) || !in_array($member, self::$data[$key]); if ($isNew) { - $this->data[$key][] = $member; + self::$data[$key][] = $member; } - $this->dataTypes[$key] = 'set'; + self::$dataTypes[$key] = 'set'; - if (array_key_exists($key, $this->dataTtl)) { - unset($this->dataTtl[$key]); + if (array_key_exists($key, self::$dataTtl)) { + unset(self::$dataTtl[$key]); } return $this->returnPipedInfo((int) $isNew); @@ -236,11 +236,11 @@ public function sadd($key, $member) public function smembers($key) { - if (!isset($this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(array()); } - return $this->returnPipedInfo($this->data[$key]); + return $this->returnPipedInfo(self::$data[$key]); } public function srem($key, $member) @@ -249,14 +249,14 @@ public function srem($key, $member) throw new UnsupportedException('In RedisMock, `srem` command can not remove more than one member at once.'); } - if (!isset($this->data[$key]) || !in_array($member, $this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || !in_array($member, self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(0); } - $this->data[$key] = array_diff($this->data[$key], array($member)); + self::$data[$key] = array_diff(self::$data[$key], array($member)); - if (0 === count($this->data[$key])) { - unset($this->dataTypes[$key]); + if (0 === count(self::$data[$key])) { + unset(self::$dataTypes[$key]); } return $this->returnPipedInfo(1); @@ -264,7 +264,7 @@ public function srem($key, $member) public function sismember($key, $member) { - if (!isset($this->data[$key]) || !in_array($member, $this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || !in_array($member, self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(0); } @@ -275,11 +275,11 @@ public function sismember($key, $member) public function lrem($key, $count, $value) { - if (!isset($this->data[$key]) || !in_array($value, $this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || !in_array($value, self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(0); } - $arr = $this->data[$key]; + $arr = self::$data[$key]; $reversed = false; if ($count < 0) { @@ -299,80 +299,80 @@ public function lrem($key, $count, $value) return true; }); - $deletedItems = count($this->data[$key]) - count($arr); + $deletedItems = count(self::$data[$key]) - count($arr); if ($reversed) { $arr = array_reverse($arr); } - $this->data[$key] = array_values($arr); + self::$data[$key] = array_values($arr); return $this->returnPipedInfo($deletedItems); } public function lpush($key, $value) { - if ($this->deleteOnTtlExpired($key) || !isset($this->data[$key])) { - $this->data[$key] = array(); + if ($this->deleteOnTtlExpired($key) || !isset(self::$data[$key])) { + self::$data[$key] = array(); } - if (isset($this->data[$key]) && !is_array($this->data[$key])) { + if (isset(self::$data[$key]) && !is_array(self::$data[$key])) { return $this->returnPipedInfo(null); } - array_unshift($this->data[$key], $value); + array_unshift(self::$data[$key], $value); - return $this->returnPipedInfo(count($this->data[$key])); + return $this->returnPipedInfo(count(self::$data[$key])); } public function rpush($key, $value) { - if ($this->deleteOnTtlExpired($key) || !isset($this->data[$key])) { - $this->data[$key] = array(); + if ($this->deleteOnTtlExpired($key) || !isset(self::$data[$key])) { + self::$data[$key] = array(); } - if (isset($this->data[$key]) && !is_array($this->data[$key])) { + if (isset(self::$data[$key]) && !is_array(self::$data[$key])) { return $this->returnPipedInfo(null); } - array_push($this->data[$key], $value); + array_push(self::$data[$key], $value); - return $this->returnPipedInfo(count($this->data[$key])); + return $this->returnPipedInfo(count(self::$data[$key])); } public function lpop($key) { - if (!isset($this->data[$key]) || !is_array($this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || !is_array(self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(null); } - return $this->returnPipedInfo(array_shift($this->data[$key])); + return $this->returnPipedInfo(array_shift(self::$data[$key])); } public function rpop($key) { - if (!isset($this->data[$key]) || !is_array($this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || !is_array(self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(null); } - return $this->returnPipedInfo(array_pop($this->data[$key])); + return $this->returnPipedInfo(array_pop(self::$data[$key])); } public function ltrim($key, $start, $stop) { $this->deleteOnTtlExpired($key); - if (isset($this->data[$key]) && !is_array($this->data[$key])) { + if (isset(self::$data[$key]) && !is_array(self::$data[$key])) { return $this->returnPipedInfo(null); - } elseif (!isset($this->data[$key])) { + } elseif (!isset(self::$data[$key])) { return $this->returnPipedInfo('OK'); } if ($start < 0) { - if (abs($start) > count($this->data[$key])) { + if (abs($start) > count(self::$data[$key])) { $start = 0; } else { - $start = count($this->data[$key]) + $start; + $start = count(self::$data[$key]) + $start; } } @@ -386,9 +386,9 @@ public function ltrim($key, $start, $stop) } } - $this->data[$key] = array_slice($this->data[$key], $start, $length); + self::$data[$key] = array_slice(self::$data[$key], $start, $length); - if (!count($this->data[$key])) { + if (!count(self::$data[$key])) { $this->stopPipeline(); $this->del($key); $this->restorePipeline(); @@ -401,15 +401,15 @@ public function lrange($key, $start, $stop) { $this->deleteOnTtlExpired($key); - if (!isset($this->data[$key]) || !is_array($this->data[$key])) { + if (!isset(self::$data[$key]) || !is_array(self::$data[$key])) { return $this->returnPipedInfo(array()); } if ($start < 0) { - if (abs($start) > count($this->data[$key])) { + if (abs($start) > count(self::$data[$key])) { $start = 0; } else { - $start = count($this->data[$key]) + $start; + $start = count(self::$data[$key]) + $start; } } @@ -423,7 +423,7 @@ public function lrange($key, $start, $stop) } } - $data = array_slice($this->data[$key], $start, $length); + $data = array_slice(self::$data[$key], $start, $length); return $this->returnPipedInfo($data); } @@ -434,16 +434,16 @@ public function hset($key, $field, $value) { $this->deleteOnTtlExpired($key); - if (isset($this->data[$key]) && !is_array($this->data[$key])) { + if (isset(self::$data[$key]) && !is_array(self::$data[$key])) { return $this->returnPipedInfo(null); } - $isNew = !isset($this->data[$key]) || !isset($this->data[$key][$field]); + $isNew = !isset(self::$data[$key]) || !isset(self::$data[$key][$field]); - $this->data[$key][$field] = $value; - $this->dataTypes[$key] = 'hash'; - if (array_key_exists($key, $this->dataTtl)) { - unset($this->dataTtl[$key]); + self::$data[$key][$field] = $value; + self::$dataTypes[$key] = 'hash'; + if (array_key_exists($key, self::$dataTtl)) { + unset(self::$dataTtl[$key]); } return $this->returnPipedInfo((int) $isNew); @@ -453,7 +453,7 @@ public function hmset($key, $pairs) { $this->deleteOnTtlExpired($key); - if (isset($this->data[$key]) && !is_array($this->data[$key])) { + if (isset(self::$data[$key]) && !is_array(self::$data[$key])) { return $this->returnPipedInfo(null); } @@ -469,20 +469,20 @@ public function hmset($key, $pairs) public function hget($key, $field) { - if (!isset($this->data[$key][$field]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key][$field]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(null); } - return $this->returnPipedInfo($this->data[$key][$field]); + return $this->returnPipedInfo(self::$data[$key][$field]); } public function hmget($key, $fields) { foreach ($fields as $field) { - if (!isset($this->data[$key][$field]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key][$field]) || $this->deleteOnTtlExpired($key)) { $result[$field] = null; } else { - $result[$field] = $this->data[$key][$field]; + $result[$field] = self::$data[$key][$field]; } } @@ -495,18 +495,18 @@ public function hdel($key, $field) throw new UnsupportedException('In RedisMock, `hdel` command can not delete more than one entry at once.'); } - if (isset($this->data[$key]) && !is_array($this->data[$key])) { + if (isset(self::$data[$key]) && !is_array(self::$data[$key])) { return $this->returnPipedInfo(null); } - if (!array_key_exists($key, $this->data) || $this->deleteOnTtlExpired($key)) { + if (!array_key_exists($key, self::$data) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(0); } - if (array_key_exists($field, $this->data[$key])) { - unset($this->data[$key][$field]); - if (0 === count($this->data[$key])) { - unset($this->dataTypes[$key]); + if (array_key_exists($field, self::$data[$key])) { + unset(self::$data[$key][$field]); + if (0 === count(self::$data[$key])) { + unset(self::$dataTypes[$key]); } return $this->returnPipedInfo(1); @@ -517,25 +517,25 @@ public function hdel($key, $field) public function hgetall($key) { - if (!isset($this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(array()); } - return $this->returnPipedInfo($this->data[$key]); + return $this->returnPipedInfo(self::$data[$key]); } public function hexists($key, $field) { $this->deleteOnTtlExpired($key); - return $this->returnPipedInfo((int) isset($this->data[$key][$field])); + return $this->returnPipedInfo((int) isset(self::$data[$key][$field])); } // Sorted set public function zrange($key, $start, $stop, $withscores = false) { - if (!isset($this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(array()); } @@ -566,7 +566,7 @@ public function zrange($key, $start, $stop, $withscores = false) public function zrevrange($key, $start, $stop, $withscores = false) { - if (!isset($this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(array()); } @@ -597,20 +597,20 @@ public function zrevrange($key, $start, $stop, $withscores = false) protected function zrangebyscoreHelper($key, $min, $max, array $options = array(), $rev = false) { - if (!isset($this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(array()); } - if (!is_array($this->data[$key])) { + if (!is_array(self::$data[$key])) { return $this->returnPipedInfo(null); } if (!isset($options['limit']) || !is_array($options['limit']) || count($options['limit']) != 2) { - $options['limit'] = array(0, count($this->data[$key])); + $options['limit'] = array(0, count(self::$data[$key])); } - $set = $this->data[$key]; - uksort($this->data[$key], function($a, $b) use ($set, $rev) { + $set = self::$data[$key]; + uksort(self::$data[$key], function($a, $b) use ($set, $rev) { if ($set[$a] > $set[$b]) { return $rev ? -1 : 1; } elseif ($set[$a] < $set[$b]) { @@ -621,7 +621,7 @@ protected function zrangebyscoreHelper($key, $min, $max, array $options = array( }); if ($min == '-inf' && $max == '+inf') { - $slice = array_slice($this->data[$key], $options['limit'][0], $options['limit'][1], true); + $slice = array_slice(self::$data[$key], $options['limit'][0], $options['limit'][1], true); if (isset($options['withscores']) && $options['withscores']) { return $this->returnPipedInfo($slice); } else { @@ -646,7 +646,7 @@ protected function zrangebyscoreHelper($key, $min, $max, array $options = array( }; $results = array(); - foreach ($this->data[$key] as $k => $v) { + foreach (self::$data[$key] as $k => $v) { if ($min == '-inf' && $isInfMax($v)) { $results[$k] = $v; } elseif ($max == '+inf' && $isSupMin($v)) { @@ -686,24 +686,24 @@ public function zadd($key, $score, $member) { $this->deleteOnTtlExpired($key); - if (isset($this->data[$key]) && !is_array($this->data[$key])) { + if (isset(self::$data[$key]) && !is_array(self::$data[$key])) { return $this->returnPipedInfo(null); } - $isNew = !isset($this->data[$key][$member]); + $isNew = !isset(self::$data[$key][$member]); - $this->data[$key][$member] = (int) $score; - $this->dataTypes[$key] = 'zset'; - if (array_key_exists($key, $this->dataTtl)) + self::$data[$key][$member] = (int) $score; + self::$dataTypes[$key] = 'zset'; + if (array_key_exists($key, self::$dataTtl)) { - unset($this->dataTtl[$key]); + unset(self::$dataTtl[$key]); } return $this->returnPipedInfo((int) $isNew); } public function zremrangebyscore($key, $min, $max) { - if (!isset($this->data[$key]) || $this->deleteOnTtlExpired($key)) { + if (!isset(self::$data[$key]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(0); } @@ -729,14 +729,14 @@ public function zrem($key, $member) { throw new UnsupportedException('In RedisMock, `zrem` command can not remove more than one member at once.'); } - if (isset($this->data[$key]) && !is_array($this->data[$key]) || !isset($this->data[$key][$member]) || $this->deleteOnTtlExpired($key)) { + if (isset(self::$data[$key]) && !is_array(self::$data[$key]) || !isset(self::$data[$key][$member]) || $this->deleteOnTtlExpired($key)) { return $this->returnPipedInfo(0); } - unset($this->data[$key][$member]); + unset(self::$data[$key][$member]); - if (0 === count($this->data[$key])) { - unset($this->dataTypes[$key]); + if (0 === count(self::$data[$key])) { + unset(self::$dataTypes[$key]); } return $this->returnPipedInfo(1); @@ -828,7 +828,7 @@ protected function returnPipedInfo($info) protected function deleteOnTtlExpired($key) { - if (array_key_exists($key, $this->dataTtl) and (time() > $this->dataTtl[$key])) { + if (array_key_exists($key, self::$dataTtl) and (time() > self::$dataTtl[$key])) { // clean datas $this->stopPipeline(); $this->del($key);