diff --git a/composer.json b/composer.json index ee0766a..4cc1743 100644 --- a/composer.json +++ b/composer.json @@ -69,6 +69,7 @@ "yiisoft/yii2-debug": "self.version", "yiisoft/yii2-gii": "self.version", "yiisoft/yii2-jui": "self.version", + "yiisoft/yii2-redis": "self.version", "yiisoft/yii2-smarty": "self.version", "yiisoft/yii2-swiftmailer": "self.version", "yiisoft/yii2-sphinx": "self.version", @@ -95,6 +96,7 @@ "yii\\debug\\": "extensions/debug/", "yii\\gii\\": "extensions/gii/", "yii\\jui\\": "extensions/jui/", + "yii\\redis\\": "extensions/redis/", "yii\\smarty\\": "extensions/smarty/", "yii\\swiftmailer\\": "extensions/swiftmailer/", "yii\\sphinx\\": "extensions/sphinx/", diff --git a/framework/yii/redis/ActiveQuery.php b/extensions/redis/ActiveQuery.php similarity index 100% rename from framework/yii/redis/ActiveQuery.php rename to extensions/redis/ActiveQuery.php diff --git a/framework/yii/redis/ActiveRecord.php b/extensions/redis/ActiveRecord.php similarity index 100% rename from framework/yii/redis/ActiveRecord.php rename to extensions/redis/ActiveRecord.php diff --git a/framework/yii/redis/ActiveRelation.php b/extensions/redis/ActiveRelation.php similarity index 100% rename from framework/yii/redis/ActiveRelation.php rename to extensions/redis/ActiveRelation.php diff --git a/extensions/redis/Cache.php b/extensions/redis/Cache.php new file mode 100644 index 0000000..f1a21ed --- /dev/null +++ b/extensions/redis/Cache.php @@ -0,0 +1,184 @@ + [ + * 'cache' => [ + * 'class' => 'yii\redis\Cache', + * ], + * 'redis' => [ + * 'class' => 'yii\redis\Connection', + * 'hostname' => 'localhost', + * 'port' => 6379, + * 'database' => 0, + * ] + * ], + * ] + * ~~~ + * + * @property Connection $connection The redis connection object. This property is read-only. + * + * @author Carsten Brandt + * @since 2.0 + */ +class Cache extends \yii\caching\Cache +{ + /** + * @var string the id of the application component to use as the redis connection. + * It should be configured as a [[yii\redis\Connection]]. Defaults to `redis`. + */ + public $connectionId = 'redis'; + + + /** + * Checks whether a specified key exists in the cache. + * This can be faster than getting the value from the cache if the data is big. + * Note that this method does not check whether the dependency associated + * with the cached data, if there is any, has changed. So a call to [[get]] + * may return false while exists returns true. + * @param mixed $key a key identifying the cached value. This can be a simple string or + * a complex data structure consisting of factors representing the key. + * @return boolean true if a value exists in cache, false if the value is not in the cache or expired. + */ + public function exists($key) + { + /** @var Connection $connection */ + $connection = \Yii::$app->getComponent($this->connectionId); + return (bool) $connection->executeCommand('EXISTS', [$this->buildKey($key)]); + } + + /** + * @inheritDocs + */ + protected function getValue($key) + { + /** @var Connection $connection */ + $connection = \Yii::$app->getComponent($this->connectionId); + return $connection->executeCommand('GET', [$key]); + } + + /** + * @inheritDocs + */ + protected function getValues($keys) + { + /** @var Connection $connection */ + $connection = \Yii::$app->getComponent($this->connectionId); + $response = $connection->executeCommand('MGET', $keys); + $result = []; + $i = 0; + foreach ($keys as $key) { + $result[$key] = $response[$i++]; + } + return $result; + } + + /** + * @inheritDocs + */ + protected function setValue($key, $value, $expire) + { + /** @var Connection $connection */ + $connection = \Yii::$app->getComponent($this->connectionId); + if ($expire == 0) { + return (bool) $connection->executeCommand('SET', [$key, $value]); + } else { + $expire = (int) ($expire * 1000); + return (bool) $connection->executeCommand('SET', [$key, $value, 'PX', $expire]); + } + } + + /** + * @inheritDocs + */ + protected function setValues($data, $expire) + { + /** @var Connection $connection */ + $connection = \Yii::$app->getComponent($this->connectionId); + + $args = []; + foreach($data as $key => $value) { + $args[] = $key; + $args[] = $value; + } + + $failedKeys = []; + if ($expire == 0) { + $connection->executeCommand('MSET', $args); + } else { + $expire = (int) ($expire * 1000); + $connection->executeCommand('MULTI'); + $connection->executeCommand('MSET', $args); + $index = []; + foreach ($data as $key => $value) { + $connection->executeCommand('PEXPIRE', [$key, $expire]); + $index[] = $key; + } + $result = $connection->executeCommand('EXEC'); + array_shift($result); + foreach($result as $i => $r) { + if ($r != 1) { + $failedKeys[] = $index[$i]; + } + } + } + return $failedKeys; + } + + /** + * @inheritDocs + */ + protected function addValue($key, $value, $expire) + { + /** @var Connection $connection */ + $connection = \Yii::$app->getComponent($this->connectionId); + if ($expire == 0) { + return (bool) $connection->executeCommand('SET', [$key, $value, 'NX']); + } else { + $expire = (int) ($expire * 1000); + return (bool) $connection->executeCommand('SET', [$key, $value, 'PX', $expire, 'NX']); + } + } + + /** + * @inheritDocs + */ + protected function deleteValue($key) + { + /** @var Connection $connection */ + $connection = \Yii::$app->getComponent($this->connectionId); + return (bool) $connection->executeCommand('DEL', [$key]); + } + + /** + * @inheritDocs + */ + protected function flushValues() + { + /** @var Connection $connection */ + $connection = \Yii::$app->getComponent($this->connectionId); + return $connection->executeCommand('FLUSHDB'); + } +} diff --git a/framework/yii/redis/Connection.php b/extensions/redis/Connection.php similarity index 88% rename from framework/yii/redis/Connection.php rename to extensions/redis/Connection.php index 371b8bc..cea559f 100644 --- a/framework/yii/redis/Connection.php +++ b/extensions/redis/Connection.php @@ -13,6 +13,15 @@ use yii\db\Exception; use yii\helpers\Inflector; /** + * The redis connection class is used to establish a connection to a [redis](http://redis.io/) server. + * + * By default it assumes there is a redis server running on localhost at port 6379 and uses the database number 0. + * + * It also supports [the AUTH command](http://redis.io/commands/auth) of redis. + * When the server needs authentication, you can set the [[password]] property to + * authenticate with the server after connect. + * + * The ecexution of [redis commands](http://redis.io/commands) is possible with via [[executeCommand()]]. * * @method mixed set($key, $value) Set the string value of a key * @method mixed get($key) Set the string value of a key @@ -33,20 +42,23 @@ class Connection extends Component const EVENT_AFTER_OPEN = 'afterOpen'; /** - * @var string the Data Source Name, or DSN, contains the information required to connect to the database. - * DSN format: redis://server:port[/db] - * Where db is a zero based integer which refers to the DB to use. - * If no DB is given, ID 0 is used. - * - * Example: redis://localhost:6379/2 + * @var string the hostname or ip address to use for connecting to the redis server. Defaults to 'localhost'. */ - public $dsn; + public $hostname = 'localhost'; + /** + * @var int the port to use for connecting to the redis server. Default port is 6379. + */ + public $port = 6379; /** * @var string the password for establishing DB connection. Defaults to null meaning no AUTH command is send. * See http://redis.io/commands/auth */ public $password; /** + * @var int the redis database to use. This is an integer value starting from 0. Defaults to 0. + */ + public $database = 0; + /** * @var float timeout to use for connection to redis. If not set the timeout set in php.ini will be used: ini_get("default_socket_timeout") */ public $connectionTimeout = null; @@ -230,38 +242,30 @@ class Connection extends Component */ public function open() { - if ($this->_socket === null) { - if (empty($this->dsn)) { - throw new InvalidConfigException('Connection.dsn cannot be empty.'); - } - $dsn = explode('/', $this->dsn); - $host = $dsn[2]; - if (strpos($host, ':')===false) { - $host .= ':6379'; + if ($this->_socket !== null) { + return; + } + $connection = $this->hostname . ':' . $this->port . ', database=' . $this->database; + \Yii::trace('Opening redis DB connection: ' . $connection, __CLASS__); + $this->_socket = @stream_socket_client( + 'tcp://' . $this->hostname . ':' . $this->port, + $errorNumber, + $errorDescription, + $this->connectionTimeout ? $this->connectionTimeout : ini_get("default_socket_timeout") + ); + if ($this->_socket) { + if ($this->dataTimeout !== null) { + stream_set_timeout($this->_socket, $timeout=(int)$this->dataTimeout, (int) (($this->dataTimeout - $timeout) * 1000000)); } - $db = isset($dsn[3]) ? $dsn[3] : 0; - - \Yii::trace('Opening DB connection: ' . $this->dsn, __CLASS__); - $this->_socket = @stream_socket_client( - $host, - $errorNumber, - $errorDescription, - $this->connectionTimeout ? $this->connectionTimeout : ini_get("default_socket_timeout") - ); - if ($this->_socket) { - if ($this->dataTimeout !== null) { - stream_set_timeout($this->_socket, $timeout=(int)$this->dataTimeout, (int) (($this->dataTimeout - $timeout) * 1000000)); - } - if ($this->password !== null) { - $this->executeCommand('AUTH', [$this->password]); - } - $this->executeCommand('SELECT', [$db]); - $this->initConnection(); - } else { - \Yii::error("Failed to open DB connection ({$this->dsn}): " . $errorNumber . ' - ' . $errorDescription, __CLASS__); - $message = YII_DEBUG ? 'Failed to open DB connection: ' . $errorNumber . ' - ' . $errorDescription : 'Failed to open DB connection.'; - throw new Exception($message, $errorDescription, (int)$errorNumber); + if ($this->password !== null) { + $this->executeCommand('AUTH', [$this->password]); } + $this->executeCommand('SELECT', [$this->database]); + $this->initConnection(); + } else { + \Yii::error("Failed to open DB connection ($connection): " . $errorNumber . ' - ' . $errorDescription, __CLASS__); + $message = YII_DEBUG ? 'Failed to open DB connection: ' . $errorNumber . ' - ' . $errorDescription : 'Failed to open DB connection.'; + throw new Exception($message, $errorDescription, (int)$errorNumber); } } @@ -272,7 +276,8 @@ class Connection extends Component public function close() { if ($this->_socket !== null) { - \Yii::trace('Closing DB connection: ' . $this->dsn, __CLASS__); + $connection = $this->hostname . ':' . $this->port . ', database=' . $this->database; + \Yii::trace('Closing DB connection: ' . $connection, __CLASS__); $this->executeCommand('QUIT'); stream_socket_shutdown($this->_socket, STREAM_SHUT_RDWR); $this->_socket = null; @@ -295,11 +300,7 @@ class Connection extends Component */ public function getDriverName() { - if (($pos = strpos($this->dsn, ':')) !== false) { - return strtolower(substr($this->dsn, 0, $pos)); - } else { - return 'redis'; - } + return 'redis'; } /** diff --git a/extensions/redis/LICENSE.md b/extensions/redis/LICENSE.md new file mode 100644 index 0000000..e98f03d --- /dev/null +++ b/extensions/redis/LICENSE.md @@ -0,0 +1,32 @@ +The Yii framework is free software. It is released under the terms of +the following BSD License. + +Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Yii Software LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/framework/yii/redis/LuaScriptBuilder.php b/extensions/redis/LuaScriptBuilder.php similarity index 100% rename from framework/yii/redis/LuaScriptBuilder.php rename to extensions/redis/LuaScriptBuilder.php diff --git a/extensions/redis/README.md b/extensions/redis/README.md new file mode 100644 index 0000000..28cecf1 --- /dev/null +++ b/extensions/redis/README.md @@ -0,0 +1,91 @@ +Redis Cache and ActiveRecord for Yii 2 +====================================== + +This extension provides the [redis](http://redis.io/) key-value store support for the Yii2 framework. +It includes a `Cache` class and implents the `ActiveRecord` pattern that allows you to store active +records in redis. + +To use this extension, you have to configure the Connection class in your application configuration: + +```php +return [ + //.... + 'components' => [ + 'redis' => [ + 'class' => 'yii\redis\Connection', + 'hostname' => 'localhost', + 'port' => 6379, + 'database' => 0, + ], + ] +]; +``` + +To use the `Cache` component, you also have to configure the `cache` component to be `yii\redis\Cache`: + +```php +return [ + //.... + 'components' => [ + // ... + 'cache' => [ + 'class' => 'yii\redis\Cache', + ], + ] +]; +``` + + +Installation +------------ + +The preferred way to install this extension is through [composer](http://getcomposer.org/download/). + +Either run + +``` +php composer.phar require yiisoft/yii2-redis "*" +``` + +or add + +```json +"yiisoft/yii2-redis": "*" +``` + +to the require section of your composer.json. + + +Using the redis ActiveRecord +---------------------------- + +For general information on how to use yii's ActiveRecord please refer to the [guide](https://github.com/yiisoft/yii2/blob/master/docs/guide/active-record.md). + +For defining a redis ActiveRecord class your record class needs to extend from `yii\redis\ActiveRecord` and +implement at least the `attributes()` method to define the attributes of the record. +A primary key can be defined via [[primaryKey()]] which defaults to `id` if not specified. +The primaryKey needs to be part of the attributes so make sure you have an `id` attribute defined if you do +not specify your own primary key. + +The following is an example model called `Customer`: + +```php +class Customer extends \yii\redis\ActiveRecord +{ + public function attributes() + { + return ['id', 'name', 'address', 'registration_date']; + } +} +``` + +The general usage of redis ActiveRecord is very similar to the database ActiveRecord as described in the +[guide](https://github.com/yiisoft/yii2/blob/master/docs/guide/active-record.md). +It supports the same interface and features except the following limitations: + +- As redis does not support SQL the query API is limited to the following methods: + `where()`, `limit()`, `offset()`, `orderBy()` and `indexBy()`. + (orderBy() is not yet implemented: [#1305](https://github.com/yiisoft/yii2/issues/1305)) +- `via`-relations can not be defined via a table as there are not tables in redis. You can only define relations via other records. + +It is also possible to define relations from redis ActiveRecords to normal ActiveRecord classes and vice versa. \ No newline at end of file diff --git a/extensions/redis/composer.json b/extensions/redis/composer.json new file mode 100644 index 0000000..fb5065b --- /dev/null +++ b/extensions/redis/composer.json @@ -0,0 +1,27 @@ +{ + "name": "yiisoft/yii2-redis", + "description": "Redis Cache and ActiveRecord for the Yii framework", + "keywords": ["yii", "redis", "active-record", "cache"], + "type": "yii2-extension", + "license": "BSD-3-Clause", + "support": { + "issues": "https://github.com/yiisoft/yii2/issues?labels=ext%3Aredis", + "forum": "http://www.yiiframework.com/forum/", + "wiki": "http://www.yiiframework.com/wiki/", + "irc": "irc://irc.freenode.net/yii", + "source": "https://github.com/yiisoft/yii2" + }, + "authors": [ + { + "name": "Carsten Brandt", + "email": "mail@cebe.cc" + } + ], + "require": { + "yiisoft/yii2": "*" + }, + "autoload": { + "psr-0": { "yii\\redis\\": "" } + }, + "target-dir": "yii/redis" +} diff --git a/extensions/sphinx/composer.json b/extensions/sphinx/composer.json index 0331667..decac2f 100644 --- a/extensions/sphinx/composer.json +++ b/extensions/sphinx/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/yii2-sphinx", "description": "Sphinx full text search engine extension for the Yii framework", - "keywords": ["yii", "sphinx", "search", "fulltext"], + "keywords": ["yii", "sphinx", "active-record", "search", "fulltext"], "type": "yii2-extension", "license": "BSD-3-Clause", "support": { diff --git a/framework/yii/caching/RedisCache.php b/framework/yii/caching/RedisCache.php deleted file mode 100644 index b64f000..0000000 --- a/framework/yii/caching/RedisCache.php +++ /dev/null @@ -1,218 +0,0 @@ - [ - * 'cache' => [ - * 'class' => 'RedisCache', - * 'hostname' => 'localhost', - * 'port' => 6379, - * 'database' => 0, - * ], - * ], - * ] - * ~~~ - * - * @property Connection $connection The redis connection object. This property is read-only. - * - * @author Carsten Brandt - * @since 2.0 - */ -class RedisCache extends Cache -{ - /** - * @var string hostname to use for connecting to the redis server. Defaults to 'localhost'. - */ - public $hostname = 'localhost'; - /** - * @var int the port to use for connecting to the redis server. Default port is 6379. - */ - public $port = 6379; - /** - * @var string the password to use to authenticate with the redis server. If not set, no AUTH command will be sent. - */ - public $password; - /** - * @var int the redis database to use. This is an integer value starting from 0. Defaults to 0. - */ - public $database = 0; - /** - * @var float timeout to use for connection to redis. If not set the timeout set in php.ini will be used: ini_get("default_socket_timeout") - */ - public $connectionTimeout = null; - /** - * @var float timeout to use for redis socket when reading and writing data. If not set the php default value will be used. - */ - public $dataTimeout = null; - /** - * @var Connection the redis connection - */ - private $_connection; - - - /** - * Initializes the cache component by establishing a connection to the redis server. - */ - public function init() - { - parent::init(); - $this->getConnection(); - } - - /** - * Returns the redis connection object. - * Establishes a connection to the redis server if it does not already exists. - * @return Connection the redis connection object. - */ - public function getConnection() - { - if ($this->_connection === null) { - $this->_connection = new Connection([ - 'dsn' => 'redis://' . $this->hostname . ':' . $this->port . '/' . $this->database, - 'password' => $this->password, - 'connectionTimeout' => $this->connectionTimeout, - 'dataTimeout' => $this->dataTimeout, - ]); - } - return $this->_connection; - } - - /** - * Checks whether a specified key exists in the cache. - * This can be faster than getting the value from the cache if the data is big. - * Note that this method does not check whether the dependency associated - * with the cached data, if there is any, has changed. So a call to [[get]] - * may return false while exists returns true. - * @param mixed $key a key identifying the cached value. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return boolean true if a value exists in cache, false if the value is not in the cache or expired. - */ - public function exists($key) - { - return (bool) $this->_connection->executeCommand('EXISTS', [$this->buildKey($key)]); - } - - /** - * @inheritDocs - */ - protected function getValue($key) - { - return $this->_connection->executeCommand('GET', [$key]); - } - - /** - * @inheritDocs - */ - protected function getValues($keys) - { - $response = $this->_connection->executeCommand('MGET', $keys); - $result = []; - $i = 0; - foreach ($keys as $key) { - $result[$key] = $response[$i++]; - } - return $result; - } - - /** - * @inheritDocs - */ - protected function setValue($key, $value, $expire) - { - if ($expire == 0) { - return (bool) $this->_connection->executeCommand('SET', [$key, $value]); - } else { - $expire = (int) ($expire * 1000); - return (bool) $this->_connection->executeCommand('SET', [$key, $value, 'PX', $expire]); - } - } - - /** - * @inheritDocs - */ - protected function setValues($data, $expire) - { - $args = []; - foreach($data as $key => $value) { - $args[] = $key; - $args[] = $value; - } - - $failedKeys = []; - if ($expire == 0) { - $this->_connection->executeCommand('MSET', $args); - } else { - $expire = (int) ($expire * 1000); - $this->_connection->executeCommand('MULTI'); - $this->_connection->executeCommand('MSET', $args); - $index = []; - foreach ($data as $key => $value) { - $this->_connection->executeCommand('PEXPIRE', [$key, $expire]); - $index[] = $key; - } - $result = $this->_connection->executeCommand('EXEC'); - array_shift($result); - foreach($result as $i => $r) { - if ($r != 1) { - $failedKeys[] = $index[$i]; - } - } - } - return $failedKeys; - } - - /** - * @inheritDocs - */ - protected function addValue($key, $value, $expire) - { - if ($expire == 0) { - return (bool) $this->_connection->executeCommand('SET', [$key, $value, 'NX']); - } else { - $expire = (int) ($expire * 1000); - return (bool) $this->_connection->executeCommand('SET', [$key, $value, 'PX', $expire, 'NX']); - } - } - - /** - * @inheritDocs - */ - protected function deleteValue($key) - { - return (bool) $this->_connection->executeCommand('DEL', [$key]); - } - - /** - * @inheritDocs - */ - protected function flushValues() - { - return $this->_connection->executeCommand('FLUSHDB'); - } -} diff --git a/framework/yii/classes.php b/framework/yii/classes.php index 9f39ee9..c8b2935 100644 --- a/framework/yii/classes.php +++ b/framework/yii/classes.php @@ -61,7 +61,6 @@ return [ 'yii\caching\GroupDependency' => YII_PATH . '/caching/GroupDependency.php', 'yii\caching\MemCache' => YII_PATH . '/caching/MemCache.php', 'yii\caching\MemCacheServer' => YII_PATH . '/caching/MemCacheServer.php', - 'yii\caching\RedisCache' => YII_PATH . '/caching/RedisCache.php', 'yii\caching\WinCache' => YII_PATH . '/caching/WinCache.php', 'yii\caching\XCache' => YII_PATH . '/caching/XCache.php', 'yii\caching\ZendDataCache' => YII_PATH . '/caching/ZendDataCache.php', @@ -168,8 +167,6 @@ return [ 'yii\rbac\Item' => YII_PATH . '/rbac/Item.php', 'yii\rbac\Manager' => YII_PATH . '/rbac/Manager.php', 'yii\rbac\PhpManager' => YII_PATH . '/rbac/PhpManager.php', - 'yii\redis\Connection' => YII_PATH . '/redis/Connection.php', - 'yii\redis\Transaction' => YII_PATH . '/redis/Transaction.php', 'yii\requirements\YiiRequirementChecker' => YII_PATH . '/requirements/YiiRequirementChecker.php', 'yii\test\DbFixtureManager' => YII_PATH . '/test/DbFixtureManager.php', 'yii\test\DbTestTrait' => YII_PATH . '/test/DbTestTrait.php', diff --git a/tests/unit/data/config.php b/tests/unit/data/config.php index 13a1026..28e5abe 100644 --- a/tests/unit/data/config.php +++ b/tests/unit/data/config.php @@ -30,7 +30,9 @@ return [ 'fixture' => __DIR__ . '/postgres.sql', ], 'redis' => [ - 'dsn' => 'redis://localhost:6379/0', + 'hostname' => 'localhost', + 'port' => 6379, + 'database' => 0, 'password' => null, ], ], diff --git a/tests/unit/framework/redis/ActiveRecordTest.php b/tests/unit/extensions/redis/ActiveRecordTest.php similarity index 99% rename from tests/unit/framework/redis/ActiveRecordTest.php rename to tests/unit/extensions/redis/ActiveRecordTest.php index 31907f7..74dd49e 100644 --- a/tests/unit/framework/redis/ActiveRecordTest.php +++ b/tests/unit/extensions/redis/ActiveRecordTest.php @@ -1,8 +1,7 @@ 'localhost', - 'port' => 6379, - 'database' => 0, - 'dataTimeout' => 0.1, - ]; - $dsn = $config['hostname'] . ':' .$config['port']; - if (!@stream_socket_client($dsn, $errorNumber, $errorDescription, 0.5)) { - $this->markTestSkipped('No redis server running at ' . $dsn .' : ' . $errorNumber . ' - ' . $errorDescription); + $databases = $this->getParam('databases'); + $params = isset($databases['redis']) ? $databases['redis'] : null; + if ($params === null) { + $this->markTestSkipped('No redis server connection configured.'); } + $connection = new Connection($params); + if(!@stream_socket_client($connection->hostname . ':' . $connection->port, $errorNumber, $errorDescription, 0.5)) { + $this->markTestSkipped('No redis server running at ' . $connection->hostname . ':' . $connection->port . ' : ' . $errorNumber . ' - ' . $errorDescription); + } + + $this->mockApplication(['components' => ['redis' => $connection]]); if ($this->_cacheInstance === null) { - $this->_cacheInstance = new RedisCache($config); + $this->_cacheInstance = new Cache(); } return $this->_cacheInstance; } diff --git a/tests/unit/framework/redis/RedisConnectionTest.php b/tests/unit/extensions/redis/RedisConnectionTest.php similarity index 66% rename from tests/unit/framework/redis/RedisConnectionTest.php rename to tests/unit/extensions/redis/RedisConnectionTest.php index af39e0e..7a6bd91 100644 --- a/tests/unit/framework/redis/RedisConnectionTest.php +++ b/tests/unit/extensions/redis/RedisConnectionTest.php @@ -1,6 +1,6 @@ open(); - } - - /** * test connection to redis and selection of db */ public function testConnect() { - $db = new Connection(); - $db->dsn = 'redis://localhost:6379'; + $db = $this->getConnection(false); $db->open(); $this->assertTrue($db->ping()); $db->set('YIITESTKEY', 'YIITESTVALUE'); $db->close(); - $db = new Connection(); - $db->dsn = 'redis://localhost:6379/0'; + $db = $this->getConnection(false); + $db->database = 0; $db->open(); $this->assertEquals('YIITESTVALUE', $db->get('YIITESTKEY')); $db->close(); - $db = new Connection(); - $db->dsn = 'redis://localhost:6379/1'; + $db = $this->getConnection(false); + $db->database = 1; $db->open(); $this->assertNull($db->get('YIITESTKEY')); $db->close(); diff --git a/tests/unit/framework/redis/RedisTestCase.php b/tests/unit/extensions/redis/RedisTestCase.php similarity index 50% rename from tests/unit/framework/redis/RedisTestCase.php rename to tests/unit/extensions/redis/RedisTestCase.php index 12e539d..ed4dccd 100644 --- a/tests/unit/framework/redis/RedisTestCase.php +++ b/tests/unit/extensions/redis/RedisTestCase.php @@ -1,10 +1,13 @@ mockApplication(); - $databases = $this->getParam('databases'); $params = isset($databases['redis']) ? $databases['redis'] : null; - if ($params === null || !isset($params['dsn'])) { + if ($params === null) { $this->markTestSkipped('No redis server connection configured.'); } - $dsn = explode('/', $params['dsn']); - $host = $dsn[2]; - if (strpos($host, ':')===false) { - $host .= ':6379'; - } - if(!@stream_socket_client($host, $errorNumber, $errorDescription, 0.5)) { - $this->markTestSkipped('No redis server running at ' . $params['dsn'] . ' : ' . $errorNumber . ' - ' . $errorDescription); + $connection = new Connection($params); + if(!@stream_socket_client($connection->hostname . ':' . $connection->port, $errorNumber, $errorDescription, 0.5)) { + $this->markTestSkipped('No redis server running at ' . $connection->hostname . ':' . $connection->port . ' : ' . $errorNumber . ' - ' . $errorDescription); } + $this->mockApplication(['components' => ['redis' => $connection]]); + parent::setUp(); } @@ -38,13 +37,11 @@ abstract class RedisTestCase extends TestCase public function getConnection($reset = true) { $databases = $this->getParam('databases'); - $params = isset($databases['redis']) ? $databases['redis'] : array(); - $db = new Connection; - $db->dsn = $params['dsn']; - $db->password = $params['password']; + $params = isset($databases['redis']) ? $databases['redis'] : []; + $db = new Connection($params); if ($reset) { $db->open(); - $db->flushall(); + $db->flushdb(); } return $db; }