Commit 60d9e04c by Qiang Xue

Merge pull request #1438 from klimov-paul/mongo

MongoDB integration
parents 4b2659ae 062e138c
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mongo;
use yii\db\ActiveQueryInterface;
use yii\db\ActiveQueryTrait;
/**
* ActiveQuery represents a Mongo query associated with an Active Record class.
*
* ActiveQuery instances are usually created by [[ActiveRecord::find()]].
*
* Because ActiveQuery extends from [[Query]], one can use query methods, such as [[where()]],
* [[orderBy()]] to customize the query options.
*
* ActiveQuery also provides the following additional query options:
*
* - [[with()]]: list of relations that this query should be performed with.
* - [[asArray()]]: whether to return each record as an array.
*
* These options can be configured using methods of the same name. For example:
*
* ~~~
* $customers = Customer::find()->with('orders')->asArray()->all();
* ~~~
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class ActiveQuery extends Query implements ActiveQueryInterface
{
use ActiveQueryTrait;
/**
* Executes query and returns all results as an array.
* @param Connection $db the Mongo connection used to execute the query.
* If null, the Mongo connection returned by [[modelClass]] will be used.
* @return array the query results. If the query results in nothing, an empty array will be returned.
*/
public function all($db = null)
{
$cursor = $this->buildCursor($db);
$rows = $this->fetchRows($cursor);
if (!empty($rows)) {
$models = $this->createModels($rows);
if (!empty($this->with)) {
$this->findWith($this->with, $models);
}
return $models;
} else {
return [];
}
}
/**
* Executes query and returns a single row of result.
* @param Connection $db the Mongo connection used to execute the query.
* If null, the Mongo connection returned by [[modelClass]] will be used.
* @return ActiveRecord|array|null a single row of query result. Depending on the setting of [[asArray]],
* the query result may be either an array or an ActiveRecord object. Null will be returned
* if the query results in nothing.
*/
public function one($db = null)
{
$row = parent::one($db);
if ($row !== false) {
if ($this->asArray) {
$model = $row;
} else {
/** @var ActiveRecord $class */
$class = $this->modelClass;
$model = $class::create($row);
}
if (!empty($this->with)) {
$models = [$model];
$this->findWith($this->with, $models);
$model = $models[0];
}
return $model;
} else {
return null;
}
}
/**
* Returns the Mongo collection for this query.
* @param Connection $db Mongo connection.
* @return Collection collection instance.
*/
public function getCollection($db = null)
{
/** @var ActiveRecord $modelClass */
$modelClass = $this->modelClass;
if ($db === null) {
$db = $modelClass::getDb();
}
if ($this->from === null) {
$this->from = $modelClass::collectionName();
}
return $db->getCollection($this->from);
}
}
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mongo;
use yii\db\ActiveRelationInterface;
use yii\db\ActiveRelationTrait;
/**
* ActiveRelation represents a relation to Mongo Active Record class.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class ActiveRelation extends ActiveQuery implements ActiveRelationInterface
{
use ActiveRelationTrait;
}
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mongo;
use yii\base\Component;
use yii\base\InvalidConfigException;
use Yii;
/**
* Connection represents a connection to a MongoDb server.
*
* Connection works together with [[Database]] and [[Collection]] to provide data access
* to the Mongo database. They are wrappers of the [[MongoDB PHP extension]](http://us1.php.net/manual/en/book.mongo.php).
*
* To establish a DB connection, set [[dsn]] and then call [[open()]] to be true.
*
* The following example shows how to create a Connection instance and establish
* the DB connection:
*
* ~~~
* $connection = new \yii\mongo\Connection([
* 'dsn' => $dsn,
* ]);
* $connection->open();
* ~~~
*
* After the Mongo connection is established, one can access Mongo databases and collections:
*
* ~~~
* $database = $connection->getDatabase('my_mongo_db');
* $collection = $database->getCollection('customer');
* $collection->insert(['name' => 'John Smith', 'status' => 1]);
* ~~~
*
* You can work with several different databases at the same server using this class.
* However, while it is unlikely your application will actually need it, the Connection class
* provides ability to use [[defaultDatabaseName]] as well as a shortcut method [[getCollection()]]
* to retrieve a particular collection instance:
*
* ~~~
* // get collection 'customer' from default database:
* $collection = $connection->getCollection('customer');
* // get collection 'customer' from database 'mydatabase':
* $collection = $connection->getCollection(['mydatabase', 'customer']);
* ~~~
*
* Connection is often used as an application component and configured in the application
* configuration like the following:
*
* ~~~
* [
* 'components' => [
* 'mongo' => [
* 'class' => '\yii\mongo\Connection',
* 'dsn' => 'mongodb://developer:password@localhost:27017/mydatabase',
* ],
* ],
* ]
* ~~~
*
* @property boolean $isActive Whether the Mongo connection is established. This property is read-only.
* is read-only.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class Connection extends Component
{
/**
* @var string host:port
*
* Correct syntax is:
* mongodb://[username:password@]host1[:port1][,host2[:port2:],...][/dbname]
* For example:
* mongodb://localhost:27017
* mongodb://developer:password@localhost:27017
* mongodb://developer:password@localhost:27017/mydatabase
*/
public $dsn;
/**
* @var array connection options.
* for example:
* ~~~
* [
* 'persist' => true, // use persistent connection
* 'socketTimeoutMS' => 1000, // how long a send or receive on a socket can take before timing out
* 'journal' => true // block write operations until the journal be flushed the to disk
* ]
* ~~~
*/
public $options = [];
/**
* @var string name of the Mongo database to use by default.
* If this field left blank, connection instance will attempt to determine it from
* [[options]] and [[dsn]] automatically, if needed.
*/
public $defaultDatabaseName;
/**
* @var \MongoClient mongo client instance.
*/
public $mongoClient;
/**
* @var Database[] list of Mongo databases
*/
private $_databases = [];
/**
* Returns the Mongo collection with the given name.
* @param string|null $name collection name, if null default one will be used.
* @param boolean $refresh whether to reload the table schema even if it is found in the cache.
* @return Database database instance.
*/
public function getDatabase($name = null, $refresh = false)
{
if ($name === null) {
$name = $this->fetchDefaultDatabaseName();
}
if ($refresh || !array_key_exists($name, $this->_databases)) {
$this->_databases[$name] = $this->selectDatabase($name);
}
return $this->_databases[$name];
}
/**
* Returns [[defaultDatabaseName]] value, if it is not set,
* attempts to determine it from [[dsn]] value.
* @return string default database name
* @throws \yii\base\InvalidConfigException if unable to determine default database name.
*/
protected function fetchDefaultDatabaseName()
{
if ($this->defaultDatabaseName === null) {
if (isset($this->options['db'])) {
$this->defaultDatabaseName = $this->options['db'];
} elseif (preg_match('/^mongodb:\\/\\/.+\\/(.+)$/s', $this->dsn, $matches)) {
$this->defaultDatabaseName = $matches[1];
} else {
throw new InvalidConfigException("Unable to determine default database name from dsn.");
}
}
return $this->defaultDatabaseName;
}
/**
* Selects the database with given name.
* @param string $name database name.
* @return Database database instance.
*/
protected function selectDatabase($name)
{
$this->open();
return Yii::createObject([
'class' => 'yii\mongo\Database',
'mongoDb' => $this->mongoClient->selectDB($name)
]);
}
/**
* Returns the Mongo collection with the given name.
* @param string|array $name collection name. If string considered as the name of the collection
* inside the default database. If array - first element considered as the name of the database,
* second - as name of collection inside that database
* @param boolean $refresh whether to reload the collection instance even if it is found in the cache.
* @return Collection Mongo collection instance.
*/
public function getCollection($name, $refresh = false)
{
if (is_array($name)) {
list ($dbName, $collectionName) = $name;
return $this->getDatabase($dbName)->getCollection($collectionName, $refresh);
} else {
return $this->getDatabase()->getCollection($name, $refresh);
}
}
/**
* Returns the Mongo GridFS collection.
* @param string|array $prefix collection prefix. If string considered as the prefix of the GridFS
* collection inside the default database. If array - first element considered as the name of the database,
* second - as prefix of the GridFS collection inside that database, if no second element present
* default "fs" prefix will be used.
* @param boolean $refresh whether to reload the collection instance even if it is found in the cache.
* @return file\Collection Mongo GridFS collection instance.
*/
public function getFileCollection($prefix = 'fs', $refresh = false)
{
if (is_array($prefix)) {
list ($dbName, $collectionPrefix) = $prefix;
if (!isset($collectionPrefix)) {
$collectionPrefix = 'fs';
}
return $this->getDatabase($dbName)->getFileCollection($collectionPrefix, $refresh);
} else {
return $this->getDatabase()->getFileCollection($prefix, $refresh);
}
}
/**
* Returns a value indicating whether the Mongo connection is established.
* @return boolean whether the Mongo connection is established
*/
public function getIsActive()
{
return is_object($this->mongoClient) && $this->mongoClient->connected;
}
/**
* Establishes a Mongo connection.
* It does nothing if a Mongo connection has already been established.
* @throws Exception if connection fails
*/
public function open()
{
if ($this->mongoClient === null) {
if (empty($this->dsn)) {
throw new InvalidConfigException($this->className() . '::dsn cannot be empty.');
}
$token = 'Opening Mongo connection: ' . $this->dsn;
try {
Yii::trace($token, __METHOD__);
Yii::beginProfile($token, __METHOD__);
$options = $this->options;
$options['connect'] = true;
if ($this->defaultDatabaseName !== null) {
$options['db'] = $this->defaultDatabaseName;
}
$this->mongoClient = new \MongoClient($this->dsn, $options);
Yii::endProfile($token, __METHOD__);
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
}
}
/**
* Closes the currently active DB connection.
* It does nothing if the connection is already closed.
*/
public function close()
{
if ($this->mongoClient !== null) {
Yii::trace('Closing Mongo connection: ' . $this->dsn, __METHOD__);
$this->mongoClient = null;
$this->_databases = [];
}
}
}
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mongo;
use yii\base\Object;
use Yii;
use yii\helpers\Json;
/**
* Database represents the Mongo database information.
*
* @property string $name name of this database. This property is read-only.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class Database extends Object
{
/**
* @var \MongoDB Mongo database instance.
*/
public $mongoDb;
/**
* @var Collection[] list of collections.
*/
private $_collections = [];
/**
* @var file\Collection[] list of GridFS collections.
*/
private $_fileCollections = [];
/**
* @return string name of this database.
*/
public function getName()
{
return $this->mongoDb->__toString();
}
/**
* Returns the Mongo collection with the given name.
* @param string $name collection name
* @param boolean $refresh whether to reload the collection instance even if it is found in the cache.
* @return Collection mongo collection instance.
*/
public function getCollection($name, $refresh = false)
{
if ($refresh || !array_key_exists($name, $this->_collections)) {
$this->_collections[$name] = $this->selectCollection($name);
}
return $this->_collections[$name];
}
/**
* Returns Mongo GridFS collection with given prefix.
* @param string $prefix collection prefix.
* @param boolean $refresh whether to reload the collection instance even if it is found in the cache.
* @return file\Collection mongo GridFS collection.
*/
public function getFileCollection($prefix = 'fs', $refresh = false)
{
if ($refresh || !array_key_exists($prefix, $this->_fileCollections)) {
$this->_fileCollections[$prefix] = $this->selectFileCollection($prefix);
}
return $this->_fileCollections[$prefix];
}
/**
* Selects collection with given name.
* @param string $name collection name.
* @return Collection collection instance.
*/
protected function selectCollection($name)
{
return Yii::createObject([
'class' => 'yii\mongo\Collection',
'mongoCollection' => $this->mongoDb->selectCollection($name)
]);
}
/**
* Selects GridFS collection with given prefix.
* @param string $prefix file collection prefix.
* @return file\Collection file collection instance.
*/
protected function selectFileCollection($prefix)
{
return Yii::createObject([
'class' => 'yii\mongo\file\Collection',
'mongoCollection' => $this->mongoDb->getGridFS($prefix)
]);
}
/**
* Creates new collection.
* Note: Mongo creates new collections automatically on the first demand,
* this method makes sense only for the migration script or for the case
* you need to create collection with the specific options.
* @param string $name name of the collection
* @param array $options collection options in format: "name" => "value"
* @return \MongoCollection new mongo collection instance.
* @throws Exception on failure.
*/
public function createCollection($name, $options = [])
{
$token = $this->getName() . '.create(' . $name . ', ' . Json::encode($options) . ')';
Yii::info($token, __METHOD__);
try {
Yii::beginProfile($token, __METHOD__);
$result = $this->mongoDb->createCollection($name, $options);
Yii::endProfile($token, __METHOD__);
return $result;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
}
/**
* Executes Mongo command.
* @param array $command command specification.
* @param array $options options in format: "name" => "value"
* @return array database response.
* @throws Exception on failure.
*/
public function executeCommand($command, $options = [])
{
$token = $this->getName() . '.$cmd(' . Json::encode($command) . ', ' . Json::encode($options) . ')';
Yii::info($token, __METHOD__);
try {
Yii::beginProfile($token, __METHOD__);
$result = $this->mongoDb->command($command, $options);
$this->tryResultError($result);
Yii::endProfile($token, __METHOD__);
return $result;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
}
/**
* Checks if command execution result ended with an error.
* @param mixed $result raw command execution result.
* @throws Exception if an error occurred.
*/
protected function tryResultError($result)
{
if (is_array($result)) {
if (!empty($result['errmsg'])) {
$errorMessage = $result['errmsg'];
} elseif (!empty($result['err'])) {
$errorMessage = $result['err'];
}
if (isset($errorMessage)) {
if (array_key_exists('ok', $result)) {
$errorCode = (int)$result['ok'];
} else {
$errorCode = 0;
}
throw new Exception($errorMessage, $errorCode);
}
} elseif (!$result) {
throw new Exception('Unknown error, use "w=1" option to enable error tracking');
}
}
}
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mongo;
/**
* Exception represents an exception that is caused by some Mongo-related operations.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class Exception extends \yii\base\Exception
{
/**
* @return string the user-friendly name of this exception
*/
public function getName()
{
return \Yii::t('yii', 'Mongo Exception');
}
}
\ No newline at end of file
The Yii framework is free software. It is released under the terms of
the following BSD License.
Copyright © 2008-2013 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.
Yii 2.0 Public Preview - MongoDb Extension
==========================================
Thank you for choosing Yii - a high-performance component-based PHP framework.
If you are looking for a production-ready PHP framework, please use
[Yii v1.1](https://github.com/yiisoft/yii).
Yii 2.0 is still under heavy development. We may make significant changes
without prior notices. **Yii 2.0 is not ready for production use yet.**
[![Build Status](https://secure.travis-ci.org/yiisoft/yii2.png)](http://travis-ci.org/yiisoft/yii2)
This is the yii2-sphinx extension.
Installation
------------
The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
Either run
```
php composer.phar require yiisoft/yii2-mongo "*"
```
or add
```
"yiisoft/yii2-mongo": "*"
```
to the require section of your composer.json.
*Note: You might have to run `php composer.phar selfupdate`*
Usage & Documentation
---------------------
This extension adds [MongoDB](http://www.mongodb.org/) data storage support for the Yii2 framework.
Note: extension requires [MongoDB PHP Extension](http://us1.php.net/manual/en/book.mongo.php) version 1.3.0 or higher.
To use this extension, simply add the following code in your application configuration:
```php
return [
//....
'components' => [
'mongo' => [
'class' => '\yii\mongo\Connection',
'dsn' => 'mongodb://developer:password@localhost:27017/mydatabase',
],
],
];
```
This extension provides ActiveRecord solution similar ot the [[\yii\db\ActiveRecord]].
To declare an ActiveRecord class you need to extend [[\yii\mongo\ActiveRecord]] and
implement the `collectionName` and 'attributes' methods:
```php
use yii\mongo\ActiveRecord;
class Customer extends ActiveRecord
{
/**
* @return string the name of the index associated with this ActiveRecord class.
*/
public static function collectionName()
{
return 'customer';
}
/**
* @return array list of attribute names.
*/
public function attributes()
{
return ['name', 'email', 'address', 'status'];
}
}
```
You can use [[\yii\data\ActiveDataProvider]] with the [[\yii\mongo\Query]] and [[\yii\mongo\ActiveQuery]]:
```php
use yii\data\ActiveDataProvider;
use yii\mongo\Query;
$query = new Query;
$query->from('customer')->where(['status' => 2]);
$provider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'pageSize' => 10,
]
]);
$models = $provider->getModels();
```
```php
use yii\data\ActiveDataProvider;
use app\models\Customer;
$provider = new ActiveDataProvider([
'query' => Customer::find(),
'pagination' => [
'pageSize' => 10,
]
]);
$models = $provider->getModels();
```
This extension supports [MongoGridFS](http://docs.mongodb.org/manual/core/gridfs/) via
classes at namespace "\yii\mongo\file".
\ No newline at end of file
{
"name": "yiisoft/yii2-mongo",
"description": "MongoDb extension for the Yii framework",
"keywords": ["yii", "mongo", "mongodb", "active-record"],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"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": "Paul Klimov",
"email": "klimov.paul@gmail.com"
}
],
"minimum-stability": "dev",
"require": {
"yiisoft/yii2": "*",
"ext-mongo": ">=1.3.0"
},
"autoload": {
"psr-0": { "yii\\mongo\\": "" }
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mongo\file;
use yii\db\ActiveQueryInterface;
use yii\db\ActiveQueryTrait;
/**
* ActiveQuery represents a Mongo query associated with an file Active Record class.
*
* ActiveQuery instances are usually created by [[ActiveRecord::find()]].
*
* Because ActiveQuery extends from [[Query]], one can use query methods, such as [[where()]],
* [[orderBy()]] to customize the query options.
*
* ActiveQuery also provides the following additional query options:
*
* - [[with()]]: list of relations that this query should be performed with.
* - [[asArray()]]: whether to return each record as an array.
*
* These options can be configured using methods of the same name. For example:
*
* ~~~
* $images = ImageFile::find()->with('tags')->asArray()->all();
* ~~~
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class ActiveQuery extends Query implements ActiveQueryInterface
{
use ActiveQueryTrait;
/**
* Executes query and returns all results as an array.
* @param \yii\mongo\Connection $db the Mongo connection used to execute the query.
* If null, the Mongo connection returned by [[modelClass]] will be used.
* @return array the query results. If the query results in nothing, an empty array will be returned.
*/
public function all($db = null)
{
$cursor = $this->buildCursor($db);
$rows = $this->fetchRows($cursor);
if (!empty($rows)) {
$models = $this->createModels($rows);
if (!empty($this->with)) {
$this->findWith($this->with, $models);
}
return $models;
} else {
return [];
}
}
/**
* Executes query and returns a single row of result.
* @param \yii\mongo\Connection $db the Mongo connection used to execute the query.
* If null, the Mongo connection returned by [[modelClass]] will be used.
* @return ActiveRecord|array|null a single row of query result. Depending on the setting of [[asArray]],
* the query result may be either an array or an ActiveRecord object. Null will be returned
* if the query results in nothing.
*/
public function one($db = null)
{
$row = parent::one($db);
if ($row !== false) {
if ($this->asArray) {
$model = $row;
} else {
/** @var ActiveRecord $class */
$class = $this->modelClass;
$model = $class::create($row);
}
if (!empty($this->with)) {
$models = [$model];
$this->findWith($this->with, $models);
$model = $models[0];
}
return $model;
} else {
return null;
}
}
/**
* Returns the Mongo collection for this query.
* @param \yii\mongo\Connection $db Mongo connection.
* @return Collection collection instance.
*/
public function getCollection($db = null)
{
/** @var ActiveRecord $modelClass */
$modelClass = $this->modelClass;
if ($db === null) {
$db = $modelClass::getDb();
}
if ($this->from === null) {
$this->from = $modelClass::collectionName();
}
return $db->getFileCollection($this->from);
}
}
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mongo\file;
use yii\db\ActiveRelationInterface;
use yii\db\ActiveRelationTrait;
/**
* ActiveRelation represents a relation to Mongo GridFS Active Record class.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class ActiveRelation extends ActiveQuery implements ActiveRelationInterface
{
use ActiveRelationTrait;
}
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mongo\file;
use yii\mongo\Exception;
use Yii;
/**
* Collection represents the Mongo GridFS collection information.
*
* A file collection object is usually created by calling [[Database::getFileCollection()]] or [[Connection::getFileCollection()]].
*
* File collection inherits all interface from regular [[\yii\mongo\Collection]], adding methods to store files.
*
* @property \yii\mongo\Collection $chunkCollection file chunks Mongo collection. This property is read-only.
* @method \MongoGridFSCursor find() returns a cursor for the search results.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class Collection extends \yii\mongo\Collection
{
/**
* @var \MongoGridFS Mongo GridFS collection instance.
*/
public $mongoCollection;
/**
* @var \yii\mongo\Collection file chunks Mongo collection.
*/
private $_chunkCollection;
/**
* Returns the Mongo collection for the file chunks.
* @param boolean $refresh whether to reload the collection instance even if it is found in the cache.
* @return \yii\mongo\Collection mongo collection instance.
*/
public function getChunkCollection($refresh = false)
{
if ($refresh || !is_object($this->_chunkCollection)) {
$this->_chunkCollection = Yii::createObject([
'class' => 'yii\mongo\Collection',
'mongoCollection' => $this->mongoCollection->chunks
]);
}
return $this->_chunkCollection;
}
/**
* Removes data from the collection.
* @param array $condition description of records to remove.
* @param array $options list of options in format: optionName => optionValue.
* @return integer|boolean number of updated documents or whether operation was successful.
* @throws Exception on failure.
*/
public function remove($condition = [], $options = [])
{
$result = parent::remove($condition, $options);
$this->tryLastError(); // MongoGridFS::remove will return even if the remove failed
return $result;
}
/**
* Creates new file in GridFS collection from given local filesystem file.
* Additional attributes can be added file document using $metadata.
* @param string $filename name of the file to store.
* @param array $metadata other metadata fields to include in the file document.
* @param array $options list of options in format: optionName => optionValue
* @return mixed the "_id" of the saved file document. This will be a generated [[\MongoId]]
* unless an "_id" was explicitly specified in the metadata.
* @throws Exception on failure.
*/
public function insertFile($filename, $metadata = [], $options = [])
{
$token = 'Inserting file into ' . $this->getFullName();
Yii::info($token, __METHOD__);
try {
Yii::beginProfile($token, __METHOD__);
$options = array_merge(['w' => 1], $options);
$result = $this->mongoCollection->storeFile($filename, $metadata, $options);
Yii::endProfile($token, __METHOD__);
return $result;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
}
/**
* Creates new file in GridFS collection with specified content.
* Additional attributes can be added file document using $metadata.
* @param string $bytes string of bytes to store.
* @param array $metadata other metadata fields to include in the file document.
* @param array $options list of options in format: optionName => optionValue
* @return mixed the "_id" of the saved file document. This will be a generated [[\MongoId]]
* unless an "_id" was explicitly specified in the metadata.
* @throws Exception on failure.
*/
public function insertFileContent($bytes, $metadata = [], $options = [])
{
$token = 'Inserting file content into ' . $this->getFullName();
Yii::info($token, __METHOD__);
try {
Yii::beginProfile($token, __METHOD__);
$options = array_merge(['w' => 1], $options);
$result = $this->mongoCollection->storeBytes($bytes, $metadata, $options);
Yii::endProfile($token, __METHOD__);
return $result;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
}
/**
* Creates new file in GridFS collection from uploaded file.
* Additional attributes can be added file document using $metadata.
* @param string $name name of the uploaded file to store. This should correspond to
* the file field's name attribute in the HTML form.
* @param array $metadata other metadata fields to include in the file document.
* @return mixed the "_id" of the saved file document. This will be a generated [[\MongoId]]
* unless an "_id" was explicitly specified in the metadata.
* @throws Exception on failure.
*/
public function insertUploads($name, $metadata = [])
{
$token = 'Inserting file uploads into ' . $this->getFullName();
Yii::info($token, __METHOD__);
try {
Yii::beginProfile($token, __METHOD__);
$result = $this->mongoCollection->storeUpload($name, $metadata);
Yii::endProfile($token, __METHOD__);
return $result;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
}
/**
* Retrieves the file with given _id.
* @param mixed $id _id of the file to find.
* @return \MongoGridFSFile|null found file, or null if file does not exist
* @throws Exception on failure.
*/
public function get($id)
{
$token = 'Inserting file uploads into ' . $this->getFullName();
Yii::info($token, __METHOD__);
try {
Yii::beginProfile($token, __METHOD__);
$result = $this->mongoCollection->get($id);
Yii::endProfile($token, __METHOD__);
return $result;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
}
/**
* Deletes the file with given _id.
* @param mixed $id _id of the file to find.
* @return boolean whether the operation was successful.
* @throws Exception on failure.
*/
public function delete($id)
{
$token = 'Inserting file uploads into ' . $this->getFullName();
Yii::info($token, __METHOD__);
try {
Yii::beginProfile($token, __METHOD__);
$result = $this->mongoCollection->delete($id);
$this->tryResultError($result);
Yii::endProfile($token, __METHOD__);
return true;
} catch (\Exception $e) {
Yii::endProfile($token, __METHOD__);
throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
}
}
}
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\mongo\file;
use Yii;
use yii\helpers\Json;
use yii\mongo\Exception;
/**
* Query represents Mongo "find" operation for GridFS collection.
*
* Query behaves exactly as regular [[\yii\mongo\Query]].
* Found files will be represented as arrays of file document attributes with
* additional 'file' key, which stores [[\MongoGridFSFile]] instance.
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class Query extends \yii\mongo\Query
{
/**
* Returns the Mongo collection for this query.
* @param \yii\mongo\Connection $db Mongo connection.
* @return Collection collection instance.
*/
public function getCollection($db = null)
{
if ($db === null) {
$db = Yii::$app->getComponent('mongo');
}
return $db->getFileCollection($this->from);
}
/**
* @param \MongoGridFSCursor $cursor Mongo cursor instance to fetch data from.
* @param boolean $all whether to fetch all rows or only first one.
* @param string|callable $indexBy value to index by.
* @return array|boolean result.
* @see Query::fetchRows()
*/
protected function fetchRowsInternal($cursor, $all, $indexBy)
{
$result = [];
if ($all) {
foreach ($cursor as $file) {
$row = $file->file;
$row['file'] = $file;
if ($indexBy !== null) {
if (is_string($indexBy)) {
$key = $row[$indexBy];
} else {
$key = call_user_func($indexBy, $row);
}
$result[$key] = $row;
} else {
$result[] = $row;
}
}
} else {
if ($cursor->hasNext()) {
$file = $cursor->getNext();
$result = $file->file;
$result['file'] = $file;
} else {
$result = false;
}
}
return $result;
}
}
\ No newline at end of file
......@@ -203,7 +203,8 @@ trait ActiveRelationTrait
return serialize($key);
} else {
$attribute = reset($attributes);
return $model[$attribute];
$key = $model[$attribute];
return is_scalar($key) ? $key : serialize($key);
}
}
......
<?php
namespace yiiunit\data\ar\mongo;
/**
* Test Mongo ActiveRecord
*/
class ActiveRecord extends \yii\mongo\ActiveRecord
{
public static $db;
public static function getDb()
{
return self::$db;
}
}
\ No newline at end of file
<?php
namespace yiiunit\data\ar\mongo;
class Customer extends ActiveRecord
{
public static function collectionName()
{
return 'customer';
}
public function attributes()
{
return [
'_id',
'name',
'email',
'address',
'status',
];
}
public static function activeOnly($query)
{
$query->andWhere(['status' => 2]);
}
public function getOrders()
{
return $this->hasMany(CustomerOrder::className(), ['customer_id' => '_id']);
}
}
\ No newline at end of file
<?php
namespace yiiunit\data\ar\mongo;
class CustomerOrder extends ActiveRecord
{
public static function collectionName()
{
return 'customer_order';
}
public function attributes()
{
return [
'_id',
'number',
'customer_id',
'items',
];
}
public function getCustomer()
{
return $this->hasOne(Customer::className(), ['_id' => 'customer_id']);
}
}
\ No newline at end of file
<?php
namespace yiiunit\data\ar\mongo\file;
/**
* Test Mongo ActiveRecord
*/
class ActiveRecord extends \yii\mongo\file\ActiveRecord
{
public static $db;
public static function getDb()
{
return self::$db;
}
}
\ No newline at end of file
<?php
namespace yiiunit\data\ar\mongo\file;
class CustomerFile extends ActiveRecord
{
public static function collectionName()
{
return 'customer_fs';
}
public function attributes()
{
return array_merge(
parent::attributes(),
[
'tag',
'status',
]
);
}
public static function activeOnly($query)
{
$query->andWhere(['status' => 2]);
}
}
\ No newline at end of file
......@@ -51,5 +51,10 @@ return [
'password' => '',
'fixture' => __DIR__ . '/sphinx/source.sql',
],
],
'mongo' => [
'dsn' => 'mongodb://travis:test@localhost:27017',
'defaultDatabaseName' => 'yii2test',
'options' => [],
]
];
<?php
namespace yiiunit\extensions\mongo;
use yii\data\ActiveDataProvider;
use yii\mongo\Query;
use yiiunit\data\ar\mongo\ActiveRecord;
use yiiunit\data\ar\mongo\Customer;
/**
* @group mongo
*/
class ActiveDataProviderTest extends MongoTestCase
{
protected function setUp()
{
parent::setUp();
ActiveRecord::$db = $this->getConnection();
$this->setUpTestRows();
}
protected function tearDown()
{
$this->dropCollection(Customer::collectionName());
parent::tearDown();
}
/**
* Sets up test rows.
*/
protected function setUpTestRows()
{
$collection = $this->getConnection()->getCollection('customer');
$rows = [];
for ($i = 1; $i <= 10; $i++) {
$rows[] = [
'name' => 'name' . $i,
'email' => 'email' . $i,
'address' => 'address' . $i,
'status' => $i,
];
}
$collection->batchInsert($rows);
}
// Tests :
public function testQuery()
{
$query = new Query;
$query->from('customer');
$provider = new ActiveDataProvider([
'query' => $query,
'db' => $this->getConnection(),
]);
$models = $provider->getModels();
$this->assertEquals(10, count($models));
$provider = new ActiveDataProvider([
'query' => $query,
'db' => $this->getConnection(),
'pagination' => [
'pageSize' => 5,
]
]);
$models = $provider->getModels();
$this->assertEquals(5, count($models));
}
public function testActiveQuery()
{
$provider = new ActiveDataProvider([
'query' => Customer::find()->orderBy('id ASC'),
]);
$models = $provider->getModels();
$this->assertEquals(10, count($models));
$this->assertTrue($models[0] instanceof Customer);
$keys = $provider->getKeys();
$this->assertTrue($keys[0] instanceof \MongoId);
$provider = new ActiveDataProvider([
'query' => Customer::find(),
'pagination' => [
'pageSize' => 5,
]
]);
$models = $provider->getModels();
$this->assertEquals(5, count($models));
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo;
use yii\mongo\ActiveQuery;
use yiiunit\data\ar\mongo\ActiveRecord;
use yiiunit\data\ar\mongo\Customer;
/**
* @group mongo
*/
class ActiveRecordTest extends MongoTestCase
{
/**
* @var array[] list of test rows.
*/
protected $testRows = [];
protected function setUp()
{
parent::setUp();
ActiveRecord::$db = $this->getConnection();
$this->setUpTestRows();
}
protected function tearDown()
{
$this->dropCollection(Customer::collectionName());
parent::tearDown();
}
/**
* Sets up test rows.
*/
protected function setUpTestRows()
{
$collection = $this->getConnection()->getCollection('customer');
$rows = [];
for ($i = 1; $i <= 10; $i++) {
$rows[] = [
'name' => 'name' . $i,
'email' => 'email' . $i,
'address' => 'address' . $i,
'status' => $i,
];
}
$collection->batchInsert($rows);
$this->testRows = $rows;
}
// Tests :
public function testFind()
{
// find one
$result = Customer::find();
$this->assertTrue($result instanceof ActiveQuery);
$customer = $result->one();
$this->assertTrue($customer instanceof Customer);
// find all
$customers = Customer::find()->all();
$this->assertEquals(10, count($customers));
$this->assertTrue($customers[0] instanceof Customer);
$this->assertTrue($customers[1] instanceof Customer);
// find by _id
$testId = $this->testRows[0]['_id'];
$customer = Customer::find($testId);
$this->assertTrue($customer instanceof Customer);
$this->assertEquals($testId, $customer->_id);
// find by column values
$customer = Customer::find(['name' => 'name5']);
$this->assertTrue($customer instanceof Customer);
$this->assertEquals($this->testRows[4]['_id'], $customer->_id);
$this->assertEquals('name5', $customer->name);
$customer = Customer::find(['name' => 'unexisting name']);
$this->assertNull($customer);
// find by attributes
$customer = Customer::find()->where(['status' => 4])->one();
$this->assertTrue($customer instanceof Customer);
$this->assertEquals(4, $customer->status);
// find count, sum, average, min, max, distinct
$this->assertEquals(10, Customer::find()->count());
$this->assertEquals(1, Customer::find()->where(['status' => 2])->count());
$this->assertEquals((1+10)/2*10, Customer::find()->sum('status'));
$this->assertEquals((1+10)/2, Customer::find()->average('status'));
$this->assertEquals(1, Customer::find()->min('status'));
$this->assertEquals(10, Customer::find()->max('status'));
$this->assertEquals(range(1, 10), Customer::find()->distinct('status'));
// scope
$this->assertEquals(1, Customer::find()->activeOnly()->count());
// asArray
$testRow = $this->testRows[2];
$customer = Customer::find()->where(['_id' => $testRow['_id']])->asArray()->one();
$this->assertEquals($testRow, $customer);
// indexBy
$customers = Customer::find()->indexBy('name')->all();
$this->assertTrue($customers['name1'] instanceof Customer);
$this->assertTrue($customers['name2'] instanceof Customer);
// indexBy callable
$customers = Customer::find()->indexBy(function ($customer) {
return $customer->status . '-' . $customer->status;
})->all();
$this->assertTrue($customers['1-1'] instanceof Customer);
$this->assertTrue($customers['2-2'] instanceof Customer);
}
public function testInsert()
{
$record = new Customer;
$record->name = 'new name';
$record->email = 'new email';
$record->address = 'new address';
$record->status = 7;
$this->assertTrue($record->isNewRecord);
$record->save();
$this->assertTrue($record->_id instanceof \MongoId);
$this->assertFalse($record->isNewRecord);
}
/**
* @depends testInsert
*/
public function testUpdate()
{
$record = new Customer;
$record->name = 'new name';
$record->email = 'new email';
$record->address = 'new address';
$record->status = 7;
$record->save();
// save
$record = Customer::find($record->_id);
$this->assertTrue($record instanceof Customer);
$this->assertEquals(7, $record->status);
$this->assertFalse($record->isNewRecord);
$record->status = 9;
$record->save();
$this->assertEquals(9, $record->status);
$this->assertFalse($record->isNewRecord);
$record2 = Customer::find($record->_id);
$this->assertEquals(9, $record2->status);
// updateAll
$pk = ['_id' => $record->_id];
$ret = Customer::updateAll(['status' => 55], $pk);
$this->assertEquals(1, $ret);
$record = Customer::find($pk);
$this->assertEquals(55, $record->status);
}
/**
* @depends testInsert
*/
public function testDelete()
{
// delete
$record = new Customer;
$record->name = 'new name';
$record->email = 'new email';
$record->address = 'new address';
$record->status = 7;
$record->save();
$record = Customer::find($record->_id);
$record->delete();
$record = Customer::find($record->_id);
$this->assertNull($record);
// deleteAll
$record = new Customer;
$record->name = 'new name';
$record->email = 'new email';
$record->address = 'new address';
$record->status = 7;
$record->save();
$ret = Customer::deleteAll(['name' => 'new name']);
$this->assertEquals(1, $ret);
$records = Customer::find()->where(['name' => 'new name'])->all();
$this->assertEquals(0, count($records));
}
public function testUpdateAllCounters()
{
$this->assertEquals(1, Customer::updateAllCounters(['status' => 10], ['status' => 10]));
$record = Customer::find(['status' => 10]);
$this->assertNull($record);
}
/**
* @depends testUpdateAllCounters
*/
public function testUpdateCounters()
{
$record = Customer::find($this->testRows[9]);
$originalCounter = $record->status;
$counterIncrement = 20;
$record->updateCounters(['status' => $counterIncrement]);
$this->assertEquals($originalCounter + $counterIncrement, $record->status);
$refreshedRecord = Customer::find($record->_id);
$this->assertEquals($originalCounter + $counterIncrement, $refreshedRecord->status);
}
/**
* @depends testUpdate
*/
public function testUpdateNestedAttribute()
{
$record = new Customer;
$record->name = 'new name';
$record->email = 'new email';
$record->address = [
'city' => 'SomeCity',
'street' => 'SomeStreet',
];
$record->status = 7;
$record->save();
// save
$record = Customer::find($record->_id);
$newAddress = [
'city' => 'AnotherCity'
];
$record->address = $newAddress;
$record->save();
$record2 = Customer::find($record->_id);
$this->assertEquals($newAddress, $record2->address);
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo;
use yiiunit\data\ar\mongo\ActiveRecord;
use yiiunit\data\ar\mongo\Customer;
use yiiunit\data\ar\mongo\CustomerOrder;
/**
* @group mongo
*/
class ActiveRelationTest extends MongoTestCase
{
protected function setUp()
{
parent::setUp();
ActiveRecord::$db = $this->getConnection();
$this->setUpTestRows();
}
protected function tearDown()
{
$this->dropCollection(Customer::collectionName());
$this->dropCollection(CustomerOrder::collectionName());
parent::tearDown();
}
/**
* Sets up test rows.
*/
protected function setUpTestRows()
{
$customerCollection = $this->getConnection()->getCollection('customer');
$customers = [];
for ($i = 1; $i <= 5; $i++) {
$customers[] = [
'name' => 'name' . $i,
'email' => 'email' . $i,
'address' => 'address' . $i,
'status' => $i,
];
}
$customerCollection->batchInsert($customers);
$customerOrderCollection = $this->getConnection()->getCollection('customer_order');
$customerOrders = [];
foreach ($customers as $customer) {
$customerOrders[] = [
'customer_id' => $customer['_id'],
'number' => $customer['status'],
];
$customerOrders[] = [
'customer_id' => $customer['_id'],
'number' => $customer['status'] + 1,
];
}
$customerOrderCollection->batchInsert($customerOrders);
}
// Tests :
public function testFindLazy()
{
/** @var CustomerOrder $order */
$order = CustomerOrder::find(['number' => 2]);
$this->assertFalse($order->isRelationPopulated('customer'));
$index = $order->customer;
$this->assertTrue($order->isRelationPopulated('customer'));
$this->assertTrue($index instanceof Customer);
$this->assertEquals(1, count($order->populatedRelations));
}
public function testFindEager()
{
$orders = CustomerOrder::find()->with('customer')->all();
$this->assertEquals(10, count($orders));
$this->assertTrue($orders[0]->isRelationPopulated('customer'));
$this->assertTrue($orders[1]->isRelationPopulated('customer'));
$this->assertTrue($orders[0]->customer instanceof Customer);
$this->assertTrue($orders[1]->customer instanceof Customer);
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo;
/**
* @group mongo
*/
class CollectionTest extends MongoTestCase
{
protected function tearDown()
{
$this->dropCollection('customer');
$this->dropCollection('mapReduceOut');
parent::tearDown();
}
// Tests :
public function testGetName()
{
$collectionName = 'customer';
$collection = $this->getConnection()->getCollection($collectionName);
$this->assertEquals($collectionName, $collection->getName());
$this->assertEquals($this->mongoConfig['defaultDatabaseName'] . '.' . $collectionName, $collection->getFullName());
}
public function testFind()
{
$collection = $this->getConnection()->getCollection('customer');
$cursor = $collection->find();
$this->assertTrue($cursor instanceof \MongoCursor);
}
public function testInsert()
{
$collection = $this->getConnection()->getCollection('customer');
$data = [
'name' => 'customer 1',
'address' => 'customer 1 address',
];
$id = $collection->insert($data);
$this->assertTrue($id instanceof \MongoId);
$this->assertNotEmpty($id->__toString());
}
/**
* @depends testInsert
* @depends testFind
*/
public function testFindAll()
{
$collection = $this->getConnection()->getCollection('customer');
$data = [
'name' => 'customer 1',
'address' => 'customer 1 address',
];
$id = $collection->insert($data);
$cursor = $collection->find();
$rows = [];
foreach ($cursor as $row) {
$rows[] = $row;
}
$this->assertEquals(1, count($rows));
$this->assertEquals($id, $rows[0]['_id']);
}
/**
* @depends testFind
*/
public function testBatchInsert()
{
$collection = $this->getConnection()->getCollection('customer');
$rows = [
[
'name' => 'customer 1',
'address' => 'customer 1 address',
],
[
'name' => 'customer 2',
'address' => 'customer 2 address',
],
];
$insertedRows = $collection->batchInsert($rows);
$this->assertTrue($insertedRows[0]['_id'] instanceof \MongoId);
$this->assertTrue($insertedRows[1]['_id'] instanceof \MongoId);
$this->assertEquals(count($rows), $collection->find()->count());
}
public function testSave()
{
$collection = $this->getConnection()->getCollection('customer');
$data = [
'name' => 'customer 1',
'address' => 'customer 1 address',
];
$id = $collection->save($data);
$this->assertTrue($id instanceof \MongoId);
$this->assertNotEmpty($id->__toString());
}
/**
* @depends testSave
*/
public function testUpdateBySave()
{
$collection = $this->getConnection()->getCollection('customer');
$data = [
'name' => 'customer 1',
'address' => 'customer 1 address',
];
$newId = $collection->save($data);
$updatedId = $collection->save($data);
$this->assertEquals($newId, $updatedId, 'Unable to update data!');
$data['_id'] = $newId->__toString();
$updatedId = $collection->save($data);
$this->assertEquals($newId, $updatedId, 'Unable to updated data by string id!');
}
/**
* @depends testFindAll
*/
public function testRemove()
{
$collection = $this->getConnection()->getCollection('customer');
$data = [
'name' => 'customer 1',
'address' => 'customer 1 address',
];
$id = $collection->insert($data);
$count = $collection->remove(['_id' => $id]);
$this->assertEquals(1, $count);
$rows = $this->findAll($collection);
$this->assertEquals(0, count($rows));
}
/**
* @depends testFindAll
*/
public function testUpdate()
{
$collection = $this->getConnection()->getCollection('customer');
$data = [
'name' => 'customer 1',
'address' => 'customer 1 address',
];
$id = $collection->insert($data);
$newData = [
'name' => 'new name'
];
$count = $collection->update(['_id' => $id], $newData);
$this->assertEquals(1, $count);
list($row) = $this->findAll($collection);
$this->assertEquals($newData['name'], $row['name']);
}
/**
* @depends testBatchInsert
*/
public function testGroup()
{
$collection = $this->getConnection()->getCollection('customer');
$rows = [
[
'name' => 'customer 1',
'address' => 'customer 1 address',
],
[
'name' => 'customer 2',
'address' => 'customer 2 address',
],
];
$collection->batchInsert($rows);
$keys = ['address' => 1];
$initial = ['items' => []];
$reduce = "function (obj, prev) { prev.items.push(obj.name); }";
$result = $collection->group($keys, $initial, $reduce);
$this->assertEquals(2, count($result));
$this->assertNotEmpty($result[0]['address']);
$this->assertNotEmpty($result[0]['items']);
}
/**
* @depends testBatchInsert
*/
public function testMapReduce()
{
$collection = $this->getConnection()->getCollection('customer');
$rows = [
[
'name' => 'customer 1',
'status' => 1,
'amount' => 100,
],
[
'name' => 'customer 2',
'status' => 1,
'amount' => 200,
],
[
'name' => 'customer 2',
'status' => 2,
'amount' => 400,
],
[
'name' => 'customer 2',
'status' => 3,
'amount' => 500,
],
];
$collection->batchInsert($rows);
$result = $collection->mapReduce(
'function () {emit(this.status, this.amount)}',
'function (key, values) {return Array.sum(values)}',
'mapReduceOut',
['status' => ['$lt' => 3]]
);
$this->assertEquals('mapReduceOut', $result);
$outputCollection = $this->getConnection()->getCollection($result);
$rows = $this->findAll($outputCollection);
$expectedRows = [
[
'_id' => 1,
'value' => 300,
],
[
'_id' => 2,
'value' => 400,
],
];
$this->assertEquals($expectedRows, $rows);
}
public function testCreateIndex()
{
$collection = $this->getConnection()->getCollection('customer');
$columns = [
'name',
'status' => \MongoCollection::DESCENDING,
];
$this->assertTrue($collection->createIndex($columns));
$indexInfo = $collection->mongoCollection->getIndexInfo();
$this->assertEquals(2, count($indexInfo));
}
/**
* @depends testCreateIndex
*/
public function testDropIndex()
{
$collection = $this->getConnection()->getCollection('customer');
$collection->createIndex('name');
$this->assertTrue($collection->dropIndex('name'));
$indexInfo = $collection->mongoCollection->getIndexInfo();
$this->assertEquals(1, count($indexInfo));
$this->setExpectedException('\yii\mongo\Exception');
$collection->dropIndex('name');
}
/**
* @depends testCreateIndex
*/
public function testDropAllIndexes()
{
$collection = $this->getConnection()->getCollection('customer');
$collection->createIndex('name');
$this->assertEquals(2, $collection->dropAllIndexes());
$indexInfo = $collection->mongoCollection->getIndexInfo();
$this->assertEquals(1, count($indexInfo));
}
/**
* @depends testBatchInsert
* @depends testCreateIndex
*/
public function testFullTextSearch()
{
if (version_compare('2.4', $this->getServerVersion(), '>')) {
$this->markTestSkipped("Mongo Server 2.4 required.");
}
$collection = $this->getConnection()->getCollection('customer');
$rows = [
[
'name' => 'customer 1',
'status' => 1,
'amount' => 100,
],
[
'name' => 'some customer',
'status' => 1,
'amount' => 200,
],
];
$collection->batchInsert($rows);
$collection->createIndex(['name' => 'text']);
$result = $collection->fullTextSearch('some');
$this->assertNotEmpty($result);
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo;
use yii\mongo\Collection;
use yii\mongo\file\Collection as FileCollection;
use yii\mongo\Connection;
use yii\mongo\Database;
/**
* @group mongo
*/
class ConnectionTest extends MongoTestCase
{
public function testConstruct()
{
$connection = $this->getConnection(false);
$params = $this->mongoConfig;
$connection->open();
$this->assertEquals($params['dsn'], $connection->dsn);
$this->assertEquals($params['defaultDatabaseName'], $connection->defaultDatabaseName);
$this->assertEquals($params['options'], $connection->options);
}
public function testOpenClose()
{
$connection = $this->getConnection(false, false);
$this->assertFalse($connection->isActive);
$this->assertEquals(null, $connection->mongoClient);
$connection->open();
$this->assertTrue($connection->isActive);
$this->assertTrue(is_object($connection->mongoClient));
$connection->close();
$this->assertFalse($connection->isActive);
$this->assertEquals(null, $connection->mongoClient);
$connection = new Connection;
$connection->dsn = 'unknown::memory:';
$this->setExpectedException('yii\mongo\Exception');
$connection->open();
}
public function testGetDatabase()
{
$connection = $this->getConnection();
$database = $connection->getDatabase($connection->defaultDatabaseName);
$this->assertTrue($database instanceof Database);
$this->assertTrue($database->mongoDb instanceof \MongoDB);
$database2 = $connection->getDatabase($connection->defaultDatabaseName);
$this->assertTrue($database === $database2);
$databaseRefreshed = $connection->getDatabase($connection->defaultDatabaseName, true);
$this->assertFalse($database === $databaseRefreshed);
}
/**
* @depends testGetDatabase
*/
public function testGetDefaultDatabase()
{
$connection = new Connection();
$connection->dsn = $this->mongoConfig['dsn'];
$connection->defaultDatabaseName = $this->mongoConfig['defaultDatabaseName'];
$database = $connection->getDatabase();
$this->assertTrue($database instanceof Database, 'Unable to get default database!');
$connection = new Connection();
$connection->dsn = $this->mongoConfig['dsn'];
$connection->options = ['db' => $this->mongoConfig['defaultDatabaseName']];
$database = $connection->getDatabase();
$this->assertTrue($database instanceof Database, 'Unable to determine default database from options!');
$connection = new Connection();
$connection->dsn = $this->mongoConfig['dsn'] . '/' . $this->mongoConfig['defaultDatabaseName'];
$database = $connection->getDatabase();
$this->assertTrue($database instanceof Database, 'Unable to determine default database from dsn!');
}
/**
* @depends testGetDefaultDatabase
*/
public function testGetCollection()
{
$connection = $this->getConnection();
$collection = $connection->getCollection('customer');
$this->assertTrue($collection instanceof Collection);
$collection2 = $connection->getCollection('customer');
$this->assertTrue($collection === $collection2);
$collection2 = $connection->getCollection('customer', true);
$this->assertFalse($collection === $collection2);
}
/**
* @depends testGetDefaultDatabase
*/
public function testGetFileCollection()
{
$connection = $this->getConnection();
$collection = $connection->getFileCollection('testfs');
$this->assertTrue($collection instanceof FileCollection);
$collection2 = $connection->getFileCollection('testfs');
$this->assertTrue($collection === $collection2);
$collection2 = $connection->getFileCollection('testfs', true);
$this->assertFalse($collection === $collection2);
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo;
use yii\mongo\Collection;
use yii\mongo\file\Collection as FileCollection;
/**
* @group mongo
*/
class DatabaseTest extends MongoTestCase
{
protected function tearDown()
{
$this->dropCollection('customer');
$this->dropFileCollection('testfs');
parent::tearDown();
}
// Tests :
public function testGetCollection()
{
$database = $connection = $this->getConnection()->getDatabase();
$collection = $database->getCollection('customer');
$this->assertTrue($collection instanceof Collection);
$this->assertTrue($collection->mongoCollection instanceof \MongoCollection);
$collection2 = $database->getCollection('customer');
$this->assertTrue($collection === $collection2);
$collectionRefreshed = $database->getCollection('customer', true);
$this->assertFalse($collection === $collectionRefreshed);
}
public function testGetFileCollection()
{
$database = $connection = $this->getConnection()->getDatabase();
$collection = $database->getFileCollection('testfs');
$this->assertTrue($collection instanceof FileCollection);
$this->assertTrue($collection->mongoCollection instanceof \MongoGridFS);
$collection2 = $database->getFileCollection('testfs');
$this->assertTrue($collection === $collection2);
$collectionRefreshed = $database->getFileCollection('testfs', true);
$this->assertFalse($collection === $collectionRefreshed);
}
public function testExecuteCommand()
{
$database = $connection = $this->getConnection()->getDatabase();
$result = $database->executeCommand([
'distinct' => 'customer',
'key' => 'name'
]);
$this->assertTrue(array_key_exists('ok', $result));
$this->assertTrue(array_key_exists('values', $result));
}
public function testCreateCollection()
{
$database = $connection = $this->getConnection()->getDatabase();
$collection = $database->createCollection('customer');
$this->assertTrue($collection instanceof \MongoCollection);
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo;
use yii\helpers\FileHelper;
use yii\mongo\Connection;
use Yii;
use yii\mongo\Exception;
use yiiunit\TestCase;
class MongoTestCase extends TestCase
{
/**
* @var array Mongo connection configuration.
*/
protected $mongoConfig = [
'dsn' => 'mongodb://localhost:27017',
'defaultDatabaseName' => 'yii2test',
'options' => [],
];
/**
* @var Connection Mongo connection instance.
*/
protected $mongo;
public static function setUpBeforeClass()
{
static::loadClassMap();
}
protected function setUp()
{
parent::setUp();
if (!extension_loaded('mongo')) {
$this->markTestSkipped('mongo extension required.');
}
$config = $this->getParam('mongo');
if (!empty($config)) {
$this->mongoConfig = $config;
}
$this->mockApplication();
static::loadClassMap();
}
protected function tearDown()
{
if ($this->mongo) {
$this->mongo->close();
}
$this->destroyApplication();
}
/**
* Adds sphinx extension files to [[Yii::$classPath]],
* avoiding the necessity of usage Composer autoloader.
*/
protected static function loadClassMap()
{
$baseNameSpace = 'yii/mongo';
$basePath = realpath(__DIR__. '/../../../../extensions/mongo');
$files = FileHelper::findFiles($basePath);
foreach ($files as $file) {
$classRelativePath = str_replace($basePath, '', $file);
$classFullName = str_replace(['/', '.php'], ['\\', ''], $baseNameSpace . $classRelativePath);
Yii::$classMap[$classFullName] = $file;
}
}
/**
* @param boolean $reset whether to clean up the test database
* @param boolean $open whether to open test database
* @return \yii\mongo\Connection
*/
public function getConnection($reset = false, $open = true)
{
if (!$reset && $this->mongo) {
return $this->mongo;
}
$db = new Connection;
$db->dsn = $this->mongoConfig['dsn'];
$db->defaultDatabaseName = $this->mongoConfig['defaultDatabaseName'];
if (isset($this->mongoConfig['options'])) {
$db->options = $this->mongoConfig['options'];
}
if ($open) {
$db->open();
}
$this->mongo = $db;
return $db;
}
/**
* Drops the specified collection.
* @param string $name collection name.
*/
protected function dropCollection($name)
{
if ($this->mongo) {
try {
$this->mongo->getCollection($name)->drop();
} catch (Exception $e) {
// shut down exception
}
}
}
/**
* Drops the specified file collection.
* @param string $name file collection name.
*/
protected function dropFileCollection($name = 'fs')
{
if ($this->mongo) {
try {
$this->mongo->getFileCollection($name)->drop();
} catch (Exception $e) {
// shut down exception
}
}
}
/**
* Finds all records in collection.
* @param \yii\mongo\Collection $collection
* @param array $condition
* @param array $fields
* @return array rows
*/
protected function findAll($collection, $condition = [], $fields = [])
{
$cursor = $collection->find($condition, $fields);
$result = [];
foreach ($cursor as $data) {
$result[] = $data;
}
return $result;
}
/**
* Returns the Mongo server version.
* @return string Mongo server version.
*/
protected function getServerVersion()
{
$connection = $this->getConnection();
$buildInfo = $connection->getDatabase()->executeCommand(['buildinfo' => true]);
return $buildInfo['version'];
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo;
use yii\mongo\Query;
/**
* @group mongo
*/
class QueryRunTest extends MongoTestCase
{
protected function setUp()
{
parent::setUp();
$this->setUpTestRows();
}
protected function tearDown()
{
$this->dropCollection('customer');
parent::tearDown();
}
/**
* Sets up test rows.
*/
protected function setUpTestRows()
{
$collection = $this->getConnection()->getCollection('customer');
$rows = [];
for ($i = 1; $i <= 10; $i++) {
$rows[] = [
'name' => 'name' . $i,
'address' => 'address' . $i,
'avatar' => [
'width' => 50 + $i,
'height' => 100 + $i,
'url' => 'http://some.url/' . $i,
],
];
}
$collection->batchInsert($rows);
}
// Tests :
public function testAll()
{
$connection = $this->getConnection();
$query = new Query;
$rows = $query->from('customer')->all($connection);
$this->assertEquals(10, count($rows));
}
public function testDirectMatch()
{
$connection = $this->getConnection();
$query = new Query;
$rows = $query->from('customer')
->where(['name' => 'name1'])
->all($connection);
$this->assertEquals(1, count($rows));
$this->assertEquals('name1', $rows[0]['name']);
}
public function testIndexBy()
{
$connection = $this->getConnection();
$query = new Query;
$rows = $query->from('customer')
->indexBy('name')
->all($connection);
$this->assertEquals(10, count($rows));
$this->assertNotEmpty($rows['name1']);
}
public function testInCondition()
{
$connection = $this->getConnection();
$query = new Query;
$rows = $query->from('customer')
->where([
'name' => ['name1', 'name5']
])
->all($connection);
$this->assertEquals(2, count($rows));
$this->assertEquals('name1', $rows[0]['name']);
$this->assertEquals('name5', $rows[1]['name']);
}
public function testOrCondition()
{
$connection = $this->getConnection();
$query = new Query;
$rows = $query->from('customer')
->where(['name' => 'name1'])
->orWhere(['address' => 'address5'])
->all($connection);
$this->assertEquals(2, count($rows));
$this->assertEquals('name1', $rows[0]['name']);
$this->assertEquals('address5', $rows[1]['address']);
}
public function testOrder()
{
$connection = $this->getConnection();
$query = new Query;
$rows = $query->from('customer')
->orderBy(['name' => SORT_DESC])
->all($connection);
$this->assertEquals('name9', $rows[0]['name']);
$query = new Query;
$rows = $query->from('customer')
->orderBy(['avatar.height' => SORT_DESC])
->all($connection);
$this->assertEquals('name10', $rows[0]['name']);
}
public function testMatchPlainId()
{
$connection = $this->getConnection();
$query = new Query;
$row = $query->from('customer')->one($connection);
$query = new Query;
$rows = $query->from('customer')
->where(['_id' => $row['_id']->__toString()])
->all($connection);
$this->assertEquals(1, count($rows));
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo;
use yii\mongo\Query;
/**
* @group mongo
*/
class QueryTest extends MongoTestCase
{
public function testSelect()
{
// default
$query = new Query;
$select = [];
$query->select($select);
$this->assertEquals($select, $query->select);
$query = new Query;
$select = ['name', 'something'];
$query->select($select);
$this->assertEquals($select, $query->select);
}
public function testFrom()
{
$query = new Query;
$from = 'customer';
$query->from($from);
$this->assertEquals($from, $query->from);
$query = new Query;
$from = ['', 'customer'];
$query->from($from);
$this->assertEquals($from, $query->from);
}
public function testWhere()
{
$query = new Query;
$query->where(['name' => 'name1']);
$this->assertEquals(['name' => 'name1'], $query->where);
$query->andWhere(['address' => 'address1']);
$this->assertEquals(
[
'and',
['name' => 'name1'],
['address' => 'address1']
],
$query->where
);
$query->orWhere(['name' => 'name2']);
$this->assertEquals(
[
'or',
[
'and',
['name' => 'name1'],
['address' => 'address1']
],
['name' => 'name2']
],
$query->where
);
}
public function testOrder()
{
$query = new Query;
$query->orderBy('team');
$this->assertEquals(['team' => SORT_ASC], $query->orderBy);
$query->addOrderBy('company');
$this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC], $query->orderBy);
$query->addOrderBy('age');
$this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC, 'age' => SORT_ASC], $query->orderBy);
$query->addOrderBy(['age' => SORT_DESC]);
$this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC, 'age' => SORT_DESC], $query->orderBy);
$query->addOrderBy('age ASC, company DESC');
$this->assertEquals(['team' => SORT_ASC, 'company' => SORT_DESC, 'age' => SORT_ASC], $query->orderBy);
}
public function testLimitOffset()
{
$query = new Query;
$query->limit(10)->offset(5);
$this->assertEquals(10, $query->limit);
$this->assertEquals(5, $query->offset);
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo\file;
use Yii;
use yii\helpers\FileHelper;
use yiiunit\extensions\mongo\MongoTestCase;
use yii\mongo\file\ActiveQuery;
use yiiunit\data\ar\mongo\file\ActiveRecord;
use yiiunit\data\ar\mongo\file\CustomerFile;
/**
* @group mongo
*/
class ActiveRecordTest extends MongoTestCase
{
/**
* @var array[] list of test rows.
*/
protected $testRows = [];
protected function setUp()
{
parent::setUp();
ActiveRecord::$db = $this->getConnection();
$this->setUpTestRows();
$filePath = $this->getTestFilePath();
if (!file_exists($filePath)) {
FileHelper::createDirectory($filePath);
}
}
protected function tearDown()
{
$filePath = $this->getTestFilePath();
if (file_exists($filePath)) {
FileHelper::removeDirectory($filePath);
}
$this->dropFileCollection(CustomerFile::collectionName());
parent::tearDown();
}
/**
* @return string test file path.
*/
protected function getTestFilePath()
{
return Yii::getAlias('@yiiunit/runtime') . DIRECTORY_SEPARATOR . basename(get_class($this)) . '_' . getmypid();
}
/**
* Sets up test rows.
*/
protected function setUpTestRows()
{
$collection = $this->getConnection()->getFileCollection(CustomerFile::collectionName());
$rows = [];
for ($i = 1; $i <= 10; $i++) {
$record = [
'tag' => 'tag' . $i,
'status' => $i,
];
$content = 'content' . $i;
$record['_id'] = $collection->insertFileContent($content, $record);
$record['content'] = $content;
$rows[] = $record;
}
$this->testRows = $rows;
}
// Tests :
public function testFind()
{
// find one
$result = CustomerFile::find();
$this->assertTrue($result instanceof ActiveQuery);
$customer = $result->one();
$this->assertTrue($customer instanceof CustomerFile);
// find all
$customers = CustomerFile::find()->all();
$this->assertEquals(10, count($customers));
$this->assertTrue($customers[0] instanceof CustomerFile);
$this->assertTrue($customers[1] instanceof CustomerFile);
// find by _id
$testId = $this->testRows[0]['_id'];
$customer = CustomerFile::find($testId);
$this->assertTrue($customer instanceof CustomerFile);
$this->assertEquals($testId, $customer->_id);
// find by column values
$customer = CustomerFile::find(['tag' => 'tag5']);
$this->assertTrue($customer instanceof CustomerFile);
$this->assertEquals($this->testRows[4]['_id'], $customer->_id);
$this->assertEquals('tag5', $customer->tag);
$customer = CustomerFile::find(['tag' => 'unexisting tag']);
$this->assertNull($customer);
// find by attributes
$customer = CustomerFile::find()->where(['status' => 4])->one();
$this->assertTrue($customer instanceof CustomerFile);
$this->assertEquals(4, $customer->status);
// find count, sum, average, min, max, distinct
$this->assertEquals(10, CustomerFile::find()->count());
$this->assertEquals(1, CustomerFile::find()->where(['status' => 2])->count());
$this->assertEquals((1+10)/2*10, CustomerFile::find()->sum('status'));
$this->assertEquals((1+10)/2, CustomerFile::find()->average('status'));
$this->assertEquals(1, CustomerFile::find()->min('status'));
$this->assertEquals(10, CustomerFile::find()->max('status'));
$this->assertEquals(range(1, 10), CustomerFile::find()->distinct('status'));
// scope
$this->assertEquals(1, CustomerFile::find()->activeOnly()->count());
// asArray
$testRow = $this->testRows[2];
$customer = CustomerFile::find()->where(['_id' => $testRow['_id']])->asArray()->one();
$this->assertEquals($testRow['_id'], $customer['_id']);
$this->assertEquals($testRow['tag'], $customer['tag']);
$this->assertEquals($testRow['status'], $customer['status']);
// indexBy
$customers = CustomerFile::find()->indexBy('tag')->all();
$this->assertTrue($customers['tag1'] instanceof CustomerFile);
$this->assertTrue($customers['tag2'] instanceof CustomerFile);
// indexBy callable
$customers = CustomerFile::find()->indexBy(function ($customer) {
return $customer->status . '-' . $customer->status;
})->all();
$this->assertTrue($customers['1-1'] instanceof CustomerFile);
$this->assertTrue($customers['2-2'] instanceof CustomerFile);
}
public function testInsert()
{
$record = new CustomerFile;
$record->tag = 'new new';
$record->status = 7;
$this->assertTrue($record->isNewRecord);
$record->save();
$this->assertTrue($record->_id instanceof \MongoId);
$this->assertFalse($record->isNewRecord);
$fileContent = $record->getFileContent();
$this->assertEmpty($fileContent);
}
/**
* @depends testInsert
*/
public function testInsertFile()
{
$record = new CustomerFile;
$record->tag = 'new new';
$record->status = 7;
$fileName = __FILE__;
$record->setAttribute('file', $fileName);
$record->save();
$this->assertTrue($record->_id instanceof \MongoId);
$this->assertFalse($record->isNewRecord);
$fileContent = $record->getFileContent();
$this->assertEquals(file_get_contents($fileName), $fileContent);
}
/**
* @depends testInsert
*/
public function testInsertFileContent()
{
$record = new CustomerFile;
$record->tag = 'new new';
$record->status = 7;
$newFileContent = 'Test new file content';
$record->setAttribute('newFileContent', $newFileContent);
$record->save();
$this->assertTrue($record->_id instanceof \MongoId);
$this->assertFalse($record->isNewRecord);
$fileContent = $record->getFileContent();
$this->assertEquals($newFileContent, $fileContent);
}
/**
* @depends testInsert
*/
public function testUpdate()
{
$record = new CustomerFile;
$record->tag = 'new new';
$record->status = 7;
$record->save();
// save
$record = CustomerFile::find($record->_id);
$this->assertTrue($record instanceof CustomerFile);
$this->assertEquals(7, $record->status);
$this->assertFalse($record->isNewRecord);
$record->status = 9;
$record->save();
$this->assertEquals(9, $record->status);
$this->assertFalse($record->isNewRecord);
$record2 = CustomerFile::find($record->_id);
$this->assertEquals(9, $record2->status);
// updateAll
$pk = ['_id' => $record->_id];
$ret = CustomerFile::updateAll(['status' => 55], $pk);
$this->assertEquals(1, $ret);
$record = CustomerFile::find($pk);
$this->assertEquals(55, $record->status);
}
/**
* @depends testUpdate
* @depends testInsertFileContent
*/
public function testUpdateFile()
{
$record = new CustomerFile;
$record->tag = 'new new';
$record->status = 7;
$newFileContent = 'Test new file content';
$record->setAttribute('newFileContent', $newFileContent);
$record->save();
$updateFileName = __FILE__;
$record = CustomerFile::find($record->_id);
$record->setAttribute('file', $updateFileName);
$record->status = 55;
$record->save();
$this->assertEquals(file_get_contents($updateFileName), $record->getFileContent());
$record2 = CustomerFile::find($record->_id);
$this->assertEquals($record->status, $record2->status);
$this->assertEquals(file_get_contents($updateFileName), $record2->getFileContent());
}
/**
* @depends testUpdate
* @depends testInsertFileContent
*/
public function testUpdateFileContent()
{
$record = new CustomerFile;
$record->tag = 'new new';
$record->status = 7;
$newFileContent = 'Test new file content';
$record->setAttribute('newFileContent', $newFileContent);
$record->save();
$updateFileContent = 'New updated file content';
$record = CustomerFile::find($record->_id);
$record->setAttribute('newFileContent', $updateFileContent);
$record->status = 55;
$record->save();
$this->assertEquals($updateFileContent, $record->getFileContent());
$record2 = CustomerFile::find($record->_id);
$this->assertEquals($record->status, $record2->status);
$this->assertEquals($updateFileContent, $record2->getFileContent());
}
/**
* @depends testInsertFileContent
*/
public function testWriteFile()
{
$record = new CustomerFile;
$record->tag = 'new new';
$record->status = 7;
$newFileContent = 'Test new file content';
$record->setAttribute('newFileContent', $newFileContent);
$record->save();
$outputFileName = $this->getTestFilePath() . DIRECTORY_SEPARATOR . 'out.txt';
$this->assertTrue($record->writeFile($outputFileName));
$this->assertEquals($newFileContent, file_get_contents($outputFileName));
$record2 = CustomerFile::find($record->_id);
$outputFileName = $this->getTestFilePath() . DIRECTORY_SEPARATOR . 'out_refreshed.txt';
$this->assertTrue($record2->writeFile($outputFileName));
$this->assertEquals($newFileContent, file_get_contents($outputFileName));
}
/**
* @depends testInsertFileContent
*/
public function testGetFileResource()
{
$record = new CustomerFile;
$record->tag = 'new new';
$record->status = 7;
$newFileContent = 'Test new file content';
$record->setAttribute('newFileContent', $newFileContent);
$record->save();
$fileResource = $record->getFileResource();
$contents = stream_get_contents($fileResource);
fclose($fileResource);
$this->assertEquals($newFileContent, $contents);
$record2 = CustomerFile::find($record->_id);
$fileResource = $record2->getFileResource();
$contents = stream_get_contents($fileResource);
fclose($fileResource);
$this->assertEquals($newFileContent, $contents);
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo\file;
use yiiunit\extensions\mongo\MongoTestCase;
/**
* @group mongo
*/
class CollectionTest extends MongoTestCase
{
protected function tearDown()
{
$this->dropFileCollection('fs');
parent::tearDown();
}
// Tests :
public function testGetChunkCollection()
{
$collection = $this->getConnection()->getFileCollection();
$chunkCollection = $collection->getChunkCollection();
$this->assertTrue($chunkCollection instanceof \yii\mongo\Collection);
$this->assertTrue($chunkCollection->mongoCollection instanceof \MongoCollection);
}
public function testFind()
{
$collection = $this->getConnection()->getFileCollection();
$cursor = $collection->find();
$this->assertTrue($cursor instanceof \MongoGridFSCursor);
}
public function testInsertFile()
{
$collection = $this->getConnection()->getFileCollection();
$filename = __FILE__;
$id = $collection->insertFile($filename);
$this->assertTrue($id instanceof \MongoId);
$files = $this->findAll($collection);
$this->assertEquals(1, count($files));
/** @var $file \MongoGridFSFile */
$file = $files[0];
$this->assertEquals($filename, $file->getFilename());
$this->assertEquals(file_get_contents($filename), $file->getBytes());
}
public function testInsertFileContent()
{
$collection = $this->getConnection()->getFileCollection();
$bytes = 'Test file content';
$id = $collection->insertFileContent($bytes);
$this->assertTrue($id instanceof \MongoId);
$files = $this->findAll($collection);
$this->assertEquals(1, count($files));
/** @var $file \MongoGridFSFile */
$file = $files[0];
$this->assertEquals($bytes, $file->getBytes());
}
/**
* @depends testInsertFileContent
*/
public function testGet()
{
$collection = $this->getConnection()->getFileCollection();
$bytes = 'Test file content';
$id = $collection->insertFileContent($bytes);
$file = $collection->get($id);
$this->assertTrue($file instanceof \MongoGridFSFile);
$this->assertEquals($bytes, $file->getBytes());
}
/**
* @depends testGet
*/
public function testDelete()
{
$collection = $this->getConnection()->getFileCollection();
$bytes = 'Test file content';
$id = $collection->insertFileContent($bytes);
$this->assertTrue($collection->delete($id));
$file = $collection->get($id);
$this->assertNull($file);
}
}
\ No newline at end of file
<?php
namespace yiiunit\extensions\mongo\file;
use yii\mongo\file\Query;
use yiiunit\extensions\mongo\MongoTestCase;
/**
* @group mongo
*/
class QueryTest extends MongoTestCase
{
protected function setUp()
{
parent::setUp();
$this->setUpTestRows();
}
protected function tearDown()
{
$this->dropFileCollection();
parent::tearDown();
}
/**
* Sets up test rows.
*/
protected function setUpTestRows()
{
$collection = $this->getConnection()->getFileCollection();
for ($i = 1; $i <= 10; $i++) {
$collection->insertFileContent('content' . $i, [
'filename' => 'name' . $i,
'file_index' => $i,
]);
}
}
// Tests :
public function testAll()
{
$connection = $this->getConnection();
$query = new Query;
$rows = $query->from('fs')->all($connection);
$this->assertEquals(10, count($rows));
}
public function testOne()
{
$connection = $this->getConnection();
$query = new Query;
$row = $query->from('fs')->one($connection);
$this->assertTrue(is_array($row));
$this->assertTrue($row['file'] instanceof \MongoGridFSFile);
}
public function testDirectMatch()
{
$connection = $this->getConnection();
$query = new Query;
$rows = $query->from('fs')
->where(['file_index' => 5])
->all($connection);
$this->assertEquals(1, count($rows));
/** @var $file \MongoGridFSFile */
$file = $rows[0];
$this->assertEquals('name5', $file['filename']);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment