From 0035f23781750f2e598077e11fa8deb43b10bd21 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Tue, 1 Oct 2013 21:35:35 -0400 Subject: [PATCH] refactored data providers. --- framework/yii/classes.php | 27 +-- framework/yii/data/ActiveDataProvider.php | 158 ++++--------- framework/yii/data/ArrayDataProvider.php | 104 +++------ framework/yii/data/BaseDataProvider.php | 253 +++++++++++++++++++++ framework/yii/data/DataProvider.php | 133 ----------- framework/yii/data/DataProviderInterface.php | 12 + framework/yii/widgets/BaseListView.php | 1 + .../unit/framework/data/ActiveDataProviderTest.php | 5 +- 8 files changed, 357 insertions(+), 336 deletions(-) create mode 100644 framework/yii/data/BaseDataProvider.php delete mode 100644 framework/yii/data/DataProvider.php diff --git a/framework/yii/classes.php b/framework/yii/classes.php index 1469910..78cce95 100644 --- a/framework/yii/classes.php +++ b/framework/yii/classes.php @@ -85,7 +85,7 @@ return array( 'yii\captcha\CaptchaValidator' => YII_PATH . '/captcha/CaptchaValidator.php', 'yii\data\ActiveDataProvider' => YII_PATH . '/data/ActiveDataProvider.php', 'yii\data\ArrayDataProvider' => YII_PATH . '/data/ArrayDataProvider.php', - 'yii\data\DataProvider' => YII_PATH . '/data/DataProvider.php', + 'yii\data\BaseDataProvider' => YII_PATH . '/data/BaseDataProvider.php', 'yii\data\DataProviderInterface' => YII_PATH . '/data/DataProviderInterface.php', 'yii\data\Pagination' => YII_PATH . '/data/Pagination.php', 'yii\data\Sort' => YII_PATH . '/data/Sort.php', @@ -118,6 +118,7 @@ return array( 'yii\db\pgsql\Schema' => YII_PATH . '/db/pgsql/Schema.php', 'yii\db\sqlite\QueryBuilder' => YII_PATH . '/db/sqlite/QueryBuilder.php', 'yii\db\sqlite\Schema' => YII_PATH . '/db/sqlite/Schema.php', + 'yii\grid\ActionColumn' => YII_PATH . '/grid/ActionColumn.php', 'yii\grid\CheckboxColumn' => YII_PATH . '/grid/CheckboxColumn.php', 'yii\grid\Column' => YII_PATH . '/grid/Column.php', 'yii\grid\DataColumn' => YII_PATH . '/grid/DataColumn.php', @@ -126,26 +127,26 @@ return array( 'yii\grid\SerialColumn' => YII_PATH . '/grid/SerialColumn.php', 'yii\helpers\ArrayHelper' => YII_PATH . '/helpers/ArrayHelper.php', 'yii\helpers\BaseArrayHelper' => YII_PATH . '/helpers/BaseArrayHelper.php', - 'yii\helpers\Console' => YII_PATH . '/helpers/Console.php', 'yii\helpers\BaseConsole' => YII_PATH . '/helpers/BaseConsole.php', - 'yii\helpers\FileHelper' => YII_PATH . '/helpers/FileHelper.php', 'yii\helpers\BaseFileHelper' => YII_PATH . '/helpers/BaseFileHelper.php', - 'yii\helpers\Html' => YII_PATH . '/helpers/Html.php', 'yii\helpers\BaseHtml' => YII_PATH . '/helpers/BaseHtml.php', - 'yii\helpers\HtmlPurifier' => YII_PATH . '/helpers/HtmlPurifier.php', 'yii\helpers\BaseHtmlPurifier' => YII_PATH . '/helpers/BaseHtmlPurifier.php', - 'yii\helpers\Inflector' => YII_PATH . '/helpers/Inflector.php', 'yii\helpers\BaseInflector' => YII_PATH . '/helpers/BaseInflector.php', - 'yii\helpers\Json' => YII_PATH . '/helpers/Json.php', 'yii\helpers\BaseJson' => YII_PATH . '/helpers/BaseJson.php', - 'yii\helpers\Markdown' => YII_PATH . '/helpers/Markdown.php', 'yii\helpers\BaseMarkdown' => YII_PATH . '/helpers/BaseMarkdown.php', - 'yii\helpers\Security' => YII_PATH . '/helpers/Security.php', 'yii\helpers\BaseSecurity' => YII_PATH . '/helpers/BaseSecurity.php', - 'yii\helpers\StringHelper' => YII_PATH . '/helpers/StringHelper.php', 'yii\helpers\BaseStringHelper' => YII_PATH . '/helpers/BaseStringHelper.php', - 'yii\helpers\VarDumper' => YII_PATH . '/helpers/VarDumper.php', 'yii\helpers\BaseVarDumper' => YII_PATH . '/helpers/BaseVarDumper.php', + 'yii\helpers\Console' => YII_PATH . '/helpers/Console.php', + 'yii\helpers\FileHelper' => YII_PATH . '/helpers/FileHelper.php', + 'yii\helpers\Html' => YII_PATH . '/helpers/Html.php', + 'yii\helpers\HtmlPurifier' => YII_PATH . '/helpers/HtmlPurifier.php', + 'yii\helpers\Inflector' => YII_PATH . '/helpers/Inflector.php', + 'yii\helpers\Json' => YII_PATH . '/helpers/Json.php', + 'yii\helpers\Markdown' => YII_PATH . '/helpers/Markdown.php', + 'yii\helpers\Security' => YII_PATH . '/helpers/Security.php', + 'yii\helpers\StringHelper' => YII_PATH . '/helpers/StringHelper.php', + 'yii\helpers\VarDumper' => YII_PATH . '/helpers/VarDumper.php', 'yii\i18n\DbMessageSource' => YII_PATH . '/i18n/DbMessageSource.php', 'yii\i18n\Formatter' => YII_PATH . '/i18n/Formatter.php', 'yii\i18n\GettextFile' => YII_PATH . '/i18n/GettextFile.php', @@ -194,6 +195,7 @@ return array( 'yii\web\Application' => YII_PATH . '/web/Application.php', 'yii\web\AssetBundle' => YII_PATH . '/web/AssetBundle.php', 'yii\web\AssetConverter' => YII_PATH . '/web/AssetConverter.php', + 'yii\web\AssetConverterInterface' => YII_PATH . '/web/AssetConverterInterface.php', 'yii\web\AssetManager' => YII_PATH . '/web/AssetManager.php', 'yii\web\CacheSession' => YII_PATH . '/web/CacheSession.php', 'yii\web\Controller' => YII_PATH . '/web/Controller.php', @@ -204,7 +206,6 @@ return array( 'yii\web\HeaderCollection' => YII_PATH . '/web/HeaderCollection.php', 'yii\web\HttpCache' => YII_PATH . '/web/HttpCache.php', 'yii\web\HttpException' => YII_PATH . '/web/HttpException.php', - 'yii\web\AssetConverterInterface' => YII_PATH . '/web/AssetConverterInterface.php', 'yii\web\IdentityInterface' => YII_PATH . '/web/IdentityInterface.php', 'yii\web\JqueryAsset' => YII_PATH . '/web/JqueryAsset.php', 'yii\web\JsExpression' => YII_PATH . '/web/JsExpression.php', @@ -226,6 +227,7 @@ return array( 'yii\widgets\ActiveField' => YII_PATH . '/widgets/ActiveField.php', 'yii\widgets\ActiveForm' => YII_PATH . '/widgets/ActiveForm.php', 'yii\widgets\ActiveFormAsset' => YII_PATH . '/widgets/ActiveFormAsset.php', + 'yii\widgets\BaseListView' => YII_PATH . '/widgets/BaseListView.php', 'yii\widgets\Block' => YII_PATH . '/widgets/Block.php', 'yii\widgets\Breadcrumbs' => YII_PATH . '/widgets/Breadcrumbs.php', 'yii\widgets\ContentDecorator' => YII_PATH . '/widgets/ContentDecorator.php', @@ -235,7 +237,6 @@ return array( 'yii\widgets\LinkPager' => YII_PATH . '/widgets/LinkPager.php', 'yii\widgets\LinkSorter' => YII_PATH . '/widgets/LinkSorter.php', 'yii\widgets\ListView' => YII_PATH . '/widgets/ListView.php', - 'yii\widgets\BaseListView' => YII_PATH . '/widgets/BaseListView.php', 'yii\widgets\MaskedInput' => YII_PATH . '/widgets/MaskedInput.php', 'yii\widgets\MaskedInputAsset' => YII_PATH . '/widgets/MaskedInputAsset.php', 'yii\widgets\Menu' => YII_PATH . '/widgets/Menu.php', diff --git a/framework/yii/data/ActiveDataProvider.php b/framework/yii/data/ActiveDataProvider.php index 2fe0efb..c5f1bcd 100644 --- a/framework/yii/data/ActiveDataProvider.php +++ b/framework/yii/data/ActiveDataProvider.php @@ -48,16 +48,10 @@ use yii\db\Connection; * $posts = $provider->getModels(); * ~~~ * - * @property integer $count The number of data models in the current page. This property is read-only. - * @property array $keys The list of key values corresponding to [[models]]. Each data model in [[models]] is - * uniquely identified by the corresponding key value in this array. This property is read-only. - * @property array $models The list of data models in the current page. This property is read-only. - * @property integer $totalCount Total number of possible data models. - * * @author Qiang Xue * @since 2.0 */ -class ActiveDataProvider extends DataProvider +class ActiveDataProvider extends BaseDataProvider { /** * @var Query the query that is used to fetch data models and [[totalCount]] @@ -82,10 +76,6 @@ class ActiveDataProvider extends DataProvider */ public $db; - private $_models; - private $_keys; - private $_totalCount; - /** * Initializes the DbCache component. * This method will initialize the [[db]] property to make sure it refers to a valid DB connection. @@ -103,122 +93,72 @@ class ActiveDataProvider extends DataProvider } /** - * Returns the number of data models in the current page. - * This is equivalent to `count($provider->models)`. - * When [[pagination]] is false, this is the same as [[totalCount]]. - * @return integer the number of data models in the current page. - */ - public function getCount() - { - return count($this->getModels()); - } - - /** - * Returns the total number of data models. - * When [[pagination]] is false, this returns the same value as [[count]]. - * If [[totalCount]] is not explicitly set, it will be calculated - * using [[query]] with a COUNT query. - * @return integer total number of possible data models. - * @throws InvalidConfigException + * @inheritdoc */ - public function getTotalCount() + protected function prepareModels() { - if ($this->getPagination() === false) { - return $this->getCount(); - } elseif ($this->_totalCount === null) { - if (!$this->query instanceof Query) { - throw new InvalidConfigException('The "query" property must be an instance of Query or its subclass.'); - } - $query = clone $this->query; - $this->_totalCount = $query->limit(-1)->offset(-1)->count('*', $this->db); + if (!$this->query instanceof Query) { + throw new InvalidConfigException('The "query" property must be an instance of Query or its subclass.'); } - return $this->_totalCount; - } - - /** - * Sets the total number of data models. - * @param integer $value the total number of data models. - */ - public function setTotalCount($value) - { - $this->_totalCount = $value; - } - - /** - * Returns the data models in the current page. - * @return array the list of data models in the current page. - * @throws InvalidConfigException if [[query]] is not set or invalid. - */ - public function getModels() - { - if ($this->_models === null) { - if (!$this->query instanceof Query) { - throw new InvalidConfigException('The "query" property must be an instance of Query or its subclass.'); - } - if (($pagination = $this->getPagination()) !== false) { - $this->query->limit($pagination->getLimit())->offset($pagination->getOffset()); - } - if (($sort = $this->getSort()) !== false) { - $this->query->addOrderBy($sort->getOrders()); - } - $this->_models = $this->query->all($this->db); + if (($pagination = $this->getPagination()) !== false) { + $pagination->totalCount = $this->getTotalCount(); + $this->query->limit($pagination->getLimit())->offset($pagination->getOffset()); + } + if (($sort = $this->getSort()) !== false) { + $this->query->addOrderBy($sort->getOrders()); } - return $this->_models; + return $this->query->all($this->db); } /** - * Returns the key values associated with the data models. - * @return array the list of key values corresponding to [[models]]. Each data model in [[models]] - * is uniquely identified by the corresponding key value in this array. + * @inheritdoc */ - public function getKeys() + protected function prepareKeys($models) { - if ($this->_keys === null) { - $this->_keys = array(); - $models = $this->getModels(); - if ($this->key !== null) { + $keys = array(); + if ($this->key !== null) { + foreach ($models as $model) { + if (is_string($this->key)) { + $keys[] = $model[$this->key]; + } else { + $keys[] = call_user_func($this->key, $model); + } + } + return $keys; + } elseif ($this->query instanceof ActiveQuery) { + /** @var \yii\db\ActiveRecord $class */ + $class = $this->query->modelClass; + $pks = $class::primaryKey(); + if (count($pks) === 1) { + $pk = $pks[0]; foreach ($models as $model) { - if (is_string($this->key)) { - $this->_keys[] = $model[$this->key]; - } else { - $this->_keys[] = call_user_func($this->key, $model); - } + $keys[] = $model[$pk]; } - } elseif ($this->query instanceof ActiveQuery) { - /** @var \yii\db\ActiveRecord $class */ - $class = $this->query->modelClass; - $pks = $class::primaryKey(); - if (count($pks) === 1) { - $pk = $pks[0]; - foreach ($models as $model) { - $this->_keys[] = $model[$pk]; - } - } else { - foreach ($models as $model) { - $keys = array(); - foreach ($pks as $pk) { - $keys[] = $model[$pk]; - } - $this->_keys[] = json_encode($keys); + } else { + foreach ($models as $model) { + $kk = array(); + foreach ($pks as $pk) { + $kk[] = $model[$pk]; } + $keys[] = json_encode($kk); } - } else { - $this->_keys = array_keys($models); } + return $keys; + } else { + return array_keys($models); } - return $this->_keys; } /** - * Refreshes the data provider. - * After calling this method, if [[getModels()]], [[getKeys()]] or [[getTotalCount()]] is called again, - * they will re-execute the query and return the latest data available. + * @inheritdoc */ - public function refresh() + protected function prepareTotalCount() { - $this->_models = null; - $this->_totalCount = null; - $this->_keys = null; + if (!$this->query instanceof Query) { + throw new InvalidConfigException('The "query" property must be an instance of Query or its subclass.'); + } + $query = clone $this->query; + return $query->limit(-1)->offset(-1)->count('*', $this->db); } /** @@ -227,9 +167,7 @@ class ActiveDataProvider extends DataProvider public function setSort($value) { parent::setSort($value); - if (($sort = $this->getSort()) !== false && empty($sort->attributes) && - $this->query instanceof ActiveQuery) { - + if (($sort = $this->getSort()) !== false && empty($sort->attributes) && $this->query instanceof ActiveQuery) { /** @var Model $model */ $model = new $this->query->modelClass; foreach($model->attributes() as $attribute) { diff --git a/framework/yii/data/ArrayDataProvider.php b/framework/yii/data/ArrayDataProvider.php index 9534803..925c18e 100644 --- a/framework/yii/data/ArrayDataProvider.php +++ b/framework/yii/data/ArrayDataProvider.php @@ -47,15 +47,10 @@ use yii\helpers\ArrayHelper; * Note: if you want to use the sorting feature, you must configure the [[sort]] property * so that the provider knows which columns can be sorted. * - * @property array $keys The list of key values corresponding to [[models]]. Each data model in [[models]] is - * uniquely identified by the corresponding key value in this array. - * @property array $models The list of data models in the current page. - * @property integer $totalCount Total number of possible data models. - * * @author Qiang Xue * @since 2.0 */ -class ArrayDataProvider extends DataProvider +class ArrayDataProvider extends BaseDataProvider { /** * @var string|callable the column that is used as the key of the data models. @@ -71,100 +66,53 @@ class ArrayDataProvider extends DataProvider */ public $allModels; - private $_totalCount; /** - * Returns the total number of data models. - * @return integer total number of possible data models. + * @inheritdoc */ - public function getTotalCount() + protected function prepareModels() { - if ($this->getPagination() === false) { - return $this->getCount(); - } elseif ($this->_totalCount === null) { - $this->_totalCount = count($this->allModels); + if (($models = $this->allModels) === null) { + return array(); } - return $this->_totalCount; - } - - /** - * Sets the total number of data models. - * @param integer $value the total number of data models. - */ - public function setTotalCount($value) - { - $this->_totalCount = $value; - } - - private $_models; - /** - * Returns the data models in the current page. - * @return array the list of data models in the current page. - */ - public function getModels() - { - if ($this->_models === null) { - if (($models = $this->allModels) === null) { - return array(); - } - - if (($sort = $this->getSort()) !== false) { - $models = $this->sortModels($models, $sort); - } - - if (($pagination = $this->getPagination()) !== false) { - $models = array_slice($models, $pagination->getOffset(), $pagination->getLimit()); - } + if (($sort = $this->getSort()) !== false) { + $models = $this->sortModels($models, $sort); + } - $this->_models = $models; + if (($pagination = $this->getPagination()) !== false) { + $models = array_slice($models, $pagination->getOffset(), $pagination->getLimit()); } - return $this->_models; - } - /** - * Sets the data models in the current page. - * @param array $models the models in the current page - */ - public function setModels($models) - { - $this->_models = $models; + return $models; } - private $_keys; - /** - * Returns the key values associated with the data models. - * @return array the list of key values corresponding to [[models]]. Each data model in [[models]] - * is uniquely identified by the corresponding key value in this array. + * @inheritdoc */ - public function getKeys() + protected function prepareKeys($models) { - if ($this->_keys === null) { - $this->_keys = array(); - $models = $this->getModels(); - if ($this->key !== null) { - foreach ($models as $model) { - if (is_string($this->key)) { - $this->_keys[] = $model[$this->key]; - } else { - $this->_keys[] = call_user_func($this->key, $model); - } + if ($this->key !== null) { + $keys = array(); + foreach ($models as $model) { + if (is_string($this->key)) { + $keys[] = $model[$this->key]; + } else { + $keys[] = call_user_func($this->key, $model); } - } else { - $this->_keys = array_keys($models); } + return $keys; + } else { + return array_keys($models); } - return $this->_keys; } /** - * Sets the key values associated with the data models. - * @param array $keys the list of key values corresponding to [[models]]. + * @inheritdoc */ - public function setKeys($keys) + protected function prepareTotalCount() { - $this->_keys = $keys; + return count($this->allModels); } /** diff --git a/framework/yii/data/BaseDataProvider.php b/framework/yii/data/BaseDataProvider.php new file mode 100644 index 0000000..15705b7 --- /dev/null +++ b/framework/yii/data/BaseDataProvider.php @@ -0,0 +1,253 @@ + + * @since 2.0 + */ +abstract class BaseDataProvider extends Component implements DataProviderInterface +{ + /** + * @var string an ID that uniquely identifies the data provider among all data providers. + * You should set this property if the same page contains two or more different data providers. + * Otherwise, the [[pagination]] and [[sort]] mainly not work properly. + */ + public $id; + + private $_sort; + private $_pagination; + private $_keys; + private $_models; + private $_totalCount; + + + /** + * Prepares the data models that will be made available in the current page. + * @return array the available data models + */ + abstract protected function prepareModels(); + + /** + * Prepares the keys associated with the currently available data models. + * @param array $models the available data models + * @return array the keys + */ + abstract protected function prepareKeys($models); + + /** + * Returns a value indicating the total number of data models in this data provider. + * @return integer total number of data models in this data provider. + */ + abstract protected function prepareTotalCount(); + + /** + * Prepares the data models and keys. + * + * This method will prepare the data models and keys that can be retrieved via + * [[getModels()]] and [[getKeys()]]. + * + * This method will be implicitly called by [[getModels()]] and [[getKeys()]] if it has not been called before. + * + * @param boolean $forcePrepare whether to force data preparation even if it has been done before. + */ + public function prepare($forcePrepare = false) + { + if ($forcePrepare || $this->_models === null) { + $this->_models = $this->prepareModels(); + } + if ($forcePrepare || $this->_keys === null) { + $this->_keys = $this->prepareKeys($this->_models); + } + } + + /** + * Returns the data models in the current page. + * @return array the list of data models in the current page. + */ + public function getModels() + { + $this->prepare(); + return $this->_models; + } + + /** + * Sets the data models in the current page. + * @param array $models the models in the current page + */ + public function setModels($models) + { + $this->_models = $models; + } + + /** + * Returns the key values associated with the data models. + * @return array the list of key values corresponding to [[models]]. Each data model in [[models]] + * is uniquely identified by the corresponding key value in this array. + */ + public function getKeys() + { + $this->prepare(); + return $this->_keys; + } + + /** + * Sets the key values associated with the data models. + * @param array $keys the list of key values corresponding to [[models]]. + */ + public function setKeys($keys) + { + $this->_keys = $keys; + } + + /** + * Returns the number of data models in the current page. + * @return integer the number of data models in the current page. + */ + public function getCount() + { + return count($this->getModels()); + } + + /** + * Returns the total number of data models. + * When [[pagination]] is false, this returns the same value as [[count]]. + * Otherwise, it will call [[prepareTotalCount()]] to get the count. + * @return integer total number of possible data models. + */ + public function getTotalCount() + { + if ($this->getPagination() === false) { + return $this->getCount(); + } elseif ($this->_totalCount === null) { + $this->_totalCount = $this->prepareTotalCount(); + } + return $this->_totalCount; + } + + /** + * Sets the total number of data models. + * @param integer $value the total number of data models. + */ + public function setTotalCount($value) + { + $this->_totalCount = $value; + } + + /** + * @return Pagination|boolean the pagination object. If this is false, it means the pagination is disabled. + */ + public function getPagination() + { + if ($this->_pagination === null) { + $this->_pagination = new Pagination; + if ($this->id !== null) { + $this->_pagination->pageVar = $this->id . '-page'; + } + } + return $this->_pagination; + } + + /** + * Sets the pagination for this data provider. + * @param array|Pagination|boolean $value the pagination to be used by this data provider. + * This can be one of the following: + * + * - a configuration array for creating the pagination object. The "class" element defaults + * to 'yii\data\Pagination' + * - an instance of [[Pagination]] or its subclass + * - false, if pagination needs to be disabled. + * + * @throws InvalidParamException + */ + public function setPagination($value) + { + if (is_array($value)) { + $config = array( + 'class' => Pagination::className(), + ); + if ($this->id !== null) { + $config['pageVar'] = $this->id . '-page'; + } + $this->_pagination = Yii::createObject(array_merge($config, $value)); + } elseif ($value instanceof Pagination || $value === false) { + $this->_pagination = $value; + } else { + throw new InvalidParamException('Only Pagination instance, configuration array or false is allowed.'); + } + } + + /** + * @return Sort|boolean the sorting object. If this is false, it means the sorting is disabled. + */ + public function getSort() + { + if ($this->_sort === null) { + $this->setSort(array()); + } + return $this->_sort; + } + + /** + * Sets the sort definition for this data provider. + * @param array|Sort|boolean $value the sort definition to be used by this data provider. + * This can be one of the following: + * + * - a configuration array for creating the sort definition object. The "class" element defaults + * to 'yii\data\Sort' + * - an instance of [[Sort]] or its subclass + * - false, if sorting needs to be disabled. + * + * @throws InvalidParamException + */ + public function setSort($value) + { + if (is_array($value)) { + $config = array( + 'class' => Sort::className(), + ); + if ($this->id !== null) { + $config['sortVar'] = $this->id . '-sort'; + } + $this->_sort = Yii::createObject(array_merge($config, $value)); + } elseif ($value instanceof Sort || $value === false) { + $this->_sort = $value; + } else { + throw new InvalidParamException('Only Sort instance, configuration array or false is allowed.'); + } + } + + /** + * Refreshes the data provider. + * After calling this method, if [[getModels()]], [[getKeys()]] or [[getTotalCount()]] is called again, + * they will re-execute the query and return the latest data available. + */ + public function refresh() + { + $this->_totalCount = null; + $this->_models = null; + $this->_keys = null; + } +} diff --git a/framework/yii/data/DataProvider.php b/framework/yii/data/DataProvider.php deleted file mode 100644 index d75be6f..0000000 --- a/framework/yii/data/DataProvider.php +++ /dev/null @@ -1,133 +0,0 @@ - - * @since 2.0 - */ -abstract class DataProvider extends Component implements DataProviderInterface -{ - /** - * @var string an ID that uniquely identifies the data provider among all data providers. - * You should set this property if the same page contains two or more different data providers. - * Otherwise, the [[pagination]] and [[sort]] mainly not work properly. - */ - public $id; - - private $_sort; - private $_pagination; - - /** - * @return Pagination|boolean the pagination object. If this is false, it means the pagination is disabled. - */ - public function getPagination() - { - if ($this->_pagination === null) { - $this->_pagination = new Pagination; - if ($this->id !== null) { - $this->_pagination->pageVar = $this->id . '-page'; - } - $this->_pagination->totalCount = $this->getTotalCount(); - } - return $this->_pagination; - } - - /** - * Sets the pagination for this data provider. - * @param array|Pagination|boolean $value the pagination to be used by this data provider. - * This can be one of the following: - * - * - a configuration array for creating the pagination object. The "class" element defaults - * to 'yii\data\Pagination' - * - an instance of [[Pagination]] or its subclass - * - false, if pagination needs to be disabled. - * - * @throws InvalidParamException - */ - public function setPagination($value) - { - if (is_array($value)) { - $config = array( - 'class' => Pagination::className(), - ); - if ($this->id !== null) { - $config['pageVar'] = $this->id . '-page'; - } - $this->_pagination = Yii::createObject(array_merge($config, $value)); - } elseif ($value instanceof Pagination || $value === false) { - $this->_pagination = $value; - } else { - throw new InvalidParamException('Only Pagination instance, configuration array or false is allowed.'); - } - } - - /** - * @return Sort|boolean the sorting object. If this is false, it means the sorting is disabled. - */ - public function getSort() - { - if ($this->_sort === null) { - $this->setSort(array()); - } - return $this->_sort; - } - - /** - * Sets the sort definition for this data provider. - * @param array|Sort|boolean $value the sort definition to be used by this data provider. - * This can be one of the following: - * - * - a configuration array for creating the sort definition object. The "class" element defaults - * to 'yii\data\Sort' - * - an instance of [[Sort]] or its subclass - * - false, if sorting needs to be disabled. - * - * @throws InvalidParamException - */ - public function setSort($value) - { - if (is_array($value)) { - $config = array( - 'class' => Sort::className(), - ); - if ($this->id !== null) { - $config['sortVar'] = $this->id . '-sort'; - } - $this->_sort = Yii::createObject(array_merge($config, $value)); - } elseif ($value instanceof Sort || $value === false) { - $this->_sort = $value; - } else { - throw new InvalidParamException('Only Sort instance, configuration array or false is allowed.'); - } - } - - /** - * Returns the number of data models in the current page. - * @return integer the number of data models in the current page. - */ - public function getCount() - { - return count($this->getModels()); - } -} diff --git a/framework/yii/data/DataProviderInterface.php b/framework/yii/data/DataProviderInterface.php index f0bc39d..1dea1e6 100644 --- a/framework/yii/data/DataProviderInterface.php +++ b/framework/yii/data/DataProviderInterface.php @@ -19,6 +19,18 @@ namespace yii\data; interface DataProviderInterface { /** + * Prepares the data models and keys. + * + * This method will prepare the data models and keys that can be retrieved via + * [[getModels()]] and [[getKeys()]]. + * + * This method will be implicitly called by [[getModels()]] and [[getKeys()]] if it has not been called before. + * + * @param boolean $forcePrepare whether to force data preparation even if it has been done before. + */ + public function prepare($forcePrepare = false); + + /** * Returns the number of data models in the current page. * This is equivalent to `count($provider->getModels())`. * When [[pagination]] is false, this is the same as [[totalCount]]. diff --git a/framework/yii/widgets/BaseListView.php b/framework/yii/widgets/BaseListView.php index 7268fbc..d4647ff 100644 --- a/framework/yii/widgets/BaseListView.php +++ b/framework/yii/widgets/BaseListView.php @@ -83,6 +83,7 @@ abstract class BaseListView extends Widget if ($this->dataProvider === null) { throw new InvalidConfigException('The "dataProvider" property must be set.'); } + $this->dataProvider->prepare(); } /** diff --git a/tests/unit/framework/data/ActiveDataProviderTest.php b/tests/unit/framework/data/ActiveDataProviderTest.php index 79c0a39..276c525 100644 --- a/tests/unit/framework/data/ActiveDataProviderTest.php +++ b/tests/unit/framework/data/ActiveDataProviderTest.php @@ -94,9 +94,10 @@ class ActiveDataProviderTest extends DatabaseTestCase 'query' => $query->from('tbl_order')->orderBy('id'), )); $pagination = $provider->getPagination(); - $this->assertEquals(1, $pagination->getPageCount()); + $this->assertEquals(0, $pagination->getPageCount()); $this->assertCount(3, $provider->getModels()); - + $this->assertEquals(1, $pagination->getPageCount()); + $provider->getPagination()->pageSize = 2; $this->assertEquals(3, count($provider->getModels())); $provider->refresh();