Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fix #20055 causes bad result for pagination using for example gridview #20176

Merged
merged 10 commits into from
Jun 8, 2024
1 change: 0 additions & 1 deletion build/controllers/TranslationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
namespace yii\build\controllers;

use DirectoryIterator;
use Yii;
use yii\console\Controller;
use yii\helpers\Html;

Expand Down
2 changes: 1 addition & 1 deletion framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Yii Framework 2 Change Log
2.0.51 under development
------------------------

- no changes in this release.
- Bug #20175: Fix bad result for pagination when used with GridView (@lav45)


2.0.50 May 30, 2024
Expand Down
2 changes: 0 additions & 2 deletions framework/base/ErrorException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

namespace yii\base;

use Yii;

/**
* ErrorException represents a PHP error.
*
Expand Down
1 change: 0 additions & 1 deletion framework/base/Security.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace yii\base;

use Yii;
use yii\helpers\StringHelper;

/**
Expand Down
16 changes: 9 additions & 7 deletions framework/data/ActiveDataProvider.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?php

Check failure on line 1 in framework/data/ActiveDataProvider.php

View workflow job for this annotation

GitHub Actions / PHP_CodeSniffer

Header blocks must be separated by a single blank line
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
Expand Down Expand Up @@ -110,7 +110,6 @@
if (($sort = $this->getSort()) !== false) {
$query->addOrderBy($sort->getOrders());
}

return $query->all($this->db);
}

Expand All @@ -128,7 +127,6 @@
$keys[] = call_user_func($this->key, $model);
}
}

return $keys;
} elseif ($this->query instanceof ActiveQueryInterface) {
/* @var $class \yii\db\ActiveRecordInterface */
Expand All @@ -148,13 +146,13 @@
$keys[] = $kk;
}
}

return $keys;
}

return array_keys($models);
}

private $_totalCount = [];

/**
* {@inheritdoc}
*/
Expand All @@ -163,8 +161,13 @@
if (!$this->query instanceof QueryInterface) {
throw new InvalidConfigException('The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses.');
}
$query = clone $this->query;
return (int) $query->limit(-1)->offset(-1)->orderBy([])->count('*', $this->db);
$query = (clone $this->query)->limit(-1)->offset(-1)->orderBy([]);
$key = md5((string)$query);

if (!array_key_exists($key, $this->_totalCount)) {
$this->_totalCount[$key] = (int)$query->count('*', $this->db);
}
return $this->_totalCount[$key];
}

/**
Expand Down Expand Up @@ -196,7 +199,6 @@
if (is_object($this->query)) {
$this->query = clone $this->query;
}

parent::__clone();
}
}
10 changes: 6 additions & 4 deletions framework/data/BaseDataProvider.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?php

Check failure on line 1 in framework/data/BaseDataProvider.php

View workflow job for this annotation

GitHub Actions / PHP_CodeSniffer

Header blocks must be separated by a single blank line
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
Expand Down Expand Up @@ -167,10 +167,10 @@
if ($this->_pagination === false) {
return $this->getCount();
}
if ($this->_totalCount === null) {
$this->_totalCount = $this->prepareTotalCount();
if ($this->_totalCount !== null) {
return (int)$this->_totalCount;
}
return $this->_totalCount;
return $this->prepareTotalCount();
}

/**
Expand Down Expand Up @@ -219,7 +219,9 @@
$value = Yii::createObject(array_merge($config, $value));
}
if ($value instanceof Pagination) {
$value->totalCount = $this->getTotalCount();
$value->setTotalCount(function () {
return $this->getTotalCount();
});
$this->_pagination = $value;
} elseif ($value === false) {
$this->_pagination = false;
Expand Down
46 changes: 29 additions & 17 deletions framework/data/Pagination.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?php

Check failure on line 1 in framework/data/Pagination.php

View workflow job for this annotation

GitHub Actions / PHP_CodeSniffer

Header blocks must be separated by a single blank line
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
Expand All @@ -7,6 +7,7 @@

namespace yii\data;

use Closure;
use Yii;
use yii\base\BaseObject;
use yii\web\Link;
Expand Down Expand Up @@ -69,6 +70,7 @@
* @property-read int $pageCount Number of pages.
* @property int $pageSize The number of items per page. If it is less than 1, it means the page size is
* infinite, and thus a single page contains all items.
* @property int $totalCount total number of items.
*
* @author Qiang Xue <[email protected]>
* @since 2.0
Expand Down Expand Up @@ -123,10 +125,6 @@
* number validation. By doing so, [[page]] will return the value indexed by [[pageParam]] in [[params]].
*/
public $validatePage = true;
/**
* @var int total number of items.
*/
public $totalCount = 0;
/**
* @var int the default page size. This property will be returned by [[pageSize]] when page size
* cannot be determined by [[pageSizeParam]] from [[params]].
Expand All @@ -143,6 +141,10 @@
* If it is less than 1, it means the page size is infinite, and thus a single page contains all items.
*/
private $_pageSize;
/**
* @var Closure|int total number of items or closure returning it.
*/
private $_totalCount = 0;


/**
Expand All @@ -151,13 +153,11 @@
public function getPageCount()
{
$pageSize = $this->getPageSize();
$totalCount = $this->getTotalCount();
if ($pageSize < 1) {
return $this->totalCount > 0 ? 1 : 0;
return $totalCount > 0 ? 1 : 0;
}

$totalCount = $this->totalCount < 0 ? 0 : (int) $this->totalCount;

return (int) (($totalCount + $pageSize - 1) / $pageSize);
return (int) ((max($totalCount, 0) + $pageSize - 1) / $pageSize);
}

private $_page;
Expand All @@ -173,7 +173,6 @@
$page = (int) $this->getQueryParam($this->pageParam, 1) - 1;
$this->setPage($page, true);
}

return $this->_page;
}

Expand Down Expand Up @@ -221,7 +220,6 @@
$this->setPageSize($pageSize, true);
}
}

return $this->_pageSize;
}

Expand Down Expand Up @@ -264,7 +262,7 @@
$request = Yii::$app->getRequest();
$params = $request instanceof Request ? $request->getQueryParams() : [];
}
if ($page > 0 || $page == 0 && $this->forcePageParam) {
if ($page > 0 || ($page === 0 && $this->forcePageParam)) {
$params[$this->pageParam] = $page + 1;
} else {
unset($params[$this->pageParam]);
Expand All @@ -282,7 +280,6 @@
if ($absolute) {
return $urlManager->createAbsoluteUrl($params);
}

return $urlManager->createUrl($params);
}

Expand All @@ -293,7 +290,6 @@
public function getOffset()
{
$pageSize = $this->getPageSize();

return $pageSize < 1 ? 0 : $this->getPage() * $pageSize;
}

Expand All @@ -305,7 +301,6 @@
public function getLimit()
{
$pageSize = $this->getPageSize();

return $pageSize < 1 ? -1 : $pageSize;
}

Expand All @@ -331,7 +326,6 @@
$links[self::LINK_NEXT] = $this->createUrl($currentPage + 1, null, $absolute);
}
}

return $links;
}

Expand All @@ -348,7 +342,25 @@
$request = Yii::$app->getRequest();
$params = $request instanceof Request ? $request->getQueryParams() : [];
}

return isset($params[$name]) && is_scalar($params[$name]) ? $params[$name] : $defaultValue;
}

/**
* @return int total number of items.
*/
public function getTotalCount()
{
if (is_numeric($this->_totalCount)) {
return (int)$this->_totalCount;
}
return (int)call_user_func($this->_totalCount);
samdark marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @param Closure|int $count
*/
public function setTotalCount($count)
{
$this->_totalCount = $count;
}
}
3 changes: 0 additions & 3 deletions framework/data/SqlDataProvider.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?php

Check failure on line 1 in framework/data/SqlDataProvider.php

View workflow job for this annotation

GitHub Actions / PHP_CodeSniffer

Header blocks must be separated by a single blank line
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
Expand All @@ -7,7 +7,6 @@

namespace yii\data;

use Yii;
use yii\base\InvalidConfigException;
use yii\db\Connection;
use yii\db\Expression;
Expand Down Expand Up @@ -150,10 +149,8 @@
$keys[] = call_user_func($this->key, $model);
}
}

return $keys;
}

return array_keys($models);
}

Expand Down
1 change: 0 additions & 1 deletion framework/db/ColumnSchemaBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace yii\db;

use Yii;
use yii\base\BaseObject;
use yii\helpers\StringHelper;

Expand Down
1 change: 0 additions & 1 deletion framework/i18n/DbMessageSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace yii\i18n;

use Yii;
use yii\base\InvalidConfigException;
use yii\caching\CacheInterface;
use yii\db\Connection;
Expand Down
1 change: 0 additions & 1 deletion framework/log/DbTarget.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace yii\log;

use Yii;
use yii\base\InvalidConfigException;
use yii\db\Connection;
use yii\db\Exception;
Expand Down
1 change: 0 additions & 1 deletion framework/log/Logger.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace yii\log;

use Yii;
use yii\base\Component;

/**
Expand Down
1 change: 0 additions & 1 deletion framework/log/SyslogTarget.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace yii\log;

use Yii;
use yii\helpers\VarDumper;

/**
Expand Down
1 change: 0 additions & 1 deletion framework/rbac/Assignment.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace yii\rbac;

use Yii;
use yii\base\BaseObject;

/**
Expand Down
1 change: 0 additions & 1 deletion framework/rest/Action.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace yii\rest;

use Yii;
use yii\base\InvalidConfigException;
use yii\db\ActiveRecordInterface;
use yii\web\NotFoundHttpException;
Expand Down
2 changes: 0 additions & 2 deletions framework/rest/ViewAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

namespace yii\rest;

use Yii;

/**
* ViewAction implements the API endpoint for returning the detailed information about a model.
*
Expand Down
1 change: 0 additions & 1 deletion framework/web/CacheSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace yii\web;

use Yii;
use yii\caching\CacheInterface;
use yii\di\Instance;

Expand Down
1 change: 0 additions & 1 deletion framework/web/HeaderCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace yii\web;

use Yii;
use yii\base\BaseObject;

/**
Expand Down
19 changes: 19 additions & 0 deletions tests/framework/data/ActiveDataProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,23 @@ public function testDoesNotPerformQueryWhenHasNoModels()

$this->assertEquals(0, $pagination->getPageCount());
}

public function testTotalCountAfterSearch()
{
$query = Order::find();
$provider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'pageSize' => 2,
],
]);

$pagination = $provider->getPagination();
$this->assertEquals(2, $pagination->getPageCount());
$this->assertEquals(3, $pagination->getTotalCount());

$query->andWhere(['customer_id' => 2]);
$this->assertEquals(1, $pagination->getPageCount());
$this->assertEquals(2, $pagination->getTotalCount());
}
}
Loading