CArrayDataProvider.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. /**
  3. * CArrayDataProvider class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CArrayDataProvider implements a data provider based on a raw data array.
  12. *
  13. * The {@link rawData} property contains all data that may be sorted and/or paginated.
  14. * CArrayDataProvider will supply the data after sorting and/or pagination.
  15. * You may configure the {@link sort} and {@link pagination} properties to
  16. * customize sorting and pagination behaviors.
  17. *
  18. * Elements in the raw data array may be either objects (e.g. model objects)
  19. * or associative arrays (e.g. query results of DAO).
  20. * Make sure to set the {@link keyField} property to the name of the field that uniquely
  21. * identifies a data record or false if you do not have such a field.
  22. *
  23. * CArrayDataProvider may be used in the following way:
  24. * <pre>
  25. * $rawData=Yii::app()->db->createCommand('SELECT * FROM tbl_user')->queryAll();
  26. * // or using: $rawData=User::model()->findAll();
  27. * $dataProvider=new CArrayDataProvider($rawData, array(
  28. * 'id'=>'user',
  29. * 'sort'=>array(
  30. * 'attributes'=>array(
  31. * 'id', 'username', 'email',
  32. * ),
  33. * ),
  34. * 'pagination'=>array(
  35. * 'pageSize'=>10,
  36. * ),
  37. * ));
  38. * // $dataProvider->getData() will return a list of arrays.
  39. * </pre>
  40. *
  41. * Note: if you want to use the sorting feature, you must configure {@link sort} property
  42. * so that the provider knows which columns can be sorted.
  43. *
  44. * @author Qiang Xue <qiang.xue@gmail.com>
  45. * @package system.web
  46. * @since 1.1.4
  47. */
  48. class CArrayDataProvider extends CDataProvider
  49. {
  50. /**
  51. * @var string the name of the key field. This is a field that uniquely identifies a
  52. * data record. In database this would be the primary key.
  53. * Defaults to 'id'. If it's set to false, keys of {@link rawData} array are used.
  54. */
  55. public $keyField='id';
  56. /**
  57. * @var array the data that is not paginated or sorted. When pagination is enabled,
  58. * this property usually contains more elements than {@link data}.
  59. * The array elements must use zero-based integer keys.
  60. */
  61. public $rawData=array();
  62. /**
  63. * @var boolean controls how sorting works. True value means that case will be
  64. * taken into account. False value will lead to the case insensitive sort. Default
  65. * value is true.
  66. * @since 1.1.13
  67. */
  68. public $caseSensitiveSort=true;
  69. /**
  70. * Constructor.
  71. * @param array $rawData the data that is not paginated or sorted. The array elements must use zero-based integer keys.
  72. * @param array $config configuration (name=>value) to be applied as the initial property values of this class.
  73. */
  74. public function __construct($rawData,$config=array())
  75. {
  76. $this->rawData=$rawData;
  77. foreach($config as $key=>$value)
  78. $this->$key=$value;
  79. }
  80. /**
  81. * Fetches the data from the persistent data storage.
  82. * @return array list of data items
  83. */
  84. protected function fetchData()
  85. {
  86. if(($sort=$this->getSort())!==false && ($order=$sort->getOrderBy())!='')
  87. $this->sortData($this->getSortDirections($order));
  88. if(($pagination=$this->getPagination())!==false)
  89. {
  90. $pagination->setItemCount($this->getTotalItemCount());
  91. return array_slice($this->rawData, $pagination->getOffset(), $pagination->getLimit());
  92. }
  93. else
  94. return $this->rawData;
  95. }
  96. /**
  97. * Fetches the data item keys from the persistent data storage.
  98. * @return array list of data item keys.
  99. */
  100. protected function fetchKeys()
  101. {
  102. if($this->keyField===false)
  103. return array_keys($this->rawData);
  104. $keys=array();
  105. foreach($this->getData() as $i=>$data)
  106. $keys[$i]=is_object($data) ? $data->{$this->keyField} : $data[$this->keyField];
  107. return $keys;
  108. }
  109. /**
  110. * Calculates the total number of data items.
  111. * This method simply returns the number of elements in {@link rawData}.
  112. * @return integer the total number of data items.
  113. */
  114. protected function calculateTotalItemCount()
  115. {
  116. return count($this->rawData);
  117. }
  118. /**
  119. * Sorts the raw data according to the specified sorting instructions.
  120. * After calling this method, {@link rawData} will be modified.
  121. * @param array $directions the sorting directions (field name => whether it is descending sort)
  122. */
  123. protected function sortData($directions)
  124. {
  125. if(empty($directions))
  126. return;
  127. $args=array();
  128. $dummy=array();
  129. foreach($directions as $name=>$descending)
  130. {
  131. $column=array();
  132. $fields_array=preg_split('/\.+/',$name,-1,PREG_SPLIT_NO_EMPTY);
  133. foreach($this->rawData as $index=>$data)
  134. $column[$index]=$this->getSortingFieldValue($data, $fields_array);
  135. $args[]=&$column;
  136. $dummy[]=&$column;
  137. unset($column);
  138. $direction=$descending ? SORT_DESC : SORT_ASC;
  139. $args[]=&$direction;
  140. $dummy[]=&$direction;
  141. unset($direction);
  142. }
  143. $args[]=&$this->rawData;
  144. call_user_func_array('array_multisort', $args);
  145. }
  146. /**
  147. * Get field for sorting, using dot like delimiter in query.
  148. * @param mixed $data array or object
  149. * @param array $fields sorting fields in $data
  150. * @return mixed $data sorting field value
  151. */
  152. protected function getSortingFieldValue($data, $fields)
  153. {
  154. if(is_object($data))
  155. {
  156. foreach($fields as $field)
  157. $data=isset($data->$field) ? $data->$field : null;
  158. }
  159. else
  160. {
  161. foreach($fields as $field)
  162. $data=isset($data[$field]) ? $data[$field] : null;
  163. }
  164. return $this->caseSensitiveSort ? $data : mb_strtolower($data,Yii::app()->charset);
  165. }
  166. /**
  167. * Converts the "ORDER BY" clause into an array representing the sorting directions.
  168. * @param string $order the "ORDER BY" clause.
  169. * @return array the sorting directions (field name => whether it is descending sort)
  170. */
  171. protected function getSortDirections($order)
  172. {
  173. $segs=explode(',',$order);
  174. $directions=array();
  175. foreach($segs as $seg)
  176. {
  177. if(preg_match('/(.*?)(\s+(desc|asc))?$/i',trim($seg),$matches))
  178. $directions[$matches[1]]=isset($matches[3]) && !strcasecmp($matches[3],'desc');
  179. else
  180. $directions[trim($seg)]=false;
  181. }
  182. return $directions;
  183. }
  184. }