* @author Invenzzia Group, open-source division of CleverIT company http://www.invenzzia.org * @copyright 2011 CleverIT http://www.cleverit.com.pl * @license http://www.yiiframework.com/license/ BSD license * @version 1.3 * @category ext * @package ext.YiiMongoDbSuite * @since v1.0 */ /** * EMongoRecordDataProvider implements a data provider based on EMongoRecord. * * EMongoRecordDataProvider provides data in terms of MongoRecord objects which are * of class {@link modelClass}. It uses the AR {@link CActiveRecord::findAll} method * to retrieve the data from database. The {@link query} property can be used to * specify various query options, such as conditions, sorting, pagination, etc. * * @author canni * @since v1.0 */ class EMongoDocumentDataProvider extends CDataProvider { /** * @var string the name of key field. Defaults to '_id', as a mongo default document primary key. * @since v1.0 */ public $keyField; /** * @var string the primary ActiveRecord class name. The {@link getData()} method * will return a list of objects of this class. * @since v1.0 */ public $modelClass; /** * @var EMongoRecord the AR finder instance (e.g. Post::model()). * This property can be set by passing the finder instance as the first parameter * to the constructor. * @since v1.0 */ public $model; private $_criteria; /** * Constructor. * @param mixed $modelClass the model class (e.g. 'Post') or the model finder instance * (e.g. Post::model(), Post::model()->published()). * @param array $config configuration (name=>value) to be applied as the initial property values of this class. * @since v1.0 */ public function __construct($modelClass, $config = array()) { if(is_string($modelClass)) { $this->modelClass = $modelClass; $this->model = EMongoDocument::model($modelClass); } else if($modelClass instanceof EMongoDocument) { $this->modelClass = get_class($modelClass); $this->model = $modelClass; } $this->_criteria = $this->model->getDbCriteria(); if(isset($config['criteria'])) { $this->_criteria->mergeWith($config['criteria']); unset($config['criteria']); } $this->setId($this->modelClass); foreach($config as $key=>$value) $this->$key=$value; if($this->keyField!==null) { if(is_array($this->keyField)) throw new CException('This DataProvider cannot handle multi-field primary key!'); } else $this->keyField='_id'; } /** * Returns the criteria. * @return array the query criteria * @since v1.0 */ public function getCriteria() { return $this->_criteria; } /** * Sets the query criteria. * @param array $value the query criteria. Array representing the MongoDB query criteria. * @since v1.0 */ public function setCriteria($criteria) { if(is_array($criteria)) $this->_criteria = new EMongoCriteria($criteria); else if($criteria instanceof EMongoCriteria) $this->_criteria = $criteria; } /** * Fetches the data from the persistent data storage. * @return array list of data items * @since v1.0 */ protected function fetchData() { if(($pagination=$this->getPagination())!==false) { $pagination->setItemCount($this->getTotalItemCount()); $this->_criteria->setLimit($pagination->getLimit()); $this->_criteria->setOffset($pagination->getOffset()); } if(($sort=$this->getSort())!==false && ($order=$sort->getOrderBy())!='') { $sort=array(); foreach($this->getSortDirections($order) as $name=>$descending) { $sort[$name]=$descending ? EMongoCriteria::SORT_DESC : EMongoCriteria::SORT_ASC; } $this->_criteria->setSort($sort); } return $this->model->findAll($this->_criteria); } /** * Fetches the data item keys from the persistent data storage. * @return array list of data item keys. * @since v1.0 */ protected function fetchKeys() { $keys = array(); foreach($this->getData() as $i=>$data) { $keys[$i] = $data->{$this->keyField}; } return $keys; } /** * Calculates the total number of data items. * @return integer the total number of data items. * @since v1.0 */ public function calculateTotalItemCount() { return $this->model->count($this->_criteria); } /** * Converts the "ORDER BY" clause into an array representing the sorting directions. * @param string $order the "ORDER BY" clause. * @return array the sorting directions (field name => whether it is descending sort) * @since v1.0 */ protected function getSortDirections($order) { $segs=explode(',',$order); $directions=array(); foreach($segs as $seg) { if(preg_match('/(.*?)(\s+(desc|asc))?$/i',trim($seg),$matches)) $directions[$matches[1]]=isset($matches[3]) && !strcasecmp($matches[3],'desc'); else $directions[trim($seg)]=false; } return $directions; } }