EMongoDocumentDataProvider.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. /**
  3. * EMongoDocumentDataProvider.php
  4. *
  5. * PHP version 5.2+
  6. *
  7. * @author Dariusz Górecki <darek.krk@gmail.com>
  8. * @author Invenzzia Group, open-source division of CleverIT company http://www.invenzzia.org
  9. * @copyright 2011 CleverIT http://www.cleverit.com.pl
  10. * @license http://www.yiiframework.com/license/ BSD license
  11. * @version 1.3
  12. * @category ext
  13. * @package ext.YiiMongoDbSuite
  14. * @since v1.0
  15. */
  16. /**
  17. * EMongoRecordDataProvider implements a data provider based on EMongoRecord.
  18. *
  19. * EMongoRecordDataProvider provides data in terms of MongoRecord objects which are
  20. * of class {@link modelClass}. It uses the AR {@link CActiveRecord::findAll} method
  21. * to retrieve the data from database. The {@link query} property can be used to
  22. * specify various query options, such as conditions, sorting, pagination, etc.
  23. *
  24. * @author canni
  25. * @since v1.0
  26. */
  27. class EMongoDocumentDataProvider extends CDataProvider
  28. {
  29. /**
  30. * @var string the name of key field. Defaults to '_id', as a mongo default document primary key.
  31. * @since v1.0
  32. */
  33. public $keyField;
  34. /**
  35. * @var string the primary ActiveRecord class name. The {@link getData()} method
  36. * will return a list of objects of this class.
  37. * @since v1.0
  38. */
  39. public $modelClass;
  40. /**
  41. * @var EMongoRecord the AR finder instance (e.g. <code>Post::model()</code>).
  42. * This property can be set by passing the finder instance as the first parameter
  43. * to the constructor.
  44. * @since v1.0
  45. */
  46. public $model;
  47. private $_criteria;
  48. /**
  49. * Constructor.
  50. * @param mixed $modelClass the model class (e.g. 'Post') or the model finder instance
  51. * (e.g. <code>Post::model()</code>, <code>Post::model()->published()</code>).
  52. * @param array $config configuration (name=>value) to be applied as the initial property values of this class.
  53. * @since v1.0
  54. */
  55. public function __construct($modelClass, $config = array())
  56. {
  57. if(is_string($modelClass))
  58. {
  59. $this->modelClass = $modelClass;
  60. $this->model = EMongoDocument::model($modelClass);
  61. }
  62. else if($modelClass instanceof EMongoDocument)
  63. {
  64. $this->modelClass = get_class($modelClass);
  65. $this->model = $modelClass;
  66. }
  67. $this->_criteria = $this->model->getDbCriteria();
  68. if(isset($config['criteria']))
  69. {
  70. $this->_criteria->mergeWith($config['criteria']);
  71. unset($config['criteria']);
  72. }
  73. $this->setId($this->modelClass);
  74. foreach($config as $key=>$value)
  75. $this->$key=$value;
  76. if($this->keyField!==null)
  77. {
  78. if(is_array($this->keyField))
  79. throw new CException('This DataProvider cannot handle multi-field primary key!');
  80. }
  81. else
  82. $this->keyField='_id';
  83. }
  84. /**
  85. * Returns the criteria.
  86. * @return array the query criteria
  87. * @since v1.0
  88. */
  89. public function getCriteria()
  90. {
  91. return $this->_criteria;
  92. }
  93. /**
  94. * Sets the query criteria.
  95. * @param array $value the query criteria. Array representing the MongoDB query criteria.
  96. * @since v1.0
  97. */
  98. public function setCriteria($criteria)
  99. {
  100. if(is_array($criteria))
  101. $this->_criteria = new EMongoCriteria($criteria);
  102. else if($criteria instanceof EMongoCriteria)
  103. $this->_criteria = $criteria;
  104. }
  105. /**
  106. * Fetches the data from the persistent data storage.
  107. * @return array list of data items
  108. * @since v1.0
  109. */
  110. protected function fetchData()
  111. {
  112. if(($pagination=$this->getPagination())!==false)
  113. {
  114. $pagination->setItemCount($this->getTotalItemCount());
  115. $this->_criteria->setLimit($pagination->getLimit());
  116. $this->_criteria->setOffset($pagination->getOffset());
  117. }
  118. if(($sort=$this->getSort())!==false && ($order=$sort->getOrderBy())!='')
  119. {
  120. $sort=array();
  121. foreach($this->getSortDirections($order) as $name=>$descending)
  122. {
  123. $sort[$name]=$descending ? EMongoCriteria::SORT_DESC : EMongoCriteria::SORT_ASC;
  124. }
  125. $this->_criteria->setSort($sort);
  126. }
  127. return $this->model->findAll($this->_criteria);
  128. }
  129. /**
  130. * Fetches the data item keys from the persistent data storage.
  131. * @return array list of data item keys.
  132. * @since v1.0
  133. */
  134. protected function fetchKeys()
  135. {
  136. $keys = array();
  137. foreach($this->getData() as $i=>$data)
  138. {
  139. $keys[$i] = $data->{$this->keyField};
  140. }
  141. return $keys;
  142. }
  143. /**
  144. * Calculates the total number of data items.
  145. * @return integer the total number of data items.
  146. * @since v1.0
  147. */
  148. public function calculateTotalItemCount()
  149. {
  150. return $this->model->count($this->_criteria);
  151. }
  152. /**
  153. * Converts the "ORDER BY" clause into an array representing the sorting directions.
  154. * @param string $order the "ORDER BY" clause.
  155. * @return array the sorting directions (field name => whether it is descending sort)
  156. * @since v1.0
  157. */
  158. protected function getSortDirections($order)
  159. {
  160. $segs=explode(',',$order);
  161. $directions=array();
  162. foreach($segs as $seg)
  163. {
  164. if(preg_match('/(.*?)(\s+(desc|asc))?$/i',trim($seg),$matches))
  165. $directions[$matches[1]]=isset($matches[3]) && !strcasecmp($matches[3],'desc');
  166. else
  167. $directions[trim($seg)]=false;
  168. }
  169. return $directions;
  170. }
  171. }