1: <?php
2: /**
3: * CActiveDataProvider 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: /**
12: * CActiveDataProvider implements a data provider based on ActiveRecord.
13: *
14: * CActiveDataProvider provides data in terms of ActiveRecord objects which are
15: * of class {@link modelClass}. It uses the AR {@link CActiveRecord::findAll} method
16: * to retrieve the data from database. The {@link criteria} property can be used to
17: * specify various query options.
18: *
19: * CActiveDataProvider may be used in the following way:
20: * <pre>
21: * $dataProvider=new CActiveDataProvider('Post', array(
22: * 'criteria'=>array(
23: * 'condition'=>'status=1',
24: * 'order'=>'create_time DESC',
25: * 'with'=>array('author'),
26: * ),
27: * 'countCriteria'=>array(
28: * 'condition'=>'status=1',
29: * // 'order' and 'with' clauses have no meaning for the count query
30: * ),
31: * 'pagination'=>array(
32: * 'pageSize'=>20,
33: * ),
34: * ));
35: * // $dataProvider->getData() will return a list of Post objects
36: * </pre>
37: *
38: * @property CDbCriteria $criteria The query criteria.
39: * @property CDbCriteria $countCriteria The count query criteria. This property is available
40: * since 1.1.14
41: * @property CSort $sort The sorting object. If this is false, it means the sorting is disabled.
42: *
43: * @author Qiang Xue <qiang.xue@gmail.com>
44: * @package system.web
45: * @since 1.1
46: */
47: class CActiveDataProvider extends CDataProvider
48: {
49: /**
50: * @var string the primary ActiveRecord class name. The {@link getData()} method
51: * will return a list of objects of this class.
52: */
53: public $modelClass;
54: /**
55: * @var CActiveRecord the AR finder instance (eg <code>Post::model()</code>).
56: * This property can be set by passing the finder instance as the first parameter
57: * to the constructor. For example, <code>Post::model()->published()</code>.
58: * @since 1.1.3
59: */
60: public $model;
61: /**
62: * @var string the name of key attribute for {@link modelClass}. If not set,
63: * it means the primary key of the corresponding database table will be used.
64: */
65: public $keyAttribute;
66:
67: /**
68: * @var CDbCriteria
69: */
70: private $_criteria;
71: /**
72: * @var CDbCriteria
73: */
74: private $_countCriteria;
75:
76: /**
77: * Constructor.
78: * @param mixed $modelClass the model class (e.g. 'Post') or the model finder instance
79: * (e.g. <code>Post::model()</code>, <code>Post::model()->published()</code>).
80: * @param array $config configuration (name=>value) to be applied as the initial property values of this class.
81: */
82: public function __construct($modelClass,$config=array())
83: {
84: if(is_string($modelClass))
85: {
86: $this->modelClass=$modelClass;
87: $this->model=$this->getModel($this->modelClass);
88: }
89: elseif($modelClass instanceof CActiveRecord)
90: {
91: $this->modelClass=get_class($modelClass);
92: $this->model=$modelClass;
93: }
94: $this->setId(CHtml::modelName($this->model));
95: foreach($config as $key=>$value)
96: $this->$key=$value;
97: }
98:
99: /**
100: * Returns the query criteria.
101: * @return CDbCriteria the query criteria
102: */
103: public function getCriteria()
104: {
105: if($this->_criteria===null)
106: $this->_criteria=new CDbCriteria;
107: return $this->_criteria;
108: }
109:
110: /**
111: * Sets the query criteria.
112: * @param CDbCriteria|array $value the query criteria. This can be either a CDbCriteria object or an array
113: * representing the query criteria.
114: */
115: public function setCriteria($value)
116: {
117: $this->_criteria=$value instanceof CDbCriteria ? $value : new CDbCriteria($value);
118: }
119:
120: /**
121: * Returns the count query criteria.
122: * @return CDbCriteria the count query criteria.
123: * @since 1.1.14
124: */
125: public function getCountCriteria()
126: {
127: if($this->_countCriteria===null)
128: return $this->getCriteria();
129: return $this->_countCriteria;
130: }
131:
132: /**
133: * Sets the count query criteria.
134: * @param CDbCriteria|array $value the count query criteria. This can be either a CDbCriteria object
135: * or an array representing the query criteria.
136: * @since 1.1.14
137: */
138: public function setCountCriteria($value)
139: {
140: $this->_countCriteria=$value instanceof CDbCriteria ? $value : new CDbCriteria($value);
141: }
142:
143: /**
144: * Returns the sorting object.
145: * @param string $className the sorting object class name. Parameter is available since version 1.1.13.
146: * @return CSort the sorting object. If this is false, it means the sorting is disabled.
147: */
148: public function getSort($className='CSort')
149: {
150: if(($sort=parent::getSort($className))!==false)
151: $sort->modelClass=$this->modelClass;
152: return $sort;
153: }
154:
155: /**
156: * Given active record class name returns new model instance.
157: *
158: * @param string $className active record class name.
159: * @return CActiveRecord active record model instance.
160: *
161: * @since 1.1.14
162: */
163: protected function getModel($className)
164: {
165: return CActiveRecord::model($className);
166: }
167:
168: /**
169: * Fetches the data from the persistent data storage.
170: * @return array list of data items
171: */
172: protected function fetchData()
173: {
174: $criteria=clone $this->getCriteria();
175:
176: if(($pagination=$this->getPagination())!==false)
177: {
178: $pagination->setItemCount($this->getTotalItemCount());
179: $pagination->applyLimit($criteria);
180: }
181:
182: $baseCriteria=$this->model->getDbCriteria(false);
183:
184: if(($sort=$this->getSort())!==false)
185: {
186: // set model criteria so that CSort can use its table alias setting
187: if($baseCriteria!==null)
188: {
189: $c=clone $baseCriteria;
190: $c->mergeWith($criteria);
191: $this->model->setDbCriteria($c);
192: }
193: else
194: $this->model->setDbCriteria($criteria);
195: $sort->applyOrder($criteria);
196: }
197:
198: $this->model->setDbCriteria($baseCriteria!==null ? clone $baseCriteria : null);
199: $data=$this->model->findAll($criteria);
200: $this->model->setDbCriteria($baseCriteria); // restore original criteria
201: return $data;
202: }
203:
204: /**
205: * Fetches the data item keys from the persistent data storage.
206: * @return array list of data item keys.
207: */
208: protected function fetchKeys()
209: {
210: $keys=array();
211: foreach($this->getData() as $i=>$data)
212: {
213: $key=$this->keyAttribute===null ? $data->getPrimaryKey() : $data->{$this->keyAttribute};
214: $keys[$i]=is_array($key) ? implode(',',$key) : $key;
215: }
216: return $keys;
217: }
218:
219: /**
220: * Calculates the total number of data items.
221: * @return integer the total number of data items.
222: */
223: protected function calculateTotalItemCount()
224: {
225: $baseCriteria=$this->model->getDbCriteria(false);
226: if($baseCriteria!==null)
227: $baseCriteria=clone $baseCriteria;
228: $count=$this->model->count($this->getCountCriteria());
229: $this->model->setDbCriteria($baseCriteria);
230: return $count;
231: }
232: }
233: