Skip to content

Commit

Permalink
Add modvar and create new pager (#4194)
Browse files Browse the repository at this point in the history
* add modvar for items per page to ZAuth mappings list
refs #2915

also remove legacy pager and user doctrine pager with custom wrapper
  • Loading branch information
craigh authored Mar 31, 2020
1 parent 68d6775 commit ca49fac
Show file tree
Hide file tree
Showing 17 changed files with 520 additions and 43 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG-3.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@
- Added `Zikula\Bundle\CoreBundle\Helper\LocalDotEnvHelper` to assist in writing to the `.env.local` file.
- Added email notification to deleted pending registrations (#2915).
- Added CLI Command to edit password, email, username properties of ZAuth user mappings (a replacement for the old Zikula Recovery Console).
- Added new Doctrine Paginator wrapper `Zikula\Bundle\CoreBundle\Doctrine\Paginator` and paginator template. See docs.
- Added new AlphaFilter class `Zikula\Bundle\CoreBundle\Filter\AlphaFilter` and template. See docs.

- Vendor updates:
- antishov/doctrine-extensions-bundle updated from 1.2.2 to 1.4.2
Expand Down
36 changes: 36 additions & 0 deletions docs/LayoutDesign/Templating/Dev/AlphaFilter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
currentMenu: templating
---
# AlphaFilter

In large result sets that are alphanumerically based, it is often helpful to display a filter selector that can
quickly link to results beginning with that letter or number. Zikula provides a quick method to do so.
In order to utilize Zikula's AlphaFilter, the following steps should be followed:

### In the controller
```php
use Zikula\Bundle\CoreBundle\Filter\AlphaFilter;
// ...

return [
'templateParam' => $value,
'alpha' => new AlphaFilter('mycustomroute', $routeParameters, $currentLetter),
];
```

### In the template

```twig
{{ include(alpha.template) }}
```

### Options

By default, the filter does not display digits. In order to enable them, add a fourth argument to the constructor:

```php
new AlphaFilter('mycustomroute', $routeParameters, $currentLetter, true);
```

The template can be customized by overriding `@Core/Filter/AlphaFilter.html.twig` in all the normal ways.
You can also simply set your own custom template in the controller `$myAlphaFilter->setTemplate('@MyBundle/Custom/Template.html.twig');`
44 changes: 44 additions & 0 deletions docs/LayoutDesign/Templating/Dev/Pagination.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
currentMenu: templating
---
# Pagination

Large result sets should be paginated. Doctrine provides a method to limit its result sets to do this, but it doesn't
provide an UI for proper display. Zikula provides a 'wrapper' class in order to facilitate easier UI.
In order to utilize Zikula's paginator, the following steps should be followed:

### In the repository class

```php
use Zikula\Bundle\CoreBundle\Doctrine\Paginator;
// ...

$qb = $this->createQueryBuilder('m')
->select('m');
return (new Paginator($qb, $pageSize))->paginate($page); // returns Paginator object
```

### In the controller

```php
$latestPosts = $repository->getLatestPosts($criteria, $pageSize);
$latestPosts->setRoute('mycustomroute');
$latestPosts->setRouteParameters(['foo' => 'bar']);
return $this->render('blog/index.'.$_format.'.twig', [
'paginator' => $latestPosts,
]);
```

### In the template

```twig
{% for post in paginator.results %}
{{ post.title }}
{% endfor %}
{{ include(paginator.template) }}
```

### Customization

The template can be customized by overriding `@Core/Paginator/Paginator.html.twig` in all the normal ways.
You can also simply set your own custom template in the controller `$latestPosts->setTemplate('@MyBundle/Custom/Template.html.twig');`
2 changes: 2 additions & 0 deletions docs/LayoutDesign/Templating/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ Zikula uses the Twig template engine, like Symfony does.
## For developers

- [PageAssetApi](Dev/PageAssetApi.md)
- [Pagination of large result sets](Dev/Pagination.md)
- [Display an Alpha filter](Dev/AlphaFilter.md)
174 changes: 174 additions & 0 deletions src/Zikula/CoreBundle/Doctrine/Paginator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Zikula package.
*
* Copyright Zikula Foundation - https://ziku.la/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Zikula\Bundle\CoreBundle\Doctrine;

use Doctrine\ORM\QueryBuilder as DoctrineQueryBuilder;
use Doctrine\ORM\Tools\Pagination\CountWalker;
use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator;

/**
* @author Javier Eguiluz <[email protected]>
* Most of this file is copied from https://github.com/javiereguiluz/symfony-demo/blob/master/src/Pagination/Paginator.php
*
* usage:
* in Repository class:
* return (new Paginator($qb, $pageSize))->paginate($pageNumber);
* in controller:
* $latestPosts = $repository->getLatestPosts($criteria, $pageSize);
* return $this->render('blog/index.'.$_format.'.twig', [
* 'paginator' => $latestPosts,
* ]);
* results in template {% for post in paginator.results %}
* include template: {{ include(paginator.template) }}
*/
class Paginator
{
private const PAGE_SIZE = 25;

private $queryBuilder;

private $currentPage;

private $pageSize;

private $results;

private $numResults;

private $route;

private $routeParameters;

private $template = '@Core/Paginator/Paginator.html.twig';

public function __construct(DoctrineQueryBuilder $queryBuilder, int $pageSize = self::PAGE_SIZE)
{
$this->queryBuilder = $queryBuilder;
$this->pageSize = $pageSize;
}

public function paginate(int $page = 1): self
{
$this->currentPage = max(1, $page);
$firstResult = ($this->currentPage - 1) * $this->pageSize;

$query = $this->queryBuilder
->setFirstResult($firstResult)
->setMaxResults($this->pageSize)
->getQuery();

if (0 === \count($this->queryBuilder->getDQLPart('join'))) {
$query->setHint(CountWalker::HINT_DISTINCT, false);
}

$paginator = new DoctrinePaginator($query, true);

$useOutputWalkers = \count($this->queryBuilder->getDQLPart('having') ?: []) > 0;
$paginator->setUseOutputWalkers($useOutputWalkers);

$this->results = $paginator->getIterator();
$this->numResults = $paginator->count();

return $this;
}

public function getCurrentPage(): int
{
return $this->currentPage;
}

public function getLastPage(): int
{
return (int) ceil($this->numResults / $this->pageSize);
}

public function getPageSize(): int
{
return $this->pageSize;
}

public function hasPreviousPage(): bool
{
return $this->currentPage > 1;
}

public function getPreviousPage(): int
{
return max(1, $this->currentPage - 1);
}

public function hasNextPage(): bool
{
return $this->currentPage < $this->getLastPage();
}

public function getNextPage(): int
{
return min($this->getLastPage(), $this->currentPage + 1);
}

public function hasToPaginate(): bool
{
return $this->numResults > $this->pageSize;
}

public function getNumResults(): int
{
return $this->numResults;
}

public function getResults(): \Traversable
{
return $this->results;
}

public function setRoute(string $route): self
{
$this->route = $route;

return $this;
}

public function getRoute(): string
{
return $this->route;
}

public function setRouteParameters(array $parameters): self
{
$this->routeParameters = $parameters;

return $this;
}

public function setRouteParameter(string $name, string $value): void
{
$this->routeParameters[$name] = $value;
}

public function getRouteParameters(): array
{
return $this->routeParameters;
}

public function setTemplate(string $templateName): void
{
$this->template = $templateName;
}

public function getTemplate(): string
{
return $this->template;
}
}
99 changes: 99 additions & 0 deletions src/Zikula/CoreBundle/Filter/AlphaFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Zikula package.
*
* Copyright Zikula Foundation - https://ziku.la/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Zikula\Bundle\CoreBundle\Filter;

/**
* Assist in the display of an alphabetical selector for large result sets
* In controller:
* return [
* 'templateParam' => $value,
* 'alpha' => new AlphaFilter('mycustomroute', $routeParameters, $currentLetter),
* ];
* In template:
* {{ include(alpha.template) }}
*/
class AlphaFilter
{
private $currentLetter;

private $route;

private $routeParameters;

private $template = '@Core/Filter/AlphaFilter.html.twig';

private $includeNumbers = false;

public function __construct(string $route, array $routeParameters = [], $currentLetter = 'a', $includeNumbers = false)
{
$this->route = $route;
$this->routeParameters = $routeParameters;
$this->currentLetter = $currentLetter;
$this->includeNumbers = $includeNumbers;
}

public function getCurrentLetter(): string
{
return $this->currentLetter;
}

public function setRoute(string $route): self
{
$this->route = $route;

return $this;
}

public function getRoute(): string
{
return $this->route;
}

public function setRouteParameters(array $parameters): self
{
$this->routeParameters = $parameters;

return $this;
}

public function setRouteParameter(string $name, ?string $value): void
{
$this->routeParameters[$name] = $value;
}

public function getRouteParameters(): array
{
return $this->routeParameters;
}

public function setTemplate(string $templateName): void
{
$this->template = $templateName;
}

public function getTemplate(): string
{
return $this->template;
}

public function setIncludeNumbers(bool $include): void
{
$this->includeNumbers = $include;
}

public function getIncludeNumbers(): bool
{
return $this->includeNumbers;
}
}
Loading

0 comments on commit ca49fac

Please sign in to comment.