Commit 0035f237 by Qiang Xue

refactored data providers.

parent 2c30ddfc
...@@ -85,7 +85,7 @@ return array( ...@@ -85,7 +85,7 @@ return array(
'yii\captcha\CaptchaValidator' => YII_PATH . '/captcha/CaptchaValidator.php', 'yii\captcha\CaptchaValidator' => YII_PATH . '/captcha/CaptchaValidator.php',
'yii\data\ActiveDataProvider' => YII_PATH . '/data/ActiveDataProvider.php', 'yii\data\ActiveDataProvider' => YII_PATH . '/data/ActiveDataProvider.php',
'yii\data\ArrayDataProvider' => YII_PATH . '/data/ArrayDataProvider.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\DataProviderInterface' => YII_PATH . '/data/DataProviderInterface.php',
'yii\data\Pagination' => YII_PATH . '/data/Pagination.php', 'yii\data\Pagination' => YII_PATH . '/data/Pagination.php',
'yii\data\Sort' => YII_PATH . '/data/Sort.php', 'yii\data\Sort' => YII_PATH . '/data/Sort.php',
...@@ -118,6 +118,7 @@ return array( ...@@ -118,6 +118,7 @@ return array(
'yii\db\pgsql\Schema' => YII_PATH . '/db/pgsql/Schema.php', 'yii\db\pgsql\Schema' => YII_PATH . '/db/pgsql/Schema.php',
'yii\db\sqlite\QueryBuilder' => YII_PATH . '/db/sqlite/QueryBuilder.php', 'yii\db\sqlite\QueryBuilder' => YII_PATH . '/db/sqlite/QueryBuilder.php',
'yii\db\sqlite\Schema' => YII_PATH . '/db/sqlite/Schema.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\CheckboxColumn' => YII_PATH . '/grid/CheckboxColumn.php',
'yii\grid\Column' => YII_PATH . '/grid/Column.php', 'yii\grid\Column' => YII_PATH . '/grid/Column.php',
'yii\grid\DataColumn' => YII_PATH . '/grid/DataColumn.php', 'yii\grid\DataColumn' => YII_PATH . '/grid/DataColumn.php',
...@@ -126,26 +127,26 @@ return array( ...@@ -126,26 +127,26 @@ return array(
'yii\grid\SerialColumn' => YII_PATH . '/grid/SerialColumn.php', 'yii\grid\SerialColumn' => YII_PATH . '/grid/SerialColumn.php',
'yii\helpers\ArrayHelper' => YII_PATH . '/helpers/ArrayHelper.php', 'yii\helpers\ArrayHelper' => YII_PATH . '/helpers/ArrayHelper.php',
'yii\helpers\BaseArrayHelper' => YII_PATH . '/helpers/BaseArrayHelper.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\BaseConsole' => YII_PATH . '/helpers/BaseConsole.php',
'yii\helpers\FileHelper' => YII_PATH . '/helpers/FileHelper.php',
'yii\helpers\BaseFileHelper' => YII_PATH . '/helpers/BaseFileHelper.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\BaseHtml' => YII_PATH . '/helpers/BaseHtml.php',
'yii\helpers\HtmlPurifier' => YII_PATH . '/helpers/HtmlPurifier.php',
'yii\helpers\BaseHtmlPurifier' => YII_PATH . '/helpers/BaseHtmlPurifier.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\BaseInflector' => YII_PATH . '/helpers/BaseInflector.php',
'yii\helpers\Json' => YII_PATH . '/helpers/Json.php',
'yii\helpers\BaseJson' => YII_PATH . '/helpers/BaseJson.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\BaseMarkdown' => YII_PATH . '/helpers/BaseMarkdown.php',
'yii\helpers\Security' => YII_PATH . '/helpers/Security.php',
'yii\helpers\BaseSecurity' => YII_PATH . '/helpers/BaseSecurity.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\BaseStringHelper' => YII_PATH . '/helpers/BaseStringHelper.php',
'yii\helpers\VarDumper' => YII_PATH . '/helpers/VarDumper.php',
'yii\helpers\BaseVarDumper' => YII_PATH . '/helpers/BaseVarDumper.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\DbMessageSource' => YII_PATH . '/i18n/DbMessageSource.php',
'yii\i18n\Formatter' => YII_PATH . '/i18n/Formatter.php', 'yii\i18n\Formatter' => YII_PATH . '/i18n/Formatter.php',
'yii\i18n\GettextFile' => YII_PATH . '/i18n/GettextFile.php', 'yii\i18n\GettextFile' => YII_PATH . '/i18n/GettextFile.php',
...@@ -194,6 +195,7 @@ return array( ...@@ -194,6 +195,7 @@ return array(
'yii\web\Application' => YII_PATH . '/web/Application.php', 'yii\web\Application' => YII_PATH . '/web/Application.php',
'yii\web\AssetBundle' => YII_PATH . '/web/AssetBundle.php', 'yii\web\AssetBundle' => YII_PATH . '/web/AssetBundle.php',
'yii\web\AssetConverter' => YII_PATH . '/web/AssetConverter.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\AssetManager' => YII_PATH . '/web/AssetManager.php',
'yii\web\CacheSession' => YII_PATH . '/web/CacheSession.php', 'yii\web\CacheSession' => YII_PATH . '/web/CacheSession.php',
'yii\web\Controller' => YII_PATH . '/web/Controller.php', 'yii\web\Controller' => YII_PATH . '/web/Controller.php',
...@@ -204,7 +206,6 @@ return array( ...@@ -204,7 +206,6 @@ return array(
'yii\web\HeaderCollection' => YII_PATH . '/web/HeaderCollection.php', 'yii\web\HeaderCollection' => YII_PATH . '/web/HeaderCollection.php',
'yii\web\HttpCache' => YII_PATH . '/web/HttpCache.php', 'yii\web\HttpCache' => YII_PATH . '/web/HttpCache.php',
'yii\web\HttpException' => YII_PATH . '/web/HttpException.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\IdentityInterface' => YII_PATH . '/web/IdentityInterface.php',
'yii\web\JqueryAsset' => YII_PATH . '/web/JqueryAsset.php', 'yii\web\JqueryAsset' => YII_PATH . '/web/JqueryAsset.php',
'yii\web\JsExpression' => YII_PATH . '/web/JsExpression.php', 'yii\web\JsExpression' => YII_PATH . '/web/JsExpression.php',
...@@ -226,6 +227,7 @@ return array( ...@@ -226,6 +227,7 @@ return array(
'yii\widgets\ActiveField' => YII_PATH . '/widgets/ActiveField.php', 'yii\widgets\ActiveField' => YII_PATH . '/widgets/ActiveField.php',
'yii\widgets\ActiveForm' => YII_PATH . '/widgets/ActiveForm.php', 'yii\widgets\ActiveForm' => YII_PATH . '/widgets/ActiveForm.php',
'yii\widgets\ActiveFormAsset' => YII_PATH . '/widgets/ActiveFormAsset.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\Block' => YII_PATH . '/widgets/Block.php',
'yii\widgets\Breadcrumbs' => YII_PATH . '/widgets/Breadcrumbs.php', 'yii\widgets\Breadcrumbs' => YII_PATH . '/widgets/Breadcrumbs.php',
'yii\widgets\ContentDecorator' => YII_PATH . '/widgets/ContentDecorator.php', 'yii\widgets\ContentDecorator' => YII_PATH . '/widgets/ContentDecorator.php',
...@@ -235,7 +237,6 @@ return array( ...@@ -235,7 +237,6 @@ return array(
'yii\widgets\LinkPager' => YII_PATH . '/widgets/LinkPager.php', 'yii\widgets\LinkPager' => YII_PATH . '/widgets/LinkPager.php',
'yii\widgets\LinkSorter' => YII_PATH . '/widgets/LinkSorter.php', 'yii\widgets\LinkSorter' => YII_PATH . '/widgets/LinkSorter.php',
'yii\widgets\ListView' => YII_PATH . '/widgets/ListView.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\MaskedInput' => YII_PATH . '/widgets/MaskedInput.php',
'yii\widgets\MaskedInputAsset' => YII_PATH . '/widgets/MaskedInputAsset.php', 'yii\widgets\MaskedInputAsset' => YII_PATH . '/widgets/MaskedInputAsset.php',
'yii\widgets\Menu' => YII_PATH . '/widgets/Menu.php', 'yii\widgets\Menu' => YII_PATH . '/widgets/Menu.php',
......
...@@ -48,16 +48,10 @@ use yii\db\Connection; ...@@ -48,16 +48,10 @@ use yii\db\Connection;
* $posts = $provider->getModels(); * $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 <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class ActiveDataProvider extends DataProvider class ActiveDataProvider extends BaseDataProvider
{ {
/** /**
* @var Query the query that is used to fetch data models and [[totalCount]] * @var Query the query that is used to fetch data models and [[totalCount]]
...@@ -82,10 +76,6 @@ class ActiveDataProvider extends DataProvider ...@@ -82,10 +76,6 @@ class ActiveDataProvider extends DataProvider
*/ */
public $db; public $db;
private $_models;
private $_keys;
private $_totalCount;
/** /**
* Initializes the DbCache component. * Initializes the DbCache component.
* This method will initialize the [[db]] property to make sure it refers to a valid DB connection. * 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 ...@@ -103,122 +93,72 @@ class ActiveDataProvider extends DataProvider
} }
/** /**
* Returns the number of data models in the current page. * @inheritdoc
* 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
*/ */
public function getTotalCount() protected function prepareModels()
{ {
if ($this->getPagination() === false) { if (!$this->query instanceof Query) {
return $this->getCount(); throw new InvalidConfigException('The "query" property must be an instance of Query or its subclass.');
} 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);
} }
return $this->_totalCount; if (($pagination = $this->getPagination()) !== false) {
} $pagination->totalCount = $this->getTotalCount();
$this->query->limit($pagination->getLimit())->offset($pagination->getOffset());
/** }
* Sets the total number of data models. if (($sort = $this->getSort()) !== false) {
* @param integer $value the total number of data models. $this->query->addOrderBy($sort->getOrders());
*/
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);
} }
return $this->_models; return $this->query->all($this->db);
} }
/** /**
* Returns the key values associated with the data models. * @inheritdoc
* @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() protected function prepareKeys($models)
{ {
if ($this->_keys === null) { $keys = array();
$this->_keys = array(); if ($this->key !== null) {
$models = $this->getModels(); foreach ($models as $model) {
if ($this->key !== null) { 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) { foreach ($models as $model) {
if (is_string($this->key)) { $keys[] = $model[$pk];
$this->_keys[] = $model[$this->key];
} else {
$this->_keys[] = call_user_func($this->key, $model);
}
} }
} elseif ($this->query instanceof ActiveQuery) { } else {
/** @var \yii\db\ActiveRecord $class */ foreach ($models as $model) {
$class = $this->query->modelClass; $kk = array();
$pks = $class::primaryKey(); foreach ($pks as $pk) {
if (count($pks) === 1) { $kk[] = $model[$pk];
$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);
} }
$keys[] = json_encode($kk);
} }
} else {
$this->_keys = array_keys($models);
} }
return $keys;
} else {
return array_keys($models);
} }
return $this->_keys;
} }
/** /**
* Refreshes the data provider. * @inheritdoc
* 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() protected function prepareTotalCount()
{ {
$this->_models = null; if (!$this->query instanceof Query) {
$this->_totalCount = null; throw new InvalidConfigException('The "query" property must be an instance of Query or its subclass.');
$this->_keys = null; }
$query = clone $this->query;
return $query->limit(-1)->offset(-1)->count('*', $this->db);
} }
/** /**
...@@ -227,9 +167,7 @@ class ActiveDataProvider extends DataProvider ...@@ -227,9 +167,7 @@ class ActiveDataProvider extends DataProvider
public function setSort($value) public function setSort($value)
{ {
parent::setSort($value); parent::setSort($value);
if (($sort = $this->getSort()) !== false && empty($sort->attributes) && if (($sort = $this->getSort()) !== false && empty($sort->attributes) && $this->query instanceof ActiveQuery) {
$this->query instanceof ActiveQuery) {
/** @var Model $model */ /** @var Model $model */
$model = new $this->query->modelClass; $model = new $this->query->modelClass;
foreach($model->attributes() as $attribute) { foreach($model->attributes() as $attribute) {
......
...@@ -47,15 +47,10 @@ use yii\helpers\ArrayHelper; ...@@ -47,15 +47,10 @@ use yii\helpers\ArrayHelper;
* Note: if you want to use the sorting feature, you must configure the [[sort]] property * 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. * 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 <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @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. * @var string|callable the column that is used as the key of the data models.
...@@ -71,100 +66,53 @@ class ArrayDataProvider extends DataProvider ...@@ -71,100 +66,53 @@ class ArrayDataProvider extends DataProvider
*/ */
public $allModels; public $allModels;
private $_totalCount;
/** /**
* Returns the total number of data models. * @inheritdoc
* @return integer total number of possible data models.
*/ */
public function getTotalCount() protected function prepareModels()
{ {
if ($this->getPagination() === false) { if (($models = $this->allModels) === null) {
return $this->getCount(); return array();
} elseif ($this->_totalCount === null) {
$this->_totalCount = count($this->allModels);
} }
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;
/** if (($sort = $this->getSort()) !== false) {
* Returns the data models in the current page. $models = $this->sortModels($models, $sort);
* @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());
}
$this->_models = $models; if (($pagination = $this->getPagination()) !== false) {
$models = array_slice($models, $pagination->getOffset(), $pagination->getLimit());
} }
return $this->_models;
}
/** return $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;
} }
private $_keys;
/** /**
* Returns the key values associated with the data models. * @inheritdoc
* @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() protected function prepareKeys($models)
{ {
if ($this->_keys === null) { if ($this->key !== null) {
$this->_keys = array(); $keys = array();
$models = $this->getModels(); foreach ($models as $model) {
if ($this->key !== null) { if (is_string($this->key)) {
foreach ($models as $model) { $keys[] = $model[$this->key];
if (is_string($this->key)) { } else {
$this->_keys[] = $model[$this->key]; $keys[] = call_user_func($this->key, $model);
} else {
$this->_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. * @inheritdoc
* @param array $keys the list of key values corresponding to [[models]].
*/ */
public function setKeys($keys) protected function prepareTotalCount()
{ {
$this->_keys = $keys; return count($this->allModels);
} }
/** /**
......
...@@ -12,21 +12,23 @@ use yii\base\Component; ...@@ -12,21 +12,23 @@ use yii\base\Component;
use yii\base\InvalidParamException; use yii\base\InvalidParamException;
/** /**
* DataProvider is the base class of data provider classes. * BaseDataProvider provides a base class that implements the [[DataProviderInterface]].
*
* It implements the [[getPagination()]] and [[getSort()]] methods as specified by the [[DataProviderInterface]].
* *
* @property integer $count The number of data models in the current page. This property is read-only. * @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.
* @property array $models The list of data models in the current page.
* @property Pagination|boolean $pagination The pagination object. If this is false, it means the pagination * @property Pagination|boolean $pagination The pagination object. If this is false, it means the pagination
* is disabled. Note that the type of this property differs in getter and setter. See [[getPagination()]] and * is disabled. Note that the type of this property differs in getter and setter. See [[getPagination()]] and
* [[setPagination()]] for details. * [[setPagination()]] for details.
* @property Sort|boolean $sort The sorting object. If this is false, it means the sorting is disabled. Note * @property Sort|boolean $sort The sorting object. If this is false, it means the sorting is disabled. Note
* that the type of this property differs in getter and setter. See [[getSort()]] and [[setSort()]] for details. * that the type of this property differs in getter and setter. See [[getSort()]] and [[setSort()]] for details.
* @property integer $totalCount Total number of possible data models.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
abstract class DataProvider extends Component implements DataProviderInterface abstract class BaseDataProvider extends Component implements DataProviderInterface
{ {
/** /**
* @var string an ID that uniquely identifies the data provider among all data providers. * @var string an ID that uniquely identifies the data provider among all data providers.
...@@ -37,6 +39,122 @@ abstract class DataProvider extends Component implements DataProviderInterface ...@@ -37,6 +39,122 @@ abstract class DataProvider extends Component implements DataProviderInterface
private $_sort; private $_sort;
private $_pagination; 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. * @return Pagination|boolean the pagination object. If this is false, it means the pagination is disabled.
...@@ -48,7 +166,6 @@ abstract class DataProvider extends Component implements DataProviderInterface ...@@ -48,7 +166,6 @@ abstract class DataProvider extends Component implements DataProviderInterface
if ($this->id !== null) { if ($this->id !== null) {
$this->_pagination->pageVar = $this->id . '-page'; $this->_pagination->pageVar = $this->id . '-page';
} }
$this->_pagination->totalCount = $this->getTotalCount();
} }
return $this->_pagination; return $this->_pagination;
} }
...@@ -123,11 +240,14 @@ abstract class DataProvider extends Component implements DataProviderInterface ...@@ -123,11 +240,14 @@ abstract class DataProvider extends Component implements DataProviderInterface
} }
/** /**
* Returns the number of data models in the current page. * Refreshes the data provider.
* @return integer the number of data models in the current page. * 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 getCount() public function refresh()
{ {
return count($this->getModels()); $this->_totalCount = null;
$this->_models = null;
$this->_keys = null;
} }
} }
...@@ -19,6 +19,18 @@ namespace yii\data; ...@@ -19,6 +19,18 @@ namespace yii\data;
interface DataProviderInterface 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. * Returns the number of data models in the current page.
* This is equivalent to `count($provider->getModels())`. * This is equivalent to `count($provider->getModels())`.
* When [[pagination]] is false, this is the same as [[totalCount]]. * When [[pagination]] is false, this is the same as [[totalCount]].
......
...@@ -83,6 +83,7 @@ abstract class BaseListView extends Widget ...@@ -83,6 +83,7 @@ abstract class BaseListView extends Widget
if ($this->dataProvider === null) { if ($this->dataProvider === null) {
throw new InvalidConfigException('The "dataProvider" property must be set.'); throw new InvalidConfigException('The "dataProvider" property must be set.');
} }
$this->dataProvider->prepare();
} }
/** /**
......
...@@ -94,9 +94,10 @@ class ActiveDataProviderTest extends DatabaseTestCase ...@@ -94,9 +94,10 @@ class ActiveDataProviderTest extends DatabaseTestCase
'query' => $query->from('tbl_order')->orderBy('id'), 'query' => $query->from('tbl_order')->orderBy('id'),
)); ));
$pagination = $provider->getPagination(); $pagination = $provider->getPagination();
$this->assertEquals(1, $pagination->getPageCount()); $this->assertEquals(0, $pagination->getPageCount());
$this->assertCount(3, $provider->getModels()); $this->assertCount(3, $provider->getModels());
$this->assertEquals(1, $pagination->getPageCount());
$provider->getPagination()->pageSize = 2; $provider->getPagination()->pageSize = 2;
$this->assertEquals(3, count($provider->getModels())); $this->assertEquals(3, count($provider->getModels()));
$provider->refresh(); $provider->refresh();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment