diff --git a/composer.json b/composer.json index 99f8bf0..3f91aa3 100644 --- a/composer.json +++ b/composer.json @@ -22,10 +22,13 @@ }, "require": { "php": ">=5.4", - "cakephp/cache": "^3.0", + "cakephp/cache": "^4.0", "predis/predis": "^1.0" }, "require-dev": { "phpunit/phpunit": "^4.8" + }, + "scripts": { + "test": "./vendor/bin/phpunit" } } diff --git a/src/PredisEngine.php b/src/PredisEngine.php index c7898ef..cfdf7d3 100644 --- a/src/PredisEngine.php +++ b/src/PredisEngine.php @@ -2,6 +2,7 @@ namespace Renan\Cake\Predis; use Cake\Cache\CacheEngine; +use Cake\Cache\InvalidArgumentException; use Predis\Client; use Predis\ClientInterface; @@ -45,7 +46,7 @@ final class PredisEngine extends CacheEngine * @param array $config Associative array of parameters for the engine * @return bool True if the engine has been successfully initialized, false if not */ - public function init(array $config = []) + public function init(array $config = []): bool { parent::init($config); @@ -56,109 +57,129 @@ public function init(array $config = []) } /** - * Write value for a key into cache + * Increment a number under the key and return incremented value * * @param string $key Identifier for the data - * @param mixed $value Data to be cached - * @return bool True if the data was successfully cached, false on failure + * @param int $offset How much to add + * @return bool|int New incremented value, false otherwise */ - public function write($key, $value) + public function increment(string $key, int $offset = 1) { $key = $this->_key($key); - $value = is_int($value) - ? (int) $value - : serialize($value); - - if ($this->_config['duration'] === 0) { - return (string) $this->client->set($key, $value) === 'OK'; + if (! $this->client->exists($key)) { + return false; } - return (string) $this->client->setex($key, $this->_config['duration'], $value) === 'OK'; + return $this->client->incrby($key, $offset); } /** - * Read a key from the cache + * Decrement a number under the key and return decremented value * * @param string $key Identifier for the data - * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it + * @param int $offset How much to subtract + * @return bool|int New incremented value, false otherwise */ - public function read($key) + public function decrement(string $key, int $offset = 1) { $key = $this->_key($key); - $value = $this->client->get($key); - - if ($value === null) { + if (! $this->client->exists($key)) { return false; } - return ctype_digit($value) - ? (int) $value - : unserialize($value); + return $this->client->decrby($key, $offset); } /** - * Increment a number under the key and return incremented value + * Delete a key from the cache * * @param string $key Identifier for the data - * @param int $offset How much to add - * @return bool|int New incremented value, false otherwise + * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ - public function increment($key, $offset = 1) + public function delete($key): bool { $key = $this->_key($key); if (! $this->client->exists($key)) { return false; } - return $this->client->incrby($key, $offset); + return $this->client->del($key) === 1; } /** - * Decrement a number under the key and return decremented value + * Delete all keys from the cache * - * @param string $key Identifier for the data - * @param int $offset How much to subtract - * @return bool|int New incremented value, false otherwise + * @return bool True if the cache was successfully cleared, false otherwise */ - public function decrement($key, $offset = 1) + public function clear(): bool { - $key = $this->_key($key); - if (! $this->client->exists($key)) { - return false; + $keys = $this->client->keys($this->_config['prefix'] . '*'); + foreach ($keys as $key) { + $this->client->del($key); } - return $this->client->decrby($key, $offset); + return true; } /** - * Delete a key from the cache + * Fetches the value for a given key from the cache. * - * @param string $key Identifier for the data - * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed + * @param string $key The unique key of this item in the cache. + * @param mixed $default Default value to return if the key does not exist. + * @return mixed The value of the item from the cache, or $default in case of cache miss. + * @throws InvalidArgumentException If the $key string is not a legal value. */ - public function delete($key) + public function get($key, $default = null) { $key = $this->_key($key); - if (! $this->client->exists($key)) { - return false; + $value = $this->client->get($key); + + if ($value === null) { + return $default; } - return $this->client->del($key) === 1; + return ctype_digit($value) + ? (int) $value + : unserialize($value); } /** - * Delete all keys from the cache + * Persists data in the cache, uniquely referenced by the given key with an optional expiration TTL time. * - * @param bool $check if true will check expiration, otherwise delete all - * @return bool True if the cache was successfully cleared, false otherwise + * @param string $key The key of the item to store. + * @param mixed $value The value of the item to store, must be serializable. + * @param \DateInterval|int|null $ttl Optional. The TTL value of this item. If no value is sent and + * the driver supports TTL then the library may set a default value + * for it or let the driver take care of that. + * @return bool True on success and false on failure. + * @throws InvalidArgumentException + * MUST be thrown if the $key string is not a legal value. */ - public function clear($check) + public function set($key, $value, $ttl = null): bool { - if ($check) { - return true; + $key = $this->_key($key); + $value = is_int($value) + ? (int) $value + : serialize($value); + + if ($this->_config['duration'] === 0) { + return (string) $this->client->set($key, $value) === 'OK'; } - $keys = $this->client->keys($this->_config['prefix'] . '*'); + return (string) $this->client->setex($key, $this->_config['duration'], $value) === 'OK'; + } + + /** + * Clears all values belonging to a group. Is up to the implementing engine + * to decide whether actually delete the keys or just simulate it to achieve + * the same result. + * + * @param string $group name of the group to be cleared + * @return bool + */ + public function clearGroup(string $group): bool + { + $keys = $this->client->keys($this->_config['prefix'] . $group . "*"); foreach ($keys as $key) { $this->client->del($key); } diff --git a/tests/PredisEngineTest.php b/tests/PredisEngineTest.php index 9dcd45a..e1c962a 100644 --- a/tests/PredisEngineTest.php +++ b/tests/PredisEngineTest.php @@ -28,11 +28,11 @@ public function tearDown() */ public function testWriteAndReadDataTypesAndThenDelete($value) { - $this->assertTrue($this->engine->write('dataType', $value)); - $this->assertEquals($value, $this->engine->read('dataType')); + $this->assertTrue($this->engine->set('dataType', $value)); + $this->assertEquals($value, $this->engine->get('dataType')); $this->assertTrue($this->engine->delete('dataType')); - $this->assertFalse($this->engine->read('dataType')); + $this->assertFalse($this->engine->get('dataType', false)); } public function writeAndReadDataTypes() @@ -51,7 +51,7 @@ public function testIncrement() { $this->assertFalse($this->engine->increment('key')); - $this->assertTrue($this->engine->write('key', 10)); + $this->assertTrue($this->engine->set('key', 10)); $this->assertEquals(11, $this->engine->increment('key')); $this->assertEquals(12, $this->engine->increment('key')); $this->assertEquals(13, $this->engine->increment('key')); @@ -61,7 +61,7 @@ public function testDecrement() { $this->assertFalse($this->engine->decrement('key')); - $this->assertTrue($this->engine->write('key', 10)); + $this->assertTrue($this->engine->set('key', 10)); $this->assertEquals(9, $this->engine->decrement('key')); $this->assertEquals(8, $this->engine->decrement('key')); $this->assertEquals(7, $this->engine->decrement('key'));