Commit 5d0ec52a by Qiang Xue

Added support for reading page size from query parameters by `Pagination`

parent f2a3dafb
...@@ -97,7 +97,7 @@ class Mail extends Base ...@@ -97,7 +97,7 @@ class Mail extends Base
$dataProvider = new ArrayDataProvider([ $dataProvider = new ArrayDataProvider([
'allModels' => $models, 'allModels' => $models,
'pagination' => [ 'pagination' => [
'pageSize' => 5, 'pageSize' => 20,
], ],
'sort' => [ 'sort' => [
'attributes' => ['from', 'to', 'reply', 'cc', 'bcc', 'subject', 'body', 'charset'], 'attributes' => ['from', 'to', 'reply', 'cc', 'bcc', 'subject', 'body', 'charset'],
......
...@@ -146,6 +146,7 @@ Yii Framework 2 Change Log ...@@ -146,6 +146,7 @@ Yii Framework 2 Change Log
- Enh: Improved `QueryBuilder::buildLimit()` to support big numbers (qiangxue) - Enh: Improved `QueryBuilder::buildLimit()` to support big numbers (qiangxue)
- Enh: Added support for building SQLs with sub-queries (qiangxue) - Enh: Added support for building SQLs with sub-queries (qiangxue)
- Enh: Added `Pagination::getLinks()` (qiangxue) - Enh: Added `Pagination::getLinks()` (qiangxue)
- Enh: Added support for reading page size from query parameters by `Pagination` (qiangxue)
- Chg #1186: Changed `Sort` to use comma to separate multiple sort fields and use negative sign to indicate descending sort (qiangxue) - Chg #1186: Changed `Sort` to use comma to separate multiple sort fields and use negative sign to indicate descending sort (qiangxue)
- Chg #1519: `yii\web\User::loginRequired()` now returns the `Response` object instead of exiting the application (qiangxue) - Chg #1519: `yii\web\User::loginRequired()` now returns the `Response` object instead of exiting the application (qiangxue)
- Chg #1586: `QueryBuilder::buildLikeCondition()` will now escape special characters and use percentage characters by default (qiangxue) - Chg #1586: `QueryBuilder::buildLikeCondition()` will now escape special characters and use percentage characters by default (qiangxue)
......
...@@ -188,6 +188,7 @@ abstract class BaseDataProvider extends Component implements DataProviderInterfa ...@@ -188,6 +188,7 @@ abstract class BaseDataProvider extends Component implements DataProviderInterfa
$config = ['class' => Pagination::className()]; $config = ['class' => Pagination::className()];
if ($this->id !== null) { if ($this->id !== null) {
$config['pageParam'] = $this->id . '-page'; $config['pageParam'] = $this->id . '-page';
$config['pageSizeParam'] = $this->id . '-per-page';
} }
$this->_pagination = Yii::createObject(array_merge($config, $value)); $this->_pagination = Yii::createObject(array_merge($config, $value));
} elseif ($value instanceof Pagination || $value === false) { } elseif ($value instanceof Pagination || $value === false) {
......
...@@ -74,11 +74,16 @@ class Pagination extends Object ...@@ -74,11 +74,16 @@ class Pagination extends Object
const LINK_LAST = 'last'; const LINK_LAST = 'last';
/** /**
* @var string name of the parameter storing the current page index. Defaults to 'page'. * @var string name of the parameter storing the current page index.
* @see params * @see params
*/ */
public $pageParam = 'page'; public $pageParam = 'page';
/** /**
* @var string name of the parameter storing the page size.
* @see params
*/
public $pageSizeParam = 'per-page';
/**
* @var boolean whether to always have the page parameter in the URL created by [[createUrl()]]. * @var boolean whether to always have the page parameter in the URL created by [[createUrl()]].
* If false and [[page]] is 0, the page parameter will not be put in the URL. * If false and [[page]] is 0, the page parameter will not be put in the URL.
*/ */
...@@ -94,8 +99,8 @@ class Pagination extends Object ...@@ -94,8 +99,8 @@ class Pagination extends Object
* *
* In order to add hash to all links use `array_merge($_GET, ['#' => 'my-hash'])`. * In order to add hash to all links use `array_merge($_GET, ['#' => 'my-hash'])`.
* *
* The array element indexed by [[pageParam]] is considered to be the current page number. * The array element indexed by [[pageParam]] is considered to be the current page number (defaults to 0);
* If the element does not exist, the current page number is considered 0. * while the element indexed by [[pageSizeParam]] is treated as the page size (defaults to [[defaultPageSize]]).
*/ */
public $params; public $params;
/** /**
...@@ -112,14 +117,24 @@ class Pagination extends Object ...@@ -112,14 +117,24 @@ class Pagination extends Object
*/ */
public $validatePage = true; public $validatePage = true;
/** /**
* @var integer number of items on each page. Defaults to 20.
* If it is less than 1, it means the page size is infinite, and thus a single page contains all items.
*/
public $pageSize = 20;
/**
* @var integer total number of items. * @var integer total number of items.
*/ */
public $totalCount = 0; public $totalCount = 0;
/**
* @var integer the default page size. This property will be returned by [[pageSize]] when page size
* cannot be determined by [[pageSizeParam]] from [[params]].
*/
public $defaultPageSize = 20;
/**
* @var array|boolean the page size limits. The first array element stands for the minimal page size, and the second
* the maximal page size. If this is false, it means [[pageSize]] should always return the value of [[defaultPageSize]].
*/
public $pageSizeLimit = [1, 50];
/**
* @var integer number of items on each page.
* If it is less than 1, it means the page size is infinite, and thus a single page contains all items.
*/
private $_pageSize;
/** /**
...@@ -127,11 +142,12 @@ class Pagination extends Object ...@@ -127,11 +142,12 @@ class Pagination extends Object
*/ */
public function getPageCount() public function getPageCount()
{ {
if ($this->pageSize < 1) { $pageSize = $this->getPageSize();
if ($pageSize < 1) {
return $this->totalCount > 0 ? 1 : 0; return $this->totalCount > 0 ? 1 : 0;
} else { } else {
$totalCount = $this->totalCount < 0 ? 0 : (int)$this->totalCount; $totalCount = $this->totalCount < 0 ? 0 : (int)$this->totalCount;
return (int)(($totalCount + $this->pageSize - 1) / $this->pageSize); return (int)(($totalCount + $pageSize - 1) / $pageSize);
} }
} }
...@@ -145,35 +161,72 @@ class Pagination extends Object ...@@ -145,35 +161,72 @@ class Pagination extends Object
public function getPage($recalculate = false) public function getPage($recalculate = false)
{ {
if ($this->_page === null || $recalculate) { if ($this->_page === null || $recalculate) {
if (($params = $this->params) === null) { $this->setPage((int)$this->getQueryParam($this->pageParam, 1) - 1);
$request = Yii::$app->getRequest(); }
$params = $request instanceof Request ? $request->getQueryParams() : []; return $this->_page;
} }
if (isset($params[$this->pageParam]) && is_scalar($params[$this->pageParam])) {
$this->_page = (int)$params[$this->pageParam] - 1; /**
* Sets the current page number.
* @param integer $value the zero-based index of the current page.
*/
public function setPage($value)
{
if ($value === null) {
$this->_page = null;
} else {
$value = (int)$value;
if ($this->validatePage) { if ($this->validatePage) {
$pageCount = $this->getPageCount(); $pageCount = $this->getPageCount();
if ($this->_page >= $pageCount) { if ($value >= $pageCount) {
$this->_page = $pageCount - 1; $value = $pageCount - 1;
} }
if ($value < 0) {
$value = 0;
} }
if ($this->_page < 0) {
$this->_page = 0;
} }
$this->_page = $value;
}
}
/**
* Returns the number of items per page.
* By default, this method will try to determine the page size by [[pageSizeParam]] in [[params]].
* If the page size cannot be determined this way, [[defaultPageSize]] will be returned.
* @return integer the number of items per page.
* @see pageSizeLimit
*/
public function getPageSize()
{
if ($this->_pageSize === null) {
if (empty($this->pageSizeLimit)) {
$pageSize = $this->defaultPageSize;
} else { } else {
$this->_page = 0; $pageSize = (int)$this->getQueryParam($this->pageSizeParam, $this->defaultPageSize);
} }
$this->setPageSize($pageSize);
} }
return $this->_page; return $this->_pageSize;
} }
/** /**
* Sets the current page number. * @param integer $value the number of items per page.
* @param integer $value the zero-based index of the current page.
*/ */
public function setPage($value) public function setPageSize($value)
{ {
$this->_page = $value; if ($value === null) {
$this->_pageSize = null;
} else {
$value = (int)$value;
if (count($this->pageSizeLimit) === 2 && isset($this->pageSizeLimit[0], $this->pageSizeLimit[1])) {
if ($value < $this->pageSizeLimit[0]) {
$value = $this->pageSizeLimit[0];
} elseif ($value > $this->pageSizeLimit[1]) {
$value = $this->pageSizeLimit[1];
}
}
$this->_pageSize = $value;
}
} }
/** /**
...@@ -196,6 +249,12 @@ class Pagination extends Object ...@@ -196,6 +249,12 @@ class Pagination extends Object
} else { } else {
unset($params[$this->pageParam]); unset($params[$this->pageParam]);
} }
$pageSize = $this->getPageSize();
if ($pageSize != $this->defaultPageSize) {
$params[$this->pageSizeParam] = $pageSize;
} else {
unset($params[$this->pageSizeParam]);
}
$params[0] = $this->route === null ? Yii::$app->controller->getRoute() : $this->route; $params[0] = $this->route === null ? Yii::$app->controller->getRoute() : $this->route;
$urlManager = $this->urlManager === null ? Yii::$app->getUrlManager() : $this->urlManager; $urlManager = $this->urlManager === null ? Yii::$app->getUrlManager() : $this->urlManager;
if ($absolute) { if ($absolute) {
...@@ -211,7 +270,8 @@ class Pagination extends Object ...@@ -211,7 +270,8 @@ class Pagination extends Object
*/ */
public function getOffset() public function getOffset()
{ {
return $this->pageSize < 1 ? 0 : $this->getPage() * $this->pageSize; $pageSize = $this->getPageSize();
return $pageSize < 1 ? 0 : $this->getPage() * $pageSize;
} }
/** /**
...@@ -221,7 +281,8 @@ class Pagination extends Object ...@@ -221,7 +281,8 @@ class Pagination extends Object
*/ */
public function getLimit() public function getLimit()
{ {
return $this->pageSize < 1 ? -1 : $this->pageSize; $pageSize = $this->getPageSize();
return $pageSize < 1 ? -1 : $pageSize;
} }
/** /**
...@@ -247,4 +308,20 @@ class Pagination extends Object ...@@ -247,4 +308,20 @@ class Pagination extends Object
} }
return $links; return $links;
} }
/**
* Returns the value of the specified query parameter.
* This method returns the named parameter value from [[params]]. Null is returned if the value does not exist.
* @param string $name the parameter name
* @param string $defaultValue the value to be returned when the specified parameter does not exist in [[params]].
* @return string the parameter value
*/
protected function getQueryParam($name, $defaultValue = null)
{
if (($params = $this->params) === null) {
$request = Yii::$app->getRequest();
$params = $request instanceof Request ? $request->getQueryParams() : [];
}
return isset($params[$name]) && is_scalar($params[$name]) ? $params[$name] : $defaultValue;
}
} }
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