Skip to content

Commit

Permalink
Merge pull request sonata-project#2656 from pulzarraider/simplepager
Browse files Browse the repository at this point in the history
Added SimplePager from SonataDoctrinePhpcrAdminBundle
  • Loading branch information
rande committed Feb 8, 2015
2 parents b98ffaf + e0f6d4c commit d213100
Show file tree
Hide file tree
Showing 37 changed files with 583 additions and 7 deletions.
28 changes: 28 additions & 0 deletions Admin/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
use Knp\Menu\ItemInterface as MenuItemInterface;

use Doctrine\Common\Util\ClassUtils;
use Sonata\AdminBundle\Datagrid\Pager;

abstract class Admin implements AdminInterface, DomainObjectInterface
{
Expand Down Expand Up @@ -217,6 +218,13 @@ abstract class Admin implements AdminInterface, DomainObjectInterface
*/
protected $perPageOptions = array(16, 32, 64, 128, 192);

/**
* Pager type
*
* @var string
*/
protected $pagerType = Pager::TYPE_DEFAULT;

/**
* The code related to the admin
*
Expand Down Expand Up @@ -2746,6 +2754,26 @@ public function getPerPageOptions()
return $this->perPageOptions;
}

/**
* Set pager type
*
* @param string $pagerType
*/
public function setPagerType($pagerType)
{
$this->pagerType = $pagerType;
}

/**
* Get pager type
*
* @return string
*/
public function getPagerType()
{
return $this->pagerType;
}

/**
* Returns true if the per page value is allowed, false otherwise
*
Expand Down
2 changes: 2 additions & 0 deletions Datagrid/Pager.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/
abstract class Pager implements \Iterator, \Countable, \Serializable, PagerInterface
{
const TYPE_DEFAULT = 'default';
const TYPE_SIMPLE = 'simple';

protected $page = 1;
protected $maxPerPage = 0;
Expand Down
174 changes: 174 additions & 0 deletions Datagrid/SimplePager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php

/*
* This file is part of the Sonata package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\AdminBundle\Datagrid;

use Doctrine\ORM\QueryBuilder;
use Doctrine\Common\Collections\ArrayCollection;

/**
* Simple pager
*
* @author Lukas Kahwe Smith <[email protected]>
* @author Sjoerd Peters <[email protected]>
*/
class SimplePager extends Pager
{
/**
* @var boolean
*/
protected $haveToPaginate;

/**
* How many pages to look forward to create links to next pages.
*
* @var int
*/
protected $threshold;

/**
* @var int
*/
protected $thresholdCount;

/**
* The threshold parameter can be used to determine how far ahead the pager
* should fetch results.
*
* If set to 1 which is the minimal value the pager will generate a link to the next page
* If set to 2 the pager will generate links to the next two pages
* If set to 3 the pager will generate links to the next three pages
* etc.
*
* @param integer $maxPerPage Number of records to display per page
* @param int $threshold
*/
public function __construct($maxPerPage = 10, $threshold = 1)
{
parent::__construct($maxPerPage);
$this->setThreshold($threshold);
}

/**
* Returns the exact count when there is only one page or when the current
* equals the last page.
*
* In all other cases an estimate of the total count is returned.
*
* @return integer
*/
public function getNbResults()
{
$n = ceil(($this->getLastPage() -1) * $this->getMaxPerPage());
if ($this->getLastPage() == $this->getPage()) {
return $n + $this->thresholdCount;
}

return $n;
}

/**
* Get all the results for the pager instance
*
* @param mixed $hydrationMode A hydration mode identifier
*
* @return array
*/
public function getResults($hydrationMode = null)
{
if ($this->results) {
return $this->results;
}

$this->results = $this->getQuery()->execute(array(), $hydrationMode);
$this->thresholdCount = count($this->results);
if (count($this->results) > $this->getMaxPerPage()) {
$this->haveToPaginate = true;

if ($this->results instanceof ArrayCollection) {
$this->results = new ArrayCollection($this->results->slice(0, $this->getMaxPerPage()));
} else {
$this->results = new ArrayCollection(array_slice($this->results, 0, $this->getMaxPerPage()));
}

} else {
$this->haveToPaginate = false;
}

return $this->results;
}

/**
* {@inheritDoc}
*/
public function haveToPaginate()
{
return $this->haveToPaginate || $this->getPage() > 1;
}

/**
* {@inheritDoc}
*/
protected function resetIterator()
{
parent::resetIterator();
$this->haveToPaginate = false;
}

/**
* {@inheritDoc}
*
* @throws \RuntimeException the QueryBuilder is uninitialized.
*/
public function init()
{
if (!$this->getQuery()) {
throw new \RuntimeException('Uninitialized QueryBuilder');
}
$this->resetIterator();

if (0 == $this->getPage() || 0 == $this->getMaxPerPage()) {
$this->setLastPage(0);
$this->getQuery()->setFirstResult(0);
$this->getQuery()->setMaxResults(0);
} else {
$offset = ($this->getPage() - 1) * $this->getMaxPerPage();
$this->getQuery()->setFirstResult($offset);

$maxOffset = $this->getThreshold() > 0
? $this->getMaxPerPage() * $this->threshold + 1 : $this->getMaxPerPage() + 1;

$this->getQuery()->setMaxResults($maxOffset);
$this->initializeIterator();

$t = (int) ceil($this->thresholdCount / $this->getMaxPerPage()) + $this->getPage() - 1;
$this->setLastPage($t);
}
}

/**
* Set how many pages to look forward to create links to next pages.
*
* @param int $threshold
*/
public function setThreshold($threshold)
{
$this->threshold = (int) $threshold;
}

/**
* @return int
*/
public function getThreshold()
{
return $this->threshold;
}
}
27 changes: 25 additions & 2 deletions DependencyInjection/Compiler/AddDependencyCallsCompilerPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Sonata\AdminBundle\Admin\BaseFieldDescription;
use Sonata\AdminBundle\Datagrid\Pager;

/**
* Add all dependencies to the Admin class, this avoid to write too many lines
Expand Down Expand Up @@ -226,8 +227,18 @@ public function applyDefaults(ContainerBuilder $container, $serviceId, array $at
}
}

if (isset($service['label'])) {
$label = $service['label'];
if (isset($overwriteAdminConfiguration['pager_type'])) {
$pagerType = $overwriteAdminConfiguration['pager_type'];
} elseif (isset($attributes['pager_type'])) {
$pagerType = $attributes['pager_type'];
} else {
$pagerType = Pager::TYPE_DEFAULT;
}

$definition->addMethodCall('setPagerType', array($pagerType));

if (isset($overwriteAdminConfiguration['label'])) {
$label = $overwriteAdminConfiguration['label'];
} elseif (isset($attributes['label'])) {
$label = $attributes['label'];
} else {
Expand Down Expand Up @@ -279,6 +290,18 @@ public function fixTemplates(ContainerBuilder $container, Definition $definition
continue;
}

// set template for simple pager if it is not already overwritten
if ($method[0] === 'setPagerType'
&& $method[1][0] === Pager::TYPE_SIMPLE
&& (
!isset($definedTemplates['pager_results'])
|| $definedTemplates['pager_results'] === 'SonataAdminBundle:Pager:results.html.twig'
)
) {

$definedTemplates['pager_results'] = 'SonataAdminBundle:Pager:simple_pager_results.html.twig';
}

$methods[$pos] = $method;
$pos++;
}
Expand Down
1 change: 1 addition & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ public function getConfigTreeBuilder()
->scalarNode('menu_factory')->defaultValue(null)->end()
->scalarNode('route_builder')->defaultValue(null)->end()
->scalarNode('label_translator_strategy')->defaultValue(null)->end()
->scalarNode('pager_type')->defaultValue(null)->end()
->arrayNode('templates')
->addDefaultsIfNotSet()
->children()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
Improve performance of large datasets
=====================================

If your database table contains thousands of records, the database queries generated
by SonataAdmin may become very slow. Here are tips how to improve the performance of your admin.


Change default Pager to SimplePager
-------------------------------------

Default `Pager` is counting all rows in the table, so user can easily navigate
to any page in the Datagrid. But counting thousands or milions of records
can be slow operation. If you don't need to know the number of all records,
you can use `SimplePager` instead. It doesn't count all rows, but gives user only
information if there is next page or not.

To use SimplePager in your admin just define `pager_type` inside the service definition:

.. configuration-block::

.. code-block:: xml
<!-- Acme/DemoBundle/Resources/config/admin.xml -->
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="sonata.admin.post" class="Acme\DemoBundle\Admin\PostAdmin">
<tag name="sonata.admin" manager_type="orm" group="Content" label="Post" pager_type="simple" />
<argument />
<argument>Acme\DemoBundle\Entity\Post</argument>
<argument />
</service>
</services>
</container>
.. code-block:: yaml
# Acme/DemoBundle/Resources/config/admin.yml
services:
sonata.admin.post:
class: Acme\DemoBundle\Admin\PostAdmin
tags:
- { name: sonata.admin, manager_type: orm, group: "Content", label: "Post", pager_type: "simple" }
arguments:
- ~
- Acme\DemoBundle\Entity\Post
- ~
.. note:: The `pager_results` template is automatically changed to `SonataAdminBundle:Pager:simple_pager_results.html.twig` if it's not already overloaded.
1 change: 1 addition & 0 deletions Resources/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ Cookbook
cookbook/recipe_custom_action
cookbook/recipe_customizing_a_mosaic_list
cookbook/recipe_overwrite_admin_configuration
cookbook/recipe_improve_performance_large_datasets
4 changes: 4 additions & 0 deletions Resources/translations/SonataAdminBundle.ar.xliff
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,10 @@
<source>label_view_revision</source>
<target>عرض مراجعة</target>
</trans-unit>
<trans-unit id="list_results_count_prefix">
<source>list_results_count_prefix</source>
<target>list_results_count_prefix</target>
</trans-unit>
<trans-unit id="list_results_count">
<source>list_results_count</source>
<target>%count% النتائج</target>
Expand Down
4 changes: 4 additions & 0 deletions Resources/translations/SonataAdminBundle.bg.xliff
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,10 @@
<source>label_view_revision</source>
<target>Преглед на версията</target>
</trans-unit>
<trans-unit id="list_results_count_prefix">
<source>list_results_count_prefix</source>
<target>list_results_count_prefix</target>
</trans-unit>
<trans-unit id="list_results_count">
<source>list_results_count</source>
<target>Един резултат|%count% резултата</target>
Expand Down
4 changes: 4 additions & 0 deletions Resources/translations/SonataAdminBundle.ca.xliff
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,10 @@
<source>label_view_revision</source>
<target>Mostrar revisió</target>
</trans-unit>
<trans-unit id="list_results_count_prefix">
<source>list_results_count_prefix</source>
<target>list_results_count_prefix</target>
</trans-unit>
<trans-unit id="list_results_count">
<source>list_results_count</source>
<target>1 resultat|%count% resultats</target>
Expand Down
4 changes: 4 additions & 0 deletions Resources/translations/SonataAdminBundle.cs.xliff
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,10 @@
<source>label_view_revision</source>
<target>Zobrazit revizi</target>
</trans-unit>
<trans-unit id="list_results_count_prefix">
<source>list_results_count_prefix</source>
<target>alespoň</target>
</trans-unit>
<trans-unit id="list_results_count">
<source>list_results_count</source>
<target>1 záznam|%count% záznamy|%count% záznamů</target>
Expand Down
Loading

0 comments on commit d213100

Please sign in to comment.