diff --git a/phalcon/paginator/adapter/querybuilder.zep b/phalcon/paginator/adapter/querybuilder.zep index 7ea4ce41847..ac9bf23a88d 100644 --- a/phalcon/paginator/adapter/querybuilder.zep +++ b/phalcon/paginator/adapter/querybuilder.zep @@ -3,7 +3,7 @@ +------------------------------------------------------------------------+ | Phalcon Framework | +------------------------------------------------------------------------+ - | Copyright (c) 2011-2016 Phalcon Team (https://phalconphp.com) | + | Copyright (c) 2011-2016 Phalcon Team (https://phalconphp.com) | +------------------------------------------------------------------------+ | This source file is subject to the New BSD License that is bundled | | with this package in the file docs/LICENSE.txt. | @@ -122,9 +122,12 @@ class QueryBuilder extends Adapter implements AdapterInterface let builder = clone originalBuilder; /** - * We make a copy of the original builder to count the total of records - */ - let totalBuilder = clone builder; + * We make a copy of the original builder to count the total of records + */ + if false === isset(this->_config["totalCount"]) { + + let totalBuilder = clone builder; + } let limit = this->_limitRows; let numberPage = (int) this->_page; @@ -158,41 +161,52 @@ class QueryBuilder extends Adapter implements AdapterInterface let items = query->execute(); /** - * Change the queried columns by a COUNT(*) - */ - totalBuilder->columns("COUNT(*) [rowcount]"); + * check if row count is defined in the config + */ - /** - * Change 'COUNT()' parameters, when the query contains 'GROUP BY' - */ - var groups = totalBuilder->getGroupBy(); - if !empty groups { - var groupColumn; - if typeof groups == "array" { - let groupColumn = implode(", ", groups); - } else { - let groupColumn = groups; - } - totalBuilder->groupBy(null)->columns(["COUNT(DISTINCT ".groupColumn.") AS rowcount"]); - } + if fetch rowcount, this->_config["totalCount"] { - /** - * Remove the 'ORDER BY' clause, PostgreSQL requires this - */ - totalBuilder->orderBy(null); - - /** - * Obtain the PHQL for the total query - */ - let totalQuery = totalBuilder->getQuery(); + let rowcount = intval(rowcount); + } else { - /** - * Obtain the result of the total query - */ - let result = totalQuery->execute(), - row = result->getFirst(), - rowcount = row ? intval(row->rowcount) : 0, - totalPages = intval(ceil(rowcount / limit)); + /** + * Change the queried columns by a COUNT(*) + */ + totalBuilder->columns("COUNT(*) [rowcount]"); + + /** + * Change 'COUNT()' parameters, when the query contains 'GROUP BY' + */ + var groups = totalBuilder->getGroupBy(); + if !empty groups { + var groupColumn; + if typeof groups == "array" { + let groupColumn = implode(", ", groups); + } else { + let groupColumn = groups; + } + totalBuilder->groupBy(null)->columns(["COUNT(DISTINCT ".groupColumn.") AS rowcount"]); + } + + /** + * Remove the 'ORDER BY' clause, PostgreSQL requires this + */ + totalBuilder->orderBy(null); + + /** + * Obtain the PHQL for the total query + */ + let totalQuery = totalBuilder->getQuery(); + + /** + * Obtain the row count from total query + */ + let result = totalQuery->execute(), + row = result->getFirst(), + rowcount = row ? intval(row->rowcount) : 0; + } + + let totalPages = intval(ceil(rowcount / limit)); if numberPage < totalPages { let next = numberPage + 1; diff --git a/tests/unit/Paginator/Adapter/QueryBuilderTest.php b/tests/unit/Paginator/Adapter/QueryBuilderTest.php new file mode 100644 index 00000000000..e4b81a9661c --- /dev/null +++ b/tests/unit/Paginator/Adapter/QueryBuilderTest.php @@ -0,0 +1,240 @@ + + * @author Serghei Iakovlev + * @package Phalcon\Test\Unit\Paginator\Adapter + * + * The contents of this file are subject to the New BSD License that is + * bundled with this package in the file docs/LICENSE.txt + * + * If you did not receive a copy of the license and are unable to obtain it + * through the world-wide-web, please send an email to license@phalconphp.com + * so that we can send you a copy immediately. + */ +class QueryBuilderTest extends UnitTest +{ + + /** + * @var Manager + */ + private $modelsManager; + + /** + * @var Manager + */ + private $builder; + + /** + * Executed before each test + * + * @param IntegrationTester $I + */ + public function _before() + { + parent::_before(); + /** @var \Phalcon\Mvc\Application $app */ + $app = $this->tester->getApplication(); + $this->modelsManager = $app->getDI()->getShared('modelsManager'); + + $this->builder = $this->modelsManager->createBuilder() + ->columns('sel_id, sel_name') + ->from('Phalcon\Test\Models\Select') + ->orderBy('sel_name'); + } + + /** + * Tests QueryBuilder constructor + * + * @since 2016-27-07 + */ + public function testShouldCreatePaginator() + { + $this->specify( + "Paginator QueryBuilder does not create expected object for page 1", + function () { + $paginator = new QueryBuilder( + [ + "builder" => $this->builder, + "limit" => 2, + "page" => 1 + ] + ); + + $page = $paginator->getPaginate(); + + expect($page)->isInstanceOf('stdClass'); + expect($page->items)->count(2); + + expect($page->before)->equals(1); + expect($page->next)->equals(2); + expect($page->last)->equals(4); + expect($page->limit)->equals(2); + + expect($page->current)->equals(1); + expect($page->total_pages)->equals(4); + } + ); + + $this->specify( + "Paginator QueryBuilder does not create expected object for page 2", + function () { + $paginator = new QueryBuilder( + [ + "builder" => $this->builder, + "limit" => 2, + "page" => 2 + ] + ); + + $page = $paginator->getPaginate(); + + expect($page)->isInstanceOf('stdClass'); + expect($page->items)->count(2); + + expect($page->before)->equals(1); + expect($page->next)->equals(3); + expect($page->last)->equals(4); + expect($page->limit)->equals(2); + + expect($page->current)->equals(2); + expect($page->total_pages)->equals(4); + } + ); + + $this->specify( + "Paginator QueryBuilder does not create expected object for page 3", + function () { + $paginator = new QueryBuilder( + [ + "builder" => $this->builder, + "limit" => 2, + "page" => 3 + ] + ); + + $page = $paginator->getPaginate(); + + expect($page)->isInstanceOf('stdClass'); + expect($page->items)->count(2); + + expect($page->before)->equals(2); + expect($page->next)->equals(4); + expect($page->last)->equals(4); + expect($page->limit)->equals(2); + + expect($page->current)->equals(3); + expect($page->total_pages)->equals(4); + } + ); + } + + /** + * Tests QueryBuilder::setCurrentPage + * + * @since 2016-27-07 + */ + public function testShouldSetCurrentPage() + { + $this->specify( + "Paginator QueryBuilder::setCurrentPage does not work correctly", + function () { + $paginator = new QueryBuilder( + [ + "builder" => $this->builder, + "limit" => 2, + "page" => 3 + ] + ); + + $paginator->setCurrentPage(2); + + $page = $paginator->getPaginate(); + + expect($page)->isInstanceOf('stdClass'); + expect($page->items)->count(2); + + expect($page->before)->equals(1); + expect($page->next)->equals(3); + expect($page->last)->equals(4); + expect($page->limit)->equals(2); + + expect($page->current)->equals(2); + expect($page->total_pages)->equals(4); + } + ); + } + + /** + * Tests QueryBuilder totalCount config + * + * @since 2016-27-07 + */ + public function testTotalCountConfig() + { + $this->specify( + "Paginator QueryBuilder totalCount config does not work correctly page 1", + function () { + $paginator = new QueryBuilder( + [ + "builder" => $this->builder, + "limit" => 4, + "page" => 1, + "totalCount" => 100 + ] + ); + + $page = $paginator->getPaginate(); + + expect($page)->isInstanceOf('stdClass'); + expect($page->items)->count(4); + + expect($page->before)->equals(1); + expect($page->next)->equals(2); + expect($page->last)->equals(25); + expect($page->limit)->equals(4); + + expect($page->current)->equals(1); + expect($page->total_pages)->equals(25); + } + ); + + $this->specify( + "Paginator QueryBuilder totalCount config does not work correctly page 2", + function () { + $paginator = new QueryBuilder( + [ + "builder" => $this->builder, + "limit" => 4, + "page" => 2, + "totalCount" => 100 + ] + ); + + $page = $paginator->getPaginate(); + + expect($page)->isInstanceOf('stdClass'); + expect($page->items)->count(4); + + expect($page->before)->equals(1); + expect($page->next)->equals(3); + expect($page->last)->equals(25); + expect($page->limit)->equals(4); + + expect($page->current)->equals(2); + expect($page->total_pages)->equals(25); + } + ); + } +}