Skip to content

Commit

Permalink
Added totalCount config to Phalcon\Paginator\Adapter\QueryBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
Izopi4a committed Jul 27, 2016
1 parent ca93fcf commit 1105f61
Show file tree
Hide file tree
Showing 3 changed files with 325 additions and 36 deletions.
86 changes: 50 additions & 36 deletions phalcon/paginator/adapter/querybuilder.zep
Original file line number Diff line number Diff line change
Expand Up @@ -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. |
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
35 changes: 35 additions & 0 deletions tests/_proxies/Paginator/Adapter/QueryBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Phalcon\Test\Proxy\Paginator\Adapter;

use Phalcon\Paginator\Adapter\QueryBuilder as PhQueryBuilder;

/**
* \Phalcon\Test\Proxy\Paginator\Adapter\QueryBuilder
* Beanstalk proxy class for \Phalcon\Paginator\Adapter\QueryBuilder
*
* @copyright (c) 2011-2016 Phalcon Team
* @link http://www.phalconphp.com
* @author Andres Gutierrez <andres@phalconphp.com>
* @author Serghei Iakovlev <serghei@phalconphp.com>
* @package Phalcon\Test\Proxy\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 QueryBuilder extends PhQueryBuilder
{
public function __construct($config)
{
parent::__construct($config);
}

public function getPaginate()
{
return parent::getPaginate();
}
}
240 changes: 240 additions & 0 deletions tests/unit/Paginator/Adapter/QueryBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
<?php

namespace Phalcon\Test\Unit\Paginator\Adapter;

use Phalcon\Test\Module\UnitTest;
use Phalcon\Test\Proxy\Paginator\Adapter\QueryBuilder;
use Phalcon\Mvc\Model\Metadata\Memory;

/**
* \Phalcon\Test\Unit\Paginator\Adapter\QueryBuilderTest
* Tests the \Phalcon\Paginator\Adapter\QueryBuilder component
*
* @copyright (c) 2011-2016 Phalcon Team
* @link http://www.phalconphp.com
* @author Andres Gutierrez <andres@phalconphp.com>
* @author Serghei Iakovlev <serghei@phalconphp.com>
* @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);
}
);
}
}

0 comments on commit 1105f61

Please sign in to comment.