conteneurisation de l'appli
This commit is contained in:
21
vendor/knplabs/knp-components/LICENSE
vendored
Normal file
21
vendor/knplabs/knp-components/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
Copyright (c) 2011 KnpLabs
|
||||
|
||||
The MIT license, reference http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
73
vendor/knplabs/knp-components/composer.json
vendored
Normal file
73
vendor/knplabs/knp-components/composer.json
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
{
|
||||
"name": "knplabs/knp-components",
|
||||
"type": "library",
|
||||
"description": "Knplabs component library",
|
||||
"keywords": [
|
||||
"components",
|
||||
"paginator",
|
||||
"pager",
|
||||
"knp",
|
||||
"knplabs"
|
||||
],
|
||||
"homepage": "http://github.com/KnpLabs/knp-components",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "KnpLabs Team",
|
||||
"homepage": "https://knplabs.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://github.com/KnpLabs/knp-components/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"symfony/event-dispatcher-contracts": "^2.0 || ^3.0",
|
||||
"symfony/http-foundation": "^4.4 || ^5.4 || ^6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-pdo_sqlite": "*",
|
||||
"doctrine/mongodb-odm": "^2.0",
|
||||
"doctrine/orm": "^2.7",
|
||||
"doctrine/phpcr-odm": "^1.2",
|
||||
"jackalope/jackalope-doctrine-dbal": "^1.2",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"propel/propel1": "^1.7",
|
||||
"ruflin/elastica": "^7.0",
|
||||
"solarium/solarium": "^6.0",
|
||||
"symfony/http-kernel": "^4.4 || ^5.4 || ^6.0",
|
||||
"symfony/property-access": "^4.4 || ^5.4 || ^6.0"
|
||||
},
|
||||
"suggest": {
|
||||
"doctrine/common": "to allow usage pagination with Doctrine ArrayCollection",
|
||||
"doctrine/mongodb-odm": "to allow usage pagination with Doctrine ODM MongoDB",
|
||||
"doctrine/orm": "to allow usage pagination with Doctrine ORM",
|
||||
"doctrine/phpcr-odm": "to allow usage pagination with Doctrine ODM PHPCR",
|
||||
"propel/propel1": "to allow usage pagination with Propel ORM",
|
||||
"ruflin/elastica": "to allow usage pagination with ElasticSearch Client",
|
||||
"solarium/solarium": "to allow usage pagination with Solarium Client",
|
||||
"symfony/property-access": "To allow sorting arrays"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/dbal": "<2.10"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Knp\\Component\\": "src/Knp/Component"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Test\\": "tests/Test"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "phpunit"
|
||||
}
|
||||
}
|
12
vendor/knplabs/knp-components/phpstan-baseline.neon
vendored
Normal file
12
vendor/knplabs/knp-components/phpstan-baseline.neon
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$stringPattern of class Doctrine\\\\ORM\\\\Query\\\\AST\\\\LikeExpression constructor expects Doctrine\\\\ORM\\\\Query\\\\AST\\\\InputParameter, Doctrine\\\\ORM\\\\Query\\\\AST\\\\Literal given\\.$#"
|
||||
count: 1
|
||||
path: src/Knp/Component/Pager/Event/Subscriber/Filtration/Doctrine/ORM/Query/WhereWalker.php
|
||||
|
||||
-
|
||||
message: "#^Instanceof between Doctrine\\\\ORM\\\\Query\\\\AST\\\\ConditionalExpression and Doctrine\\\\ORM\\\\Query\\\\AST\\\\ConditionalPrimary will always evaluate to false\\.$#"
|
||||
count: 1
|
||||
path: src/Knp/Component/Pager/Event/Subscriber/Filtration/Doctrine/ORM/Query/WhereWalker.php
|
||||
|
24
vendor/knplabs/knp-components/src/Knp/Component/Pager/Event/AfterEvent.php
vendored
Normal file
24
vendor/knplabs/knp-components/src/Knp/Component/Pager/Event/AfterEvent.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event;
|
||||
|
||||
use Knp\Component\Pager\Pagination\PaginationInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Specific Event class for paginator
|
||||
*/
|
||||
final class AfterEvent extends Event
|
||||
{
|
||||
private PaginationInterface $pagination;
|
||||
|
||||
public function __construct(PaginationInterface $paginationView)
|
||||
{
|
||||
$this->pagination = $paginationView;
|
||||
}
|
||||
|
||||
public function getPaginationView(): PaginationInterface
|
||||
{
|
||||
return $this->pagination;
|
||||
}
|
||||
}
|
33
vendor/knplabs/knp-components/src/Knp/Component/Pager/Event/BeforeEvent.php
vendored
Normal file
33
vendor/knplabs/knp-components/src/Knp/Component/Pager/Event/BeforeEvent.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* Specific Event class for paginator
|
||||
*/
|
||||
final class BeforeEvent extends Event
|
||||
{
|
||||
private EventDispatcherInterface $eventDispatcher;
|
||||
|
||||
private ?Request $request;
|
||||
|
||||
public function __construct(EventDispatcherInterface $eventDispatcher, ?Request $request)
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function getEventDispatcher(): EventDispatcherInterface
|
||||
{
|
||||
return $this->eventDispatcher;
|
||||
}
|
||||
|
||||
public function getRequest(): Request
|
||||
{
|
||||
return $this->request ?? Request::createFromGlobals();
|
||||
}
|
||||
}
|
72
vendor/knplabs/knp-components/src/Knp/Component/Pager/Event/ItemsEvent.php
vendored
Normal file
72
vendor/knplabs/knp-components/src/Knp/Component/Pager/Event/ItemsEvent.php
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event;
|
||||
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Specific Event class for paginator
|
||||
*/
|
||||
final class ItemsEvent extends Event
|
||||
{
|
||||
/**
|
||||
* A target being paginated
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
public $target;
|
||||
|
||||
/**
|
||||
* List of options
|
||||
*/
|
||||
public array $options;
|
||||
|
||||
/**
|
||||
* Items result
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
public $items;
|
||||
|
||||
/**
|
||||
* Count result
|
||||
*/
|
||||
public int $count;
|
||||
|
||||
private int $offset;
|
||||
private int $limit;
|
||||
private array $customPaginationParams = [];
|
||||
|
||||
public function __construct(int $offset, int $limit)
|
||||
{
|
||||
$this->offset = $offset;
|
||||
$this->limit = $limit;
|
||||
}
|
||||
|
||||
public function setCustomPaginationParameter($name, $value): void
|
||||
{
|
||||
$this->customPaginationParams[$name] = $value;
|
||||
}
|
||||
|
||||
public function getCustomPaginationParameters(): array
|
||||
{
|
||||
return $this->customPaginationParams;
|
||||
}
|
||||
|
||||
public function unsetCustomPaginationParameter($name): void
|
||||
{
|
||||
if (isset($this->customPaginationParams[$name])) {
|
||||
unset($this->customPaginationParams[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
public function getLimit(): int
|
||||
{
|
||||
return $this->limit;
|
||||
}
|
||||
|
||||
public function getOffset(): int
|
||||
{
|
||||
return $this->offset;
|
||||
}
|
||||
}
|
36
vendor/knplabs/knp-components/src/Knp/Component/Pager/Event/PaginationEvent.php
vendored
Normal file
36
vendor/knplabs/knp-components/src/Knp/Component/Pager/Event/PaginationEvent.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event;
|
||||
|
||||
use Knp\Component\Pager\Pagination\PaginationInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Specific Event class for paginator
|
||||
*/
|
||||
final class PaginationEvent extends Event
|
||||
{
|
||||
/**
|
||||
* A target being paginated
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
public $target;
|
||||
|
||||
/**
|
||||
* List of options
|
||||
*/
|
||||
public array $options;
|
||||
|
||||
private PaginationInterface $pagination;
|
||||
|
||||
public function setPagination(PaginationInterface $pagination): void
|
||||
{
|
||||
$this->pagination = $pagination;
|
||||
}
|
||||
|
||||
public function getPagination(): PaginationInterface
|
||||
{
|
||||
return $this->pagination;
|
||||
}
|
||||
}
|
@ -0,0 +1,261 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Filtration\Doctrine\ORM\Query;
|
||||
|
||||
use Doctrine\DBAL\Types\Types as Type;
|
||||
use Doctrine\ORM\Query\AST\Functions\LowerFunction;
|
||||
use Doctrine\ORM\Query\AST\ComparisonExpression;
|
||||
use Doctrine\ORM\Query\AST\ConditionalExpression;
|
||||
use Doctrine\ORM\Query\AST\ConditionalFactor;
|
||||
use Doctrine\ORM\Query\AST\ConditionalPrimary;
|
||||
use Doctrine\ORM\Query\AST\ConditionalTerm;
|
||||
use Doctrine\ORM\Query\AST\LikeExpression;
|
||||
use Doctrine\ORM\Query\AST\Literal;
|
||||
use Doctrine\ORM\Query\AST\Node;
|
||||
use Doctrine\ORM\Query\AST\PathExpression;
|
||||
use Doctrine\ORM\Query\AST\SelectStatement;
|
||||
use Doctrine\ORM\Query\AST\WhereClause;
|
||||
use Doctrine\ORM\Query\TreeWalkerAdapter;
|
||||
|
||||
/**
|
||||
* Where Query TreeWalker for Filtration functionality
|
||||
* in doctrine paginator
|
||||
*/
|
||||
class WhereWalker extends TreeWalkerAdapter
|
||||
{
|
||||
/**
|
||||
* Filter key columns hint name
|
||||
*/
|
||||
public const HINT_PAGINATOR_FILTER_COLUMNS = 'knp_paginator.filter.columns';
|
||||
|
||||
/**
|
||||
* Filter value hint name
|
||||
*/
|
||||
public const HINT_PAGINATOR_FILTER_VALUE = 'knp_paginator.filter.value';
|
||||
|
||||
/**
|
||||
* Filter strings in a case insensitive way
|
||||
*/
|
||||
const HINT_PAGINATOR_FILTER_CASE_INSENSITIVE = 'knp_paginator.filter.case_insensitive';
|
||||
|
||||
/**
|
||||
* Walks down a SelectStatement AST node, modifying it to
|
||||
* filter the query like requested by url
|
||||
*
|
||||
* @param SelectStatement $AST
|
||||
* @return void|string
|
||||
*/
|
||||
public function walkSelectStatement(SelectStatement $AST)
|
||||
{
|
||||
$query = $this->_getQuery();
|
||||
$queriedValue = $query->getHint(self::HINT_PAGINATOR_FILTER_VALUE);
|
||||
$columns = $query->getHint(self::HINT_PAGINATOR_FILTER_COLUMNS);
|
||||
$filterCaseInsensitive = $query->getHint(self::HINT_PAGINATOR_FILTER_CASE_INSENSITIVE);
|
||||
$components = $this->_getQueryComponents();
|
||||
$filterExpressions = [];
|
||||
$expressions = [];
|
||||
foreach ($columns as $column) {
|
||||
$alias = false;
|
||||
$parts = explode('.', $column, 2);
|
||||
$field = end($parts);
|
||||
if (2 <= count($parts)) {
|
||||
$alias = trim(reset($parts));
|
||||
if (!array_key_exists($alias, $components)) {
|
||||
throw new \UnexpectedValueException("There is no component aliased by [{$alias}] in the given Query");
|
||||
}
|
||||
$meta = $components[$alias];
|
||||
if (!$meta['metadata']->hasField($field)) {
|
||||
throw new \UnexpectedValueException("There is no such field [{$field}] in the given Query component, aliased by [$alias]");
|
||||
}
|
||||
$pathExpression = new PathExpression(PathExpression::TYPE_STATE_FIELD, $alias, $field);
|
||||
$pathExpression->type = PathExpression::TYPE_STATE_FIELD;
|
||||
} else {
|
||||
if (!array_key_exists($field, $components)) {
|
||||
throw new \UnexpectedValueException("There is no component field [{$field}] in the given Query");
|
||||
}
|
||||
$pathExpression = $components[$field]['resultVariable'];
|
||||
}
|
||||
$expression = new ConditionalPrimary();
|
||||
if (isset($meta) && $meta['metadata']->getTypeOfField($field) === 'boolean') {
|
||||
if (in_array(strtolower($queriedValue), ['true', 'false'])) {
|
||||
$expression->simpleConditionalExpression = new ComparisonExpression($pathExpression, '=', new Literal(Literal::BOOLEAN, $queriedValue));
|
||||
} elseif (is_numeric($queriedValue)) {
|
||||
$expression->simpleConditionalExpression = new ComparisonExpression($pathExpression, '=', new Literal(Literal::BOOLEAN, $queriedValue == '1' ? 'true' : 'false'));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
unset($meta);
|
||||
} elseif (is_numeric($queriedValue)
|
||||
&& (
|
||||
!isset($meta)
|
||||
|| in_array(
|
||||
$meta['metadata']->getTypeOfField($field),
|
||||
[
|
||||
Type::SMALLINT,
|
||||
Type::INTEGER,
|
||||
Type::BIGINT,
|
||||
Type::FLOAT,
|
||||
Type::DECIMAL,
|
||||
]
|
||||
)
|
||||
)
|
||||
) {
|
||||
$expression->simpleConditionalExpression = new ComparisonExpression($pathExpression, '=', new Literal(Literal::NUMERIC, $queriedValue));
|
||||
} else {
|
||||
$likePathExpression = $pathExpression;
|
||||
$likeQueriedValue = $queriedValue;
|
||||
|
||||
if ($filterCaseInsensitive) {
|
||||
$lower = new LowerFunction('lower');
|
||||
$lower->stringPrimary = $pathExpression;
|
||||
$likePathExpression = $lower;
|
||||
$likeQueriedValue = strtolower($queriedValue);
|
||||
}
|
||||
|
||||
$expression->simpleConditionalExpression = new LikeExpression($likePathExpression, new Literal(Literal::STRING, $likeQueriedValue));
|
||||
}
|
||||
$filterExpressions[] = $expression->simpleConditionalExpression;
|
||||
$expressions[] = $expression;
|
||||
}
|
||||
if (count($expressions) > 1) {
|
||||
$conditionalPrimary = new ConditionalExpression($expressions);
|
||||
} elseif (count($expressions) > 0) {
|
||||
$conditionalPrimary = reset($expressions);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if ($AST->whereClause) {
|
||||
if ($AST->whereClause->conditionalExpression instanceof ConditionalTerm) {
|
||||
if (!$this->termContainsFilter($AST->whereClause->conditionalExpression, $filterExpressions)) {
|
||||
array_unshift(
|
||||
$AST->whereClause->conditionalExpression->conditionalFactors,
|
||||
$this->createPrimaryFromNode($conditionalPrimary)
|
||||
);
|
||||
}
|
||||
} elseif ($AST->whereClause->conditionalExpression instanceof ConditionalPrimary) {
|
||||
if (!$this->primaryContainsFilter($AST->whereClause->conditionalExpression, $filterExpressions)) {
|
||||
$AST->whereClause->conditionalExpression = new ConditionalTerm([
|
||||
$this->createPrimaryFromNode($conditionalPrimary),
|
||||
$AST->whereClause->conditionalExpression,
|
||||
]);
|
||||
}
|
||||
} elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression) {
|
||||
if (!$this->expressionContainsFilter($AST->whereClause->conditionalExpression, $filterExpressions)) {
|
||||
$previousPrimary = new ConditionalPrimary();
|
||||
$previousPrimary->conditionalExpression = $AST->whereClause->conditionalExpression;
|
||||
$AST->whereClause->conditionalExpression = new ConditionalTerm([
|
||||
$this->createPrimaryFromNode($conditionalPrimary),
|
||||
$previousPrimary,
|
||||
]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$AST->whereClause = new WhereClause(
|
||||
$conditionalPrimary
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionalExpression $node
|
||||
* @param Node[] $filterExpressions
|
||||
* @return bool
|
||||
*/
|
||||
private function expressionContainsFilter(ConditionalExpression $node, $filterExpressions): bool
|
||||
{
|
||||
foreach ($node->conditionalTerms as $conditionalTerm) {
|
||||
if ($conditionalTerm instanceof ConditionalTerm && $this->termContainsFilter($conditionalTerm, $filterExpressions)) {
|
||||
return true;
|
||||
} elseif ($conditionalTerm instanceof ConditionalPrimary && $this->primaryContainsFilter($conditionalTerm, $filterExpressions)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionalTerm $node
|
||||
* @param Node[] $filterExpressions
|
||||
* @return bool
|
||||
*/
|
||||
private function termContainsFilter(ConditionalTerm $node, $filterExpressions): bool
|
||||
{
|
||||
foreach ($node->conditionalFactors as $conditionalFactor) {
|
||||
if ($conditionalFactor instanceof ConditionalFactor) {
|
||||
if ($this->factorContainsFilter($conditionalFactor, $filterExpressions)) {
|
||||
return true;
|
||||
}
|
||||
} elseif ($conditionalFactor instanceof ConditionalPrimary) {
|
||||
if ($this->primaryContainsFilter($conditionalFactor, $filterExpressions)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionalFactor $node
|
||||
* @param Node[] $filterExpressions
|
||||
* @return bool
|
||||
*/
|
||||
private function factorContainsFilter(ConditionalFactor $node, $filterExpressions): bool
|
||||
{
|
||||
if ($node->conditionalPrimary instanceof ConditionalPrimary && $node->not === false) {
|
||||
return $this->primaryContainsFilter($node->conditionalPrimary, $filterExpressions);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionalPrimary $node
|
||||
* @param Node[] $filterExpressions
|
||||
* @return bool
|
||||
*/
|
||||
private function primaryContainsFilter(ConditionalPrimary $node, $filterExpressions): bool
|
||||
{
|
||||
if ($node->isSimpleConditionalExpression() && ($node->simpleConditionalExpression instanceof LikeExpression || $node->simpleConditionalExpression instanceof ComparisonExpression)) {
|
||||
return $this->isExpressionInFilterExpressions($node->simpleConditionalExpression, $filterExpressions);
|
||||
}
|
||||
if ($node->isConditionalExpression()) {
|
||||
return $this->expressionContainsFilter($node->conditionalExpression, $filterExpressions);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
* @param Node[] $filterExpressions
|
||||
* @return bool
|
||||
*/
|
||||
private function isExpressionInFilterExpressions(Node $node, $filterExpressions): bool
|
||||
{
|
||||
foreach ($filterExpressions as $filterExpression) {
|
||||
if ((string) $filterExpression === (string) $node) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConditionalPrimary|ConditionalExpression $node
|
||||
* @return ConditionalPrimary
|
||||
*/
|
||||
private function createPrimaryFromNode($node): ConditionalPrimary
|
||||
{
|
||||
if ($node instanceof ConditionalPrimary) {
|
||||
$conditionalPrimary = $node;
|
||||
} else {
|
||||
$conditionalPrimary = new ConditionalPrimary();
|
||||
$conditionalPrimary->conditionalExpression = $node;
|
||||
}
|
||||
|
||||
return $conditionalPrimary;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Filtration\Doctrine\ORM;
|
||||
|
||||
use Doctrine\ORM\Query;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Knp\Component\Pager\Event\Subscriber\Filtration\Doctrine\ORM\Query\WhereWalker;
|
||||
use Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ORM\Query\Helper as QueryHelper;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class QuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private Request $request;
|
||||
|
||||
public function __construct(?Request $request)
|
||||
{
|
||||
$this->request = $request ?? Request::createFromGlobals();
|
||||
}
|
||||
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if ($event->target instanceof Query) {
|
||||
$filterValue = $this->getQueryParameter($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME]);
|
||||
if (null === $filterValue || (empty($filterValue) && $filterValue !== '0')) {
|
||||
return;
|
||||
}
|
||||
$filterName = $this->getQueryParameter($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME]);
|
||||
if (!empty($filterName)) {
|
||||
$columns = $filterName;
|
||||
} elseif (!empty($event->options[PaginatorInterface::DEFAULT_FILTER_FIELDS])) {
|
||||
$columns = $event->options[PaginatorInterface::DEFAULT_FILTER_FIELDS];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
$value = $this->getQueryParameter($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME]);
|
||||
if (false !== strpos($value, '*')) {
|
||||
$value = str_replace('*', '%', $value);
|
||||
}
|
||||
if (is_string($columns) && false !== strpos($columns, ',')) {
|
||||
$columns = explode(',', $columns);
|
||||
}
|
||||
$columns = (array) $columns;
|
||||
if (isset($event->options[PaginatorInterface::FILTER_FIELD_ALLOW_LIST])) {
|
||||
foreach ($columns as $column) {
|
||||
if (!in_array($column, $event->options[PaginatorInterface::FILTER_FIELD_ALLOW_LIST])) {
|
||||
throw new \UnexpectedValueException("Cannot filter by: [{$column}] this field is not in allow list");
|
||||
}
|
||||
}
|
||||
}
|
||||
$event->target
|
||||
->setHint(WhereWalker::HINT_PAGINATOR_FILTER_VALUE, $value)
|
||||
->setHint(WhereWalker::HINT_PAGINATOR_FILTER_COLUMNS, $columns);
|
||||
QueryHelper::addCustomTreeWalker($event->target, WhereWalker::class);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 0],
|
||||
];
|
||||
}
|
||||
|
||||
private function getQueryParameter(string $name): ?string
|
||||
{
|
||||
return $this->request->query->get($name);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Filtration;
|
||||
|
||||
use Knp\Component\Pager\Event\BeforeEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class FiltrationSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Lazy-load state tracker
|
||||
*/
|
||||
private bool $isLoaded = false;
|
||||
|
||||
public function before(BeforeEvent $event): void
|
||||
{
|
||||
// Do not lazy-load more than once
|
||||
if ($this->isLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher */
|
||||
$dispatcher = $event->getEventDispatcher();
|
||||
// hook all standard filtration subscribers
|
||||
$dispatcher->addSubscriber(new Doctrine\ORM\QuerySubscriber($event->getRequest()));
|
||||
$dispatcher->addSubscriber(new PropelQuerySubscriber($event->getRequest()));
|
||||
|
||||
$this->isLoaded = true;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.before' => ['before', 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Filtration;
|
||||
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class PropelQuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private Request $request;
|
||||
|
||||
public function __construct(?Request $request)
|
||||
{
|
||||
$this->request = $request ?? Request::createFromGlobals();
|
||||
}
|
||||
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
$query = $event->target;
|
||||
if ($query instanceof \ModelCriteria) {
|
||||
if (!$this->request->query->has($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME])) {
|
||||
return;
|
||||
}
|
||||
if ($this->request->query->has($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME])) {
|
||||
$columns = $this->request->query->get($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME]);
|
||||
} elseif (!empty($event->options[PaginatorInterface::DEFAULT_FILTER_FIELDS])) {
|
||||
$columns = $event->options[PaginatorInterface::DEFAULT_FILTER_FIELDS];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (is_string($columns) && false !== strpos($columns, ',')) {
|
||||
$columns = explode(',', $columns);
|
||||
}
|
||||
$columns = (array) $columns;
|
||||
if (isset($event->options[PaginatorInterface::FILTER_FIELD_ALLOW_LIST])) {
|
||||
foreach ($columns as $column) {
|
||||
if (!in_array($column, $event->options[PaginatorInterface::FILTER_FIELD_ALLOW_LIST])) {
|
||||
throw new \UnexpectedValueException("Cannot filter by: [{$column}] this field is not in allow list");
|
||||
}
|
||||
}
|
||||
}
|
||||
$value = $this->request->query->get($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME]);
|
||||
$criteria = \Criteria::EQUAL;
|
||||
if (false !== strpos($value, '*')) {
|
||||
$value = str_replace('*', '%', $value);
|
||||
$criteria = \Criteria::LIKE;
|
||||
}
|
||||
foreach ($columns as $column) {
|
||||
if (false !== strpos($column, '.')) {
|
||||
$query->where($column.$criteria.'?', $value);
|
||||
} else {
|
||||
$query->{'filterBy'.$column}($value, $criteria);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 0],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate;
|
||||
|
||||
use ArrayObject;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class ArraySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if (is_array($event->target)) {
|
||||
$event->count = count($event->target);
|
||||
$event->items = array_slice(
|
||||
$event->target,
|
||||
$event->getOffset(),
|
||||
$event->getLimit()
|
||||
);
|
||||
$event->stopPropagation();
|
||||
} elseif ($event->target instanceof ArrayObject) {
|
||||
$event->count = $event->target->count();
|
||||
$event->items = new ArrayObject(array_slice(
|
||||
$event->target->getArrayCopy(),
|
||||
$event->getOffset(),
|
||||
$event->getLimit()
|
||||
));
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', -1/* other data arrays should be analized first*/],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Callback;
|
||||
|
||||
/**
|
||||
* Callback pagination.
|
||||
*
|
||||
* @author Piotr Pelczar <me@athlan.pl>
|
||||
*/
|
||||
class CallbackPagination
|
||||
{
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
private $count;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
private $items;
|
||||
|
||||
public function __construct(callable $count, callable $items)
|
||||
{
|
||||
$this->count = $count;
|
||||
$this->items = $items;
|
||||
}
|
||||
|
||||
public function getPaginationCount(): int
|
||||
{
|
||||
return call_user_func($this->count);
|
||||
}
|
||||
|
||||
public function getPaginationItems(int $offset, int $limit): array
|
||||
{
|
||||
return call_user_func($this->items, $offset, $limit);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Callback;
|
||||
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Callback pagination.
|
||||
*
|
||||
* @author Piotr Pelczar <me@athlan.pl>
|
||||
*/
|
||||
class CallbackSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if ($event->target instanceof CallbackPagination) {
|
||||
$event->count = $event->target->getPaginationCount();
|
||||
if($event->count > 0) {
|
||||
$event->items = $event->target->getPaginationItems($event->getOffset(), $event->getLimit());
|
||||
}
|
||||
else {
|
||||
$event->items = [];
|
||||
}
|
||||
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 0],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class CollectionSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if ($event->target instanceof Collection) {
|
||||
$event->count = $event->target->count();
|
||||
$event->items = $event->target->slice(
|
||||
$event->getOffset(),
|
||||
$event->getLimit()
|
||||
);
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 0],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine;
|
||||
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* DBALQueryBuilderSubscriber.php
|
||||
*
|
||||
* @author Vladimir Chub <v@chub.com.ua>
|
||||
*/
|
||||
class DBALQueryBuilderSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if ($event->target instanceof QueryBuilder) {
|
||||
$target = $event->target;
|
||||
|
||||
// count results
|
||||
$qb = clone $target;
|
||||
|
||||
//reset count orderBy since it can break query and slow it down
|
||||
$qb
|
||||
->resetQueryPart('orderBy')
|
||||
;
|
||||
|
||||
// get the query
|
||||
$sql = $qb->getSQL();
|
||||
|
||||
$qb
|
||||
->resetQueryParts()
|
||||
->select('count(*) as cnt')
|
||||
->from('(' . $sql . ')', 'dbal_count_tbl')
|
||||
;
|
||||
|
||||
$compat = $qb->execute();
|
||||
$event->count = method_exists($compat, 'fetchColumn') ? $compat->fetchColumn(0) : $compat->fetchOne();
|
||||
|
||||
// if there is results
|
||||
$event->items = [];
|
||||
if ($event->count) {
|
||||
$qb = clone $target;
|
||||
$qb
|
||||
->setFirstResult($event->getOffset())
|
||||
->setMaxResults($event->getLimit())
|
||||
;
|
||||
|
||||
$event->items = $qb
|
||||
->execute()
|
||||
->fetchAll()
|
||||
;
|
||||
}
|
||||
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 10 /*make sure to transform before any further modifications*/],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ODM\MongoDB;
|
||||
|
||||
use Doctrine\ODM\MongoDB\Query\Builder;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class QueryBuilderSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if ($event->target instanceof Builder) {
|
||||
// change target into query
|
||||
$event->target = $event->target->getQuery($event->options[PaginatorInterface::ODM_QUERY_OPTIONS] ?? []);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 10/*make sure to transform before any further modifications*/],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ODM\MongoDB;
|
||||
|
||||
use Doctrine\ODM\MongoDB\Query\Query;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class QuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if ($event->target instanceof Query) {
|
||||
// items
|
||||
$type = $event->target->getType();
|
||||
if ($type !== Query::TYPE_FIND) {
|
||||
throw new \UnexpectedValueException('ODM query must be a FIND type query');
|
||||
}
|
||||
static $reflectionProperty;
|
||||
if (is_null($reflectionProperty)) {
|
||||
$reflectionClass = new \ReflectionClass('Doctrine\ODM\MongoDB\Query\Query');
|
||||
$reflectionProperty = $reflectionClass->getProperty('query');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
}
|
||||
$queryOptions = $reflectionProperty->getValue($event->target);
|
||||
$resultCount = clone $event->target;
|
||||
$queryOptions['type'] = Query::TYPE_COUNT;
|
||||
$reflectionProperty->setValue($resultCount, $queryOptions);
|
||||
$event->count = $resultCount->execute();
|
||||
|
||||
$queryOptions = $reflectionProperty->getValue($event->target);
|
||||
$queryOptions['type'] = Query::TYPE_FIND;
|
||||
$queryOptions['limit'] = $event->getLimit();
|
||||
$queryOptions['skip'] = $event->getOffset();
|
||||
$resultQuery = clone $event->target;
|
||||
$reflectionProperty->setValue($resultQuery, $queryOptions);
|
||||
$cursor = $resultQuery->execute();
|
||||
|
||||
$event->items = [];
|
||||
// iterator_to_array for GridFS results in 1 item
|
||||
foreach ($cursor as $item) {
|
||||
$event->items[] = $item;
|
||||
}
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 0],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ODM\PHPCR;
|
||||
|
||||
use Doctrine\ODM\PHPCR\Query\Builder\QueryBuilder;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* @author Martin Hasoň <martin.hason@gmail.com>
|
||||
*/
|
||||
class QueryBuilderSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if (!$event->target instanceof QueryBuilder) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->target = $event->target->getQuery();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 10/*make sure to transform before any further modifications*/],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ODM\PHPCR;
|
||||
|
||||
use Doctrine\ODM\PHPCR\Query\Query;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* @author Martin Hasoň <martin.hason@gmail.com>
|
||||
*/
|
||||
class QuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if (!$event->target instanceof Query) {
|
||||
return;
|
||||
}
|
||||
|
||||
$queryCount = clone $event->target;
|
||||
$event->count = $queryCount->execute(null, Query::HYDRATE_PHPCR)->getRows()->count();
|
||||
|
||||
$query = $event->target;
|
||||
$query->setMaxResults($event->getLimit());
|
||||
$query->setFirstResult($event->getOffset());
|
||||
|
||||
$event->items = $query->execute();
|
||||
$event->stopPropagation();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 0],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ORM\Query;
|
||||
|
||||
use Doctrine\ORM\Query;
|
||||
|
||||
/**
|
||||
* ORM Query helper for cloning
|
||||
* and hint processing
|
||||
*/
|
||||
class Helper
|
||||
{
|
||||
/**
|
||||
* Clones the given $query and copies all used
|
||||
* parameters and hints
|
||||
*/
|
||||
public static function cloneQuery(Query $query): Query
|
||||
{
|
||||
$clonedQuery = clone $query;
|
||||
$clonedQuery->setParameters(clone $query->getParameters());
|
||||
// attach hints
|
||||
foreach ($query->getHints() as $name => $hint) {
|
||||
$clonedQuery->setHint($name, $hint);
|
||||
}
|
||||
|
||||
return $clonedQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom TreeWalker $walker class name to
|
||||
* be included in the CustomTreeWalker hint list
|
||||
* of the given $query
|
||||
*/
|
||||
public static function addCustomTreeWalker(Query $query, string $walker): void
|
||||
{
|
||||
$customTreeWalkers = $query->getHint(Query::HINT_CUSTOM_TREE_WALKERS);
|
||||
if ($customTreeWalkers !== false && is_array($customTreeWalkers)) {
|
||||
$customTreeWalkers = array_merge($customTreeWalkers, [$walker]);
|
||||
} else {
|
||||
$customTreeWalkers = [$walker];
|
||||
}
|
||||
$query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $customTreeWalkers);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ORM;
|
||||
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class QueryBuilderSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if ($event->target instanceof QueryBuilder) {
|
||||
// change target into query
|
||||
$event->target = $event->target->getQuery();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 10/*make sure to transform before any further modifications*/],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ORM;
|
||||
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\Tools\Pagination\CountWalker;
|
||||
use Doctrine\ORM\Tools\Pagination\Paginator;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class QuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public const HINT_COUNT = 'knp_paginator.count';
|
||||
public const HINT_FETCH_JOIN_COLLECTION = 'knp_paginator.fetch_join_collection';
|
||||
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if (!$event->target instanceof Query) {
|
||||
return;
|
||||
}
|
||||
$event->stopPropagation();
|
||||
|
||||
$useOutputWalkers = false;
|
||||
if (isset($event->options['wrap-queries'])) {
|
||||
$useOutputWalkers = $event->options['wrap-queries'];
|
||||
}
|
||||
|
||||
$event->target
|
||||
->setFirstResult($event->getOffset())
|
||||
->setMaxResults($event->getLimit())
|
||||
->setHint(CountWalker::HINT_DISTINCT, $event->options['distinct'])
|
||||
;
|
||||
|
||||
$fetchJoinCollection = true;
|
||||
if ($event->target->hasHint(self::HINT_FETCH_JOIN_COLLECTION)) {
|
||||
$fetchJoinCollection = $event->target->getHint(self::HINT_FETCH_JOIN_COLLECTION);
|
||||
} else if (isset($event->options['distinct'])) {
|
||||
$fetchJoinCollection = $event->options['distinct'];
|
||||
}
|
||||
|
||||
$paginator = new Paginator($event->target, $fetchJoinCollection);
|
||||
$paginator->setUseOutputWalkers($useOutputWalkers);
|
||||
if (($count = $event->target->getHint(self::HINT_COUNT)) !== false) {
|
||||
$event->count = (int) $count;
|
||||
} else {
|
||||
$event->count = count($paginator);
|
||||
}
|
||||
$event->items = iterator_to_array($paginator);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 0],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate;
|
||||
|
||||
use Elastica\Query;
|
||||
use Elastica\SearchableInterface;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Elastica query pagination.
|
||||
*
|
||||
*/
|
||||
class ElasticaQuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if (is_array($event->target) && 2 === count($event->target) && reset($event->target) instanceof SearchableInterface && end($event->target) instanceof Query) {
|
||||
[$searchable, $query] = $event->target;
|
||||
|
||||
$query->setFrom($event->getOffset());
|
||||
$query->setSize($event->getLimit());
|
||||
$results = $searchable->search($query);
|
||||
|
||||
$event->count = $results->getTotalHits();
|
||||
|
||||
if ($results->hasAggregations()) {
|
||||
$event->setCustomPaginationParameter('aggregations', $results->getAggregations());
|
||||
}
|
||||
|
||||
$event->setCustomPaginationParameter('resultSet', $results);
|
||||
$event->items = $results->getResults();
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 0], /* triggers before a standard array subscriber*/
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate;
|
||||
|
||||
use Knp\Component\Pager\Event\BeforeEvent;
|
||||
use Knp\Component\Pager\Event\PaginationEvent;
|
||||
use Knp\Component\Pager\Pagination\SlidingPagination;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class PaginationSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Lazy-load state tracker
|
||||
*/
|
||||
private bool $isLoaded = false;
|
||||
|
||||
public function pagination(PaginationEvent $event): void
|
||||
{
|
||||
$event->setPagination(new SlidingPagination);
|
||||
$event->stopPropagation();
|
||||
}
|
||||
|
||||
public function before(BeforeEvent $event): void
|
||||
{
|
||||
// Do not lazy-load more than once
|
||||
if ($this->isLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher */
|
||||
$dispatcher = $event->getEventDispatcher();
|
||||
// hook all standard subscribers
|
||||
$dispatcher->addSubscriber(new ArraySubscriber);
|
||||
$dispatcher->addSubscriber(new Callback\CallbackSubscriber);
|
||||
$dispatcher->addSubscriber(new Doctrine\ORM\QueryBuilderSubscriber);
|
||||
$dispatcher->addSubscriber(new Doctrine\ORM\QuerySubscriber);
|
||||
$dispatcher->addSubscriber(new Doctrine\ODM\MongoDB\QueryBuilderSubscriber);
|
||||
$dispatcher->addSubscriber(new Doctrine\ODM\MongoDB\QuerySubscriber);
|
||||
$dispatcher->addSubscriber(new Doctrine\ODM\PHPCR\QueryBuilderSubscriber);
|
||||
$dispatcher->addSubscriber(new Doctrine\ODM\PHPCR\QuerySubscriber);
|
||||
$dispatcher->addSubscriber(new Doctrine\CollectionSubscriber);
|
||||
$dispatcher->addSubscriber(new Doctrine\DBALQueryBuilderSubscriber);
|
||||
$dispatcher->addSubscriber(new PropelQuerySubscriber);
|
||||
$dispatcher->addSubscriber(new SolariumQuerySubscriber());
|
||||
$dispatcher->addSubscriber(new ElasticaQuerySubscriber());
|
||||
|
||||
$this->isLoaded = true;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.before' => ['before', 0],
|
||||
'knp_pager.pagination' => ['pagination', 0],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate;
|
||||
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use ModelCriteria;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class PropelQuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if ($event->target instanceof ModelCriteria) {
|
||||
// process count
|
||||
$countQuery = clone $event->target;
|
||||
$countQuery
|
||||
->limit(0)
|
||||
->offset(0)
|
||||
;
|
||||
if ($event->options[PaginatorInterface::DISTINCT]) {
|
||||
$countQuery->distinct();
|
||||
}
|
||||
$event->count = intval($countQuery->count());
|
||||
// process items
|
||||
$result = null;
|
||||
if ($event->count) {
|
||||
$resultQuery = clone $event->target;
|
||||
if ($event->options[PaginatorInterface::DISTINCT]) {
|
||||
$resultQuery->distinct();
|
||||
}
|
||||
$resultQuery
|
||||
->offset($event->getOffset())
|
||||
->limit($event->getLimit())
|
||||
;
|
||||
$result = $resultQuery->find();
|
||||
} else {
|
||||
$result = []; // count is 0
|
||||
}
|
||||
$event->items = $result;
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 0],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Paginate;
|
||||
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Solarium query pagination.
|
||||
*
|
||||
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
|
||||
*/
|
||||
class SolariumQuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if (is_array($event->target) && 2 == count($event->target)) {
|
||||
$values = array_values($event->target);
|
||||
[$client, $query] = $values;
|
||||
|
||||
if ($client instanceof \Solarium\Client && $query instanceof \Solarium\QueryType\Select\Query\Query) {
|
||||
$query->setStart($event->getOffset())->setRows($event->getLimit());
|
||||
$solrResult = $client->select($query);
|
||||
|
||||
$event->items = iterator_to_array($solrResult->getIterator());
|
||||
$event->count = $solrResult->getNumFound();
|
||||
$event->setCustomPaginationParameter('result', $solrResult);
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 0], /* triggers before a standard array subscriber*/
|
||||
];
|
||||
}
|
||||
}
|
151
vendor/knplabs/knp-components/src/Knp/Component/Pager/Event/Subscriber/Sortable/ArraySubscriber.php
vendored
Normal file
151
vendor/knplabs/knp-components/src/Knp/Component/Pager/Event/Subscriber/Sortable/ArraySubscriber.php
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Sortable;
|
||||
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
|
||||
class ArraySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @var string the field used to sort current object array list
|
||||
*/
|
||||
private string $currentSortingField;
|
||||
|
||||
/**
|
||||
* @var string the sorting direction
|
||||
*/
|
||||
private string $sortDirection;
|
||||
|
||||
private ?PropertyAccessorInterface $propertyAccessor;
|
||||
|
||||
private Request $request;
|
||||
|
||||
public function __construct(Request $request = null, PropertyAccessorInterface $accessor = null)
|
||||
{
|
||||
if (!$accessor && class_exists(PropertyAccess::class)) {
|
||||
$accessor = PropertyAccess::createPropertyAccessorBuilder()->enableMagicCall()->getPropertyAccessor();
|
||||
}
|
||||
|
||||
$this->propertyAccessor = $accessor;
|
||||
// check needed because $request must be nullable, being the second parameter (with the first one nullable)
|
||||
if (null === $request) {
|
||||
throw new \InvalidArgumentException('Request must be initialized.');
|
||||
}
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
// Check if the result has already been sorted by an other sort subscriber
|
||||
$customPaginationParameters = $event->getCustomPaginationParameters();
|
||||
if (!empty($customPaginationParameters['sorted']) ) {
|
||||
return;
|
||||
}
|
||||
$sortField = $event->options[PaginatorInterface::SORT_FIELD_PARAMETER_NAME];
|
||||
if (!is_array($event->target) || null === $sortField || !$this->request->query->has($sortField)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->setCustomPaginationParameter('sorted', true);
|
||||
|
||||
if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST]) && !in_array($this->request->query->get($sortField), $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
|
||||
throw new \UnexpectedValueException("Cannot sort by: [{$this->request->query->get($sortField)}] this field is not in allow list.");
|
||||
}
|
||||
|
||||
$sortFunction = $event->options['sortFunction'] ?? [$this, 'proxySortFunction'];
|
||||
$sortField = $this->request->query->get($sortField);
|
||||
|
||||
// compatibility layer
|
||||
if ($sortField[0] === '.') {
|
||||
$sortField = substr($sortField, 1);
|
||||
}
|
||||
|
||||
call_user_func_array($sortFunction, [
|
||||
&$event->target,
|
||||
$sortField,
|
||||
$this->getSortDirection($event->options),
|
||||
]);
|
||||
}
|
||||
|
||||
private function getSortDirection(array $options): string
|
||||
{
|
||||
if (!$this->request->query->has($options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME])) {
|
||||
return 'desc';
|
||||
}
|
||||
$direction = $this->request->query->get($options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME]);
|
||||
if (strtolower($direction) === 'asc') {
|
||||
return 'asc';
|
||||
}
|
||||
|
||||
return 'desc';
|
||||
}
|
||||
|
||||
private function proxySortFunction(&$target, $sortField, $sortDirection): bool
|
||||
{
|
||||
$this->currentSortingField = $sortField;
|
||||
$this->sortDirection = $sortDirection;
|
||||
|
||||
return usort($target, [$this, 'sortFunction']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $object1 first object to compare
|
||||
* @param mixed $object2 second object to compare
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function sortFunction($object1, $object2): int
|
||||
{
|
||||
if (null === $this->propertyAccessor) {
|
||||
throw new \UnexpectedValueException('You need symfony/property-access component to use this sorting function');
|
||||
}
|
||||
|
||||
if (!$this->propertyAccessor->isReadable($object1, $this->currentSortingField) || !$this->propertyAccessor->isReadable($object2, $this->currentSortingField)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
$fieldValue1 = $this->propertyAccessor->getValue($object1, $this->currentSortingField);
|
||||
} catch (UnexpectedTypeException $e) {
|
||||
return -1 * $this->getSortCoefficient();
|
||||
}
|
||||
|
||||
try {
|
||||
$fieldValue2 = $this->propertyAccessor->getValue($object2, $this->currentSortingField);
|
||||
} catch (UnexpectedTypeException $e) {
|
||||
return 1 * $this->getSortCoefficient();
|
||||
}
|
||||
|
||||
if (is_string($fieldValue1)) {
|
||||
$fieldValue1 = mb_strtolower($fieldValue1);
|
||||
}
|
||||
|
||||
if (is_string($fieldValue2)) {
|
||||
$fieldValue2 = mb_strtolower($fieldValue2);
|
||||
}
|
||||
|
||||
if ($fieldValue1 === $fieldValue2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ($fieldValue1 > $fieldValue2 ? 1 : -1) * $this->getSortCoefficient();
|
||||
}
|
||||
|
||||
private function getSortCoefficient(): int
|
||||
{
|
||||
return $this->sortDirection === 'asc' ? 1 : -1;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Sortable\Doctrine\ODM\MongoDB;
|
||||
|
||||
use Doctrine\ODM\MongoDB\Query\Query;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class QuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private Request $request;
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
// Check if the result has already been sorted by an other sort subscriber
|
||||
$customPaginationParameters = $event->getCustomPaginationParameters();
|
||||
if (!empty($customPaginationParameters['sorted']) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event->target instanceof Query) {
|
||||
$event->setCustomPaginationParameter('sorted', true);
|
||||
$sortField = $event->options[PaginatorInterface::SORT_FIELD_PARAMETER_NAME];
|
||||
$sortDir = $event->options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME];
|
||||
if (null !== $sortField && $this->request->query->has($sortField)) {
|
||||
$field = $this->request->query->get($sortField);
|
||||
$dir = null !== $sortDir && strtolower($this->request->query->get($sortDir)) === 'asc' ? 1 : -1;
|
||||
|
||||
if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
|
||||
if (!in_array($field, $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
|
||||
throw new \UnexpectedValueException("Cannot sort by: [{$field}] this field is not in allow list.");
|
||||
}
|
||||
}
|
||||
static $reflectionProperty;
|
||||
if (is_null($reflectionProperty)) {
|
||||
$reflectionClass = new \ReflectionClass(Query::class);
|
||||
$reflectionProperty = $reflectionClass->getProperty('query');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
}
|
||||
$queryOptions = $reflectionProperty->getValue($event->target);
|
||||
|
||||
// handle multi sort
|
||||
$sortFields = explode('+', $field);
|
||||
$sortOption = [];
|
||||
foreach ($sortFields as $sortField) {
|
||||
$sortOption[$sortField] = $dir;
|
||||
}
|
||||
|
||||
$queryOptions['sort'] = $sortOption;
|
||||
$reflectionProperty->setValue($event->target, $queryOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Sortable\Doctrine\ORM\Query;
|
||||
|
||||
use Doctrine\ORM\Query\AST\OrderByClause,
|
||||
Doctrine\ORM\Query\AST\OrderByItem,
|
||||
Doctrine\ORM\Query\AST\PathExpression,
|
||||
Doctrine\ORM\Query\AST\SelectStatement,
|
||||
Doctrine\ORM\Query\TreeWalkerAdapter;
|
||||
|
||||
/**
|
||||
* OrderBy Query TreeWalker for Sortable functionality
|
||||
* in doctrine paginator
|
||||
*/
|
||||
class OrderByWalker extends TreeWalkerAdapter
|
||||
{
|
||||
/**
|
||||
* Sort key alias hint name
|
||||
*/
|
||||
public const HINT_PAGINATOR_SORT_ALIAS = 'knp_paginator.sort.alias';
|
||||
|
||||
/**
|
||||
* Sort key field hint name
|
||||
*/
|
||||
public const HINT_PAGINATOR_SORT_FIELD = 'knp_paginator.sort.field';
|
||||
|
||||
/**
|
||||
* Sort direction hint name
|
||||
*/
|
||||
public const HINT_PAGINATOR_SORT_DIRECTION = 'knp_paginator.sort.direction';
|
||||
|
||||
/**
|
||||
* Walks down a SelectStatement AST node, modifying it to
|
||||
* sort the query like requested by url
|
||||
*/
|
||||
public function walkSelectStatement(SelectStatement $AST): string
|
||||
{
|
||||
$query = $this->_getQuery();
|
||||
$fields = (array)$query->getHint(self::HINT_PAGINATOR_SORT_FIELD);
|
||||
$aliases = (array)$query->getHint(self::HINT_PAGINATOR_SORT_ALIAS);
|
||||
|
||||
$components = $this->_getQueryComponents();
|
||||
foreach ($fields as $index => $field) {
|
||||
if (!$field) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$alias = $aliases[$index];
|
||||
if ($alias !== false) {
|
||||
if (!array_key_exists($alias, $components)) {
|
||||
throw new \UnexpectedValueException("There is no component aliased by [{$alias}] in the given Query");
|
||||
}
|
||||
$meta = $components[$alias];
|
||||
if (!$meta['metadata']->hasField($field)) {
|
||||
throw new \UnexpectedValueException("There is no such field [{$field}] in the given Query component, aliased by [$alias]");
|
||||
}
|
||||
} else {
|
||||
if (!array_key_exists($field, $components)) {
|
||||
throw new \UnexpectedValueException("There is no component field [{$field}] in the given Query");
|
||||
}
|
||||
}
|
||||
|
||||
$direction = $query->getHint(self::HINT_PAGINATOR_SORT_DIRECTION);
|
||||
if ($alias !== false) {
|
||||
$pathExpression = new PathExpression(PathExpression::TYPE_STATE_FIELD, $alias, $field);
|
||||
$pathExpression->type = PathExpression::TYPE_STATE_FIELD;
|
||||
} else {
|
||||
$pathExpression = $field;
|
||||
}
|
||||
|
||||
$orderByItem = new OrderByItem($pathExpression);
|
||||
$orderByItem->type = $direction;
|
||||
|
||||
if ($AST->orderByClause) {
|
||||
$set = false;
|
||||
foreach ($AST->orderByClause->orderByItems as $item) {
|
||||
if ($item->expression instanceof PathExpression) {
|
||||
if ($item->expression->identificationVariable === $alias && $item->expression->field === $field) {
|
||||
$item->type = $direction;
|
||||
$set = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$set) {
|
||||
array_unshift($AST->orderByClause->orderByItems, $orderByItem);
|
||||
}
|
||||
} else {
|
||||
$AST->orderByClause = new OrderByClause([$orderByItem]);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Sortable\Doctrine\ORM;
|
||||
|
||||
use Doctrine\ORM\Query;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Knp\Component\Pager\Event\Subscriber\Paginate\Doctrine\ORM\Query\Helper as QueryHelper;
|
||||
use Knp\Component\Pager\Event\Subscriber\Sortable\Doctrine\ORM\Query\OrderByWalker;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class QuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @var Request
|
||||
*/
|
||||
private $request;
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
// Check if the result has already been sorted by an other sort subscriber
|
||||
$customPaginationParameters = $event->getCustomPaginationParameters();
|
||||
if (!empty($customPaginationParameters['sorted']) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event->target instanceof Query) {
|
||||
$event->setCustomPaginationParameter('sorted', true);
|
||||
$sortField = $event->options[PaginatorInterface::SORT_FIELD_PARAMETER_NAME];
|
||||
$sortDir = $event->options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME];
|
||||
if (null !== $sortField && $this->request->query->has($sortField)) {
|
||||
$dir = null !== $sortDir && $this->request->query->has($sortDir) && strtolower($this->request->query->get($sortDir)) === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
|
||||
if (!in_array($this->request->query->get($sortField), $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
|
||||
throw new \UnexpectedValueException("Cannot sort by: [{$this->request->query->get($sortField)}] this field is not in allow list.");
|
||||
}
|
||||
}
|
||||
|
||||
$sortFieldParameterNames = $this->request->query->get($sortField);
|
||||
$fields = [];
|
||||
$aliases = [];
|
||||
if (!is_string($sortFieldParameterNames)) {
|
||||
throw new \UnexpectedValueException('Cannot sort with array parameter.');
|
||||
}
|
||||
|
||||
foreach (explode('+', $sortFieldParameterNames) as $sortFieldParameterName) {
|
||||
$parts = explode('.', $sortFieldParameterName, 2);
|
||||
|
||||
// We have to prepend the field. Otherwise OrderByWalker will add
|
||||
// the order-by items in the wrong order
|
||||
array_unshift($fields, end($parts));
|
||||
array_unshift($aliases, 2 <= count($parts) ? reset($parts) : false);
|
||||
}
|
||||
|
||||
$event->target
|
||||
->setHint(OrderByWalker::HINT_PAGINATOR_SORT_DIRECTION, $dir)
|
||||
->setHint(OrderByWalker::HINT_PAGINATOR_SORT_FIELD, $fields)
|
||||
->setHint(OrderByWalker::HINT_PAGINATOR_SORT_ALIAS, $aliases)
|
||||
;
|
||||
|
||||
QueryHelper::addCustomTreeWalker($event->target, OrderByWalker::class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Sortable;
|
||||
|
||||
use Elastica\Query;
|
||||
use Elastica\SearchableInterface;
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class ElasticaQuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private Request $request;
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
// Check if the result has already been sorted by an other sort subscriber
|
||||
$customPaginationParameters = $event->getCustomPaginationParameters();
|
||||
if (!empty($customPaginationParameters['sorted']) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($event->target) && 2 === count($event->target) && reset($event->target) instanceof SearchableInterface && end($event->target) instanceof Query) {
|
||||
[$searchable, $query] = $event->target;
|
||||
$event->setCustomPaginationParameter('sorted', true);
|
||||
$sortField = $event->options[PaginatorInterface::SORT_FIELD_PARAMETER_NAME];
|
||||
$sortDir = $event->options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME];
|
||||
if (null !== $sortField && $this->request->query->has($sortField)) {
|
||||
$field = $this->request->query->get($sortField);
|
||||
$dir = null !== $sortDir && $this->request->query->has($sortDir) && strtolower($this->request->query->get($sortDir)) === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST]) && !in_array($field, $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
|
||||
throw new \UnexpectedValueException(sprintf('Cannot sort by: [%s] this field is not in allow list.', $field));
|
||||
}
|
||||
|
||||
$query->setSort([
|
||||
$field => ['order' => $dir],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Sortable;
|
||||
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class PropelQuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private Request $request;
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
// Check if the result has already been sorted by an other sort subscriber
|
||||
$customPaginationParameters = $event->getCustomPaginationParameters();
|
||||
if (!empty($customPaginationParameters['sorted']) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$query = $event->target;
|
||||
if ($query instanceof \ModelCriteria) {
|
||||
$event->setCustomPaginationParameter('sorted', true);
|
||||
$sortField = $event->options[PaginatorInterface::SORT_FIELD_PARAMETER_NAME];
|
||||
$sortDir = $event->options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME];
|
||||
if (null !== $sortField && $this->request->query->has($sortField)) {
|
||||
$part = $this->request->query->get($sortField);
|
||||
$direction = (null !== $sortDir && $this->request->query->has($sortDir) && strtolower($this->request->query->get($sortDir)) === 'asc')
|
||||
? 'asc' : 'desc';
|
||||
|
||||
if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
|
||||
if (!in_array($this->request->query->get($sortField), $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
|
||||
throw new \UnexpectedValueException("Cannot sort by: [{$this->request->query->get($sortField)}] this field is not in allow list.");
|
||||
}
|
||||
}
|
||||
|
||||
$query->orderBy($part, $direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Sortable;
|
||||
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Solarium query sorting
|
||||
*
|
||||
* @author Marek Kalnik <marekk@theodo.fr>
|
||||
*/
|
||||
class SolariumQuerySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private Request $request;
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
// Check if the result has already been sorted by an other sort subscriber
|
||||
$customPaginationParameters = $event->getCustomPaginationParameters();
|
||||
if (!empty($customPaginationParameters['sorted']) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($event->target) && 2 === count($event->target)) {
|
||||
$values = array_values($event->target);
|
||||
[$client, $query] = $values;
|
||||
|
||||
if ($client instanceof \Solarium\Client && $query instanceof \Solarium\QueryType\Select\Query\Query) {
|
||||
$event->setCustomPaginationParameter('sorted', true);
|
||||
$sortField = $event->options[PaginatorInterface::SORT_FIELD_PARAMETER_NAME];
|
||||
if (null !== $sortField && $this->request->query->has($sortField)) {
|
||||
if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
|
||||
if (!in_array($this->request->query->get($sortField), $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
|
||||
throw new \UnexpectedValueException("Cannot sort by: [{$this->request->query->get($sortField)}] this field is not in allow list.");
|
||||
}
|
||||
}
|
||||
|
||||
$query->addSort($this->request->query->get($sortField), $this->getSortDirection($event));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
// trigger before the pagination subscriber
|
||||
'knp_pager.items' => ['items', 1],
|
||||
];
|
||||
}
|
||||
|
||||
private function getSortDirection($event): string
|
||||
{
|
||||
$sortDir = $event->options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME];
|
||||
|
||||
return null !== $sortDir && $this->request->query->has($sortDir) &&
|
||||
strtolower($this->request->query->get($sortDir)) === 'asc' ? 'asc' : 'desc';
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Event\Subscriber\Sortable;
|
||||
|
||||
use Knp\Component\Pager\Event\BeforeEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class SortableSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Lazy-load state tracker
|
||||
*/
|
||||
private bool $isLoaded = false;
|
||||
|
||||
public function before(BeforeEvent $event): void
|
||||
{
|
||||
// Do not lazy-load more than once
|
||||
if ($this->isLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher */
|
||||
$dispatcher = $event->getEventDispatcher();
|
||||
// hook all standard sortable subscribers
|
||||
$request = $event->getRequest();
|
||||
$dispatcher->addSubscriber(new Doctrine\ORM\QuerySubscriber($request));
|
||||
$dispatcher->addSubscriber(new Doctrine\ODM\MongoDB\QuerySubscriber($request));
|
||||
$dispatcher->addSubscriber(new ElasticaQuerySubscriber($request));
|
||||
$dispatcher->addSubscriber(new PropelQuerySubscriber($request));
|
||||
$dispatcher->addSubscriber(new SolariumQuerySubscriber($request));
|
||||
$dispatcher->addSubscriber(new ArraySubscriber($request));
|
||||
|
||||
$this->isLoaded = true;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.before' => ['before', 1],
|
||||
];
|
||||
}
|
||||
}
|
15
vendor/knplabs/knp-components/src/Knp/Component/Pager/Exception/PageLimitInvalidException.php
vendored
Normal file
15
vendor/knplabs/knp-components/src/Knp/Component/Pager/Exception/PageLimitInvalidException.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Exception;
|
||||
|
||||
use OutOfRangeException;
|
||||
|
||||
final class PageLimitInvalidException extends OutOfRangeException
|
||||
{
|
||||
public static function create(int $limit): self
|
||||
{
|
||||
return new self(
|
||||
sprintf('Invalid page limit. Limit: %d: $limit must be positive non-zero integer', $limit)
|
||||
);
|
||||
}
|
||||
}
|
15
vendor/knplabs/knp-components/src/Knp/Component/Pager/Exception/PageNumberInvalidException.php
vendored
Normal file
15
vendor/knplabs/knp-components/src/Knp/Component/Pager/Exception/PageNumberInvalidException.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Exception;
|
||||
|
||||
use OutOfRangeException;
|
||||
|
||||
final class PageNumberInvalidException extends OutOfRangeException
|
||||
{
|
||||
public static function create(int $page): self
|
||||
{
|
||||
return new self(
|
||||
sprintf('Invalid page number. Page: %d: $page must be positive non-zero integer', $page)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Exception;
|
||||
|
||||
use OutOfRangeException;
|
||||
use Throwable;
|
||||
|
||||
class PageNumberOutOfRangeException extends OutOfRangeException
|
||||
{
|
||||
private int $maxPageNumber;
|
||||
|
||||
public function __construct(?string $message, int $maxPageNumber, ?Throwable $previousException = null)
|
||||
{
|
||||
parent::__construct($message, 0, $previousException);
|
||||
|
||||
$this->maxPageNumber = $maxPageNumber;
|
||||
}
|
||||
|
||||
public function getMaxPageNumber(): int
|
||||
{
|
||||
return $this->maxPageNumber;
|
||||
}
|
||||
}
|
162
vendor/knplabs/knp-components/src/Knp/Component/Pager/Pagination/AbstractPagination.php
vendored
Normal file
162
vendor/knplabs/knp-components/src/Knp/Component/Pager/Pagination/AbstractPagination.php
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Pagination;
|
||||
|
||||
use Iterator;
|
||||
|
||||
abstract class AbstractPagination implements Iterator, PaginationInterface
|
||||
{
|
||||
protected ?int $currentPageNumber = null;
|
||||
protected ?int $numItemsPerPage = null;
|
||||
protected iterable $items = [];
|
||||
protected ?int $totalCount = null;
|
||||
protected ?array $paginatorOptions = null;
|
||||
protected ?array $customParameters = null;
|
||||
|
||||
public function rewind(): void
|
||||
{
|
||||
reset($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
return current($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|float|int|string|null
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
return key($this->items);
|
||||
}
|
||||
|
||||
public function next(): void
|
||||
{
|
||||
next($this->items);
|
||||
}
|
||||
|
||||
public function valid(): bool
|
||||
{
|
||||
return key($this->items) !== null;
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->items);
|
||||
}
|
||||
|
||||
public function setCustomParameters(array $parameters): void
|
||||
{
|
||||
$this->customParameters = $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getCustomParameter(string $name)
|
||||
{
|
||||
return $this->customParameters[$name] ?? null;
|
||||
}
|
||||
|
||||
public function setCurrentPageNumber(int $pageNumber): void
|
||||
{
|
||||
$this->currentPageNumber = $pageNumber;
|
||||
}
|
||||
|
||||
public function getCurrentPageNumber(): int
|
||||
{
|
||||
return $this->currentPageNumber;
|
||||
}
|
||||
|
||||
public function setItemNumberPerPage(int $numItemsPerPage): void
|
||||
{
|
||||
$this->numItemsPerPage = $numItemsPerPage;
|
||||
}
|
||||
|
||||
public function getItemNumberPerPage(): int
|
||||
{
|
||||
return $this->numItemsPerPage;
|
||||
}
|
||||
|
||||
public function setTotalItemCount(int $numTotal): void
|
||||
{
|
||||
$this->totalCount = $numTotal;
|
||||
}
|
||||
|
||||
public function getTotalItemCount(): int
|
||||
{
|
||||
return $this->totalCount;
|
||||
}
|
||||
|
||||
public function setPaginatorOptions(array $options): void
|
||||
{
|
||||
$this->paginatorOptions = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getPaginatorOption(string $name)
|
||||
{
|
||||
return $this->paginatorOptions[$name] ?? null;
|
||||
}
|
||||
|
||||
public function setItems(iterable $items): void
|
||||
{
|
||||
$this->items = $items;
|
||||
}
|
||||
|
||||
public function getItems(): iterable
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int|float|bool|null $offset
|
||||
*/
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
if ($this->items instanceof \ArrayIterator) {
|
||||
return array_key_exists($offset, iterator_to_array($this->items));
|
||||
}
|
||||
|
||||
return array_key_exists($offset, $this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int|float|bool|null $offset
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->items[$offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int|float|bool|null $offset
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if (null === $offset) {
|
||||
$this->items[] = $value;
|
||||
} else {
|
||||
$this->items[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int|float|bool|null $offset
|
||||
*/
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
unset($this->items[$offset]);
|
||||
}
|
||||
}
|
65
vendor/knplabs/knp-components/src/Knp/Component/Pager/Pagination/PaginationInterface.php
vendored
Normal file
65
vendor/knplabs/knp-components/src/Knp/Component/Pager/Pagination/PaginationInterface.php
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Pagination;
|
||||
|
||||
use ArrayAccess, Countable, Traversable;
|
||||
|
||||
/**
|
||||
* Pagination interface strictly defines
|
||||
* the methods - paginator will use to populate the
|
||||
* pagination data
|
||||
*/
|
||||
interface PaginationInterface extends Countable, Traversable, ArrayAccess
|
||||
{
|
||||
public function setCurrentPageNumber(int $pageNumber): void;
|
||||
|
||||
/**
|
||||
* Get currently used page number
|
||||
*/
|
||||
public function getCurrentPageNumber(): int;
|
||||
|
||||
public function setItemNumberPerPage(int $numItemsPerPage): void;
|
||||
|
||||
/**
|
||||
* Get number of items per page
|
||||
*/
|
||||
public function getItemNumberPerPage(): int;
|
||||
|
||||
public function setTotalItemCount(int $numTotal): void;
|
||||
|
||||
/**
|
||||
* Get total item number available
|
||||
*/
|
||||
public function getTotalItemCount(): int;
|
||||
|
||||
public function setItems(iterable $items): void;
|
||||
|
||||
/**
|
||||
* Get current items
|
||||
*/
|
||||
public function getItems(): iterable;
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
*/
|
||||
public function setPaginatorOptions(array $options): void;
|
||||
|
||||
/**
|
||||
* Get pagination alias
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPaginatorOption(string $name);
|
||||
|
||||
/**
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function setCustomParameters(array $parameters): void;
|
||||
|
||||
/**
|
||||
* Return custom parameter
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCustomParameter(string $name);
|
||||
}
|
94
vendor/knplabs/knp-components/src/Knp/Component/Pager/Pagination/SlidingPagination.php
vendored
Normal file
94
vendor/knplabs/knp-components/src/Knp/Component/Pager/Pagination/SlidingPagination.php
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager\Pagination;
|
||||
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* @todo: find a way to avoid exposing private member setters
|
||||
*
|
||||
* Sliding pagination
|
||||
*/
|
||||
final class SlidingPagination extends AbstractPagination
|
||||
{
|
||||
/**
|
||||
* Pagination page range
|
||||
*/
|
||||
private int $range = 5;
|
||||
|
||||
/**
|
||||
* Closure which is executed to render pagination
|
||||
*/
|
||||
public ?Closure $renderer = null;
|
||||
|
||||
public function setPageRange(int $range): void
|
||||
{
|
||||
$this->range = abs($range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the pagination
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
$data = $this->getPaginationData();
|
||||
$output = 'override in order to render a template';
|
||||
if ($this->renderer instanceof Closure) {
|
||||
$output = call_user_func($this->renderer, $data);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function getPaginationData(): array
|
||||
{
|
||||
$pageCount = (int) ceil($this->totalCount / $this->numItemsPerPage);
|
||||
$current = $this->currentPageNumber;
|
||||
|
||||
if ($this->range > $pageCount) {
|
||||
$this->range = $pageCount;
|
||||
}
|
||||
|
||||
$delta = ceil($this->range / 2);
|
||||
|
||||
if ($current - $delta > $pageCount - $this->range) {
|
||||
$pages = range($pageCount - $this->range + 1, $pageCount);
|
||||
} else {
|
||||
if ($current - $delta < 0) {
|
||||
$delta = $current;
|
||||
}
|
||||
|
||||
$offset = $current - $delta;
|
||||
$pages = range($offset + 1, $offset + $this->range);
|
||||
}
|
||||
|
||||
$viewData = [
|
||||
'last' => $pageCount,
|
||||
'current' => $current,
|
||||
'numItemsPerPage' => $this->numItemsPerPage,
|
||||
'first' => 1,
|
||||
'pageCount' => $pageCount,
|
||||
'totalCount' => $this->totalCount,
|
||||
];
|
||||
$viewData = array_merge($viewData, $this->paginatorOptions, $this->customParameters);
|
||||
|
||||
if ($current - 1 > 0) {
|
||||
$viewData['previous'] = $current - 1;
|
||||
}
|
||||
|
||||
if ($current + 1 <= $pageCount) {
|
||||
$viewData['next'] = $current + 1;
|
||||
}
|
||||
$viewData['pagesInRange'] = $pages;
|
||||
$viewData['firstPageInRange'] = min($pages);
|
||||
$viewData['lastPageInRange'] = max($pages);
|
||||
|
||||
if ($this->getItems() !== null) {
|
||||
$viewData['currentItemCount'] = $this->count();
|
||||
$viewData['firstItemNumber'] = (($current - 1) * $this->numItemsPerPage) + 1;
|
||||
$viewData['lastItemNumber'] = $viewData['firstItemNumber'] + $viewData['currentItemCount'] - 1;
|
||||
}
|
||||
|
||||
return $viewData;
|
||||
}
|
||||
}
|
134
vendor/knplabs/knp-components/src/Knp/Component/Pager/Paginator.php
vendored
Normal file
134
vendor/knplabs/knp-components/src/Knp/Component/Pager/Paginator.php
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager;
|
||||
|
||||
use Knp\Component\Pager\Exception\PageLimitInvalidException;
|
||||
use Knp\Component\Pager\Exception\PageNumberInvalidException;
|
||||
use Knp\Component\Pager\Exception\PageNumberOutOfRangeException;
|
||||
use Knp\Component\Pager\Pagination\PaginationInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* Paginator uses event dispatcher to trigger pagination
|
||||
* lifecycle events. Subscribers are expected to paginate
|
||||
* wanted target and finally it generates pagination view
|
||||
* which is only the result of paginator
|
||||
*/
|
||||
final class Paginator implements PaginatorInterface
|
||||
{
|
||||
private EventDispatcherInterface $eventDispatcher;
|
||||
|
||||
/**
|
||||
* Default options of paginator
|
||||
*
|
||||
* @var array<string, scalar>
|
||||
*/
|
||||
private array $defaultOptions = [
|
||||
self::PAGE_PARAMETER_NAME => 'page',
|
||||
self::SORT_FIELD_PARAMETER_NAME => 'sort',
|
||||
self::SORT_DIRECTION_PARAMETER_NAME => 'direction',
|
||||
self::FILTER_FIELD_PARAMETER_NAME => 'filterParam',
|
||||
self::FILTER_VALUE_PARAMETER_NAME => 'filterValue',
|
||||
self::DISTINCT => true,
|
||||
self::PAGE_OUT_OF_RANGE => self::PAGE_OUT_OF_RANGE_IGNORE,
|
||||
self::DEFAULT_LIMIT => self::DEFAULT_LIMIT_VALUE,
|
||||
];
|
||||
|
||||
private ?RequestStack $requestStack;
|
||||
|
||||
public function __construct(EventDispatcherInterface $eventDispatcher, RequestStack $requestStack = null)
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default paginator options
|
||||
* to be reused for paginations
|
||||
*/
|
||||
public function setDefaultPaginatorOptions(array $options): void
|
||||
{
|
||||
$this->defaultOptions = \array_merge($this->defaultOptions, $options);
|
||||
}
|
||||
|
||||
public function paginate($target, int $page = 1, int $limit = null, array $options = []): PaginationInterface
|
||||
{
|
||||
if ($page <= 0) {
|
||||
throw PageNumberInvalidException::create($page);
|
||||
}
|
||||
|
||||
$limit = $limit ?? $this->defaultOptions[self::DEFAULT_LIMIT];
|
||||
if ($limit <= 0) {
|
||||
throw PageLimitInvalidException::create($limit);
|
||||
}
|
||||
|
||||
$offset = ($page - 1) * $limit;
|
||||
$options = \array_merge($this->defaultOptions, $options);
|
||||
|
||||
// normalize default sort field
|
||||
if (isset($options[PaginatorInterface::DEFAULT_SORT_FIELD_NAME]) && is_array($options[PaginatorInterface::DEFAULT_SORT_FIELD_NAME])) {
|
||||
$options[PaginatorInterface::DEFAULT_SORT_FIELD_NAME] = implode('+', $options[PaginatorInterface::DEFAULT_SORT_FIELD_NAME]);
|
||||
}
|
||||
|
||||
$request = null === $this->requestStack ? Request::createFromGlobals() : $this->requestStack->getCurrentRequest();
|
||||
|
||||
// default sort field and direction are set based on options (if available)
|
||||
if (isset($options[self::DEFAULT_SORT_FIELD_NAME]) && !$request->query->has($options[self::SORT_FIELD_PARAMETER_NAME])) {
|
||||
$request->query->set($options[self::SORT_FIELD_PARAMETER_NAME], $options[self::DEFAULT_SORT_FIELD_NAME]);
|
||||
|
||||
if (!$request->query->has($options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME])) {
|
||||
$request->query->set($options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME], $options[PaginatorInterface::DEFAULT_SORT_DIRECTION] ?? 'asc');
|
||||
}
|
||||
}
|
||||
|
||||
// before pagination start
|
||||
$beforeEvent = new Event\BeforeEvent($this->eventDispatcher, $request);
|
||||
$this->eventDispatcher->dispatch($beforeEvent, 'knp_pager.before');
|
||||
// items
|
||||
$itemsEvent = new Event\ItemsEvent($offset, $limit);
|
||||
$itemsEvent->options = &$options;
|
||||
$itemsEvent->target = &$target;
|
||||
$this->eventDispatcher->dispatch($itemsEvent, 'knp_pager.items');
|
||||
if (!$itemsEvent->isPropagationStopped()) {
|
||||
throw new \RuntimeException('One of listeners must count and slice given target');
|
||||
}
|
||||
if ($page > ceil($itemsEvent->count / $limit)) {
|
||||
$pageOutOfRangeOption = $options[PaginatorInterface::PAGE_OUT_OF_RANGE] ?? $this->defaultOptions[PaginatorInterface::PAGE_OUT_OF_RANGE];
|
||||
if ($pageOutOfRangeOption === PaginatorInterface::PAGE_OUT_OF_RANGE_FIX && $itemsEvent->count > 0) {
|
||||
// replace page number out of range with max page
|
||||
return $this->paginate($target, (int) ceil($itemsEvent->count / $limit), $limit, $options);
|
||||
}
|
||||
if ($pageOutOfRangeOption === self::PAGE_OUT_OF_RANGE_THROW_EXCEPTION && $page > 1) {
|
||||
throw new PageNumberOutOfRangeException(
|
||||
sprintf('Page number: %d is out of range.', $page),
|
||||
(int) ceil($itemsEvent->count / $limit)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// pagination initialization event
|
||||
$paginationEvent = new Event\PaginationEvent;
|
||||
$paginationEvent->target = &$target;
|
||||
$paginationEvent->options = &$options;
|
||||
$this->eventDispatcher->dispatch($paginationEvent, 'knp_pager.pagination');
|
||||
if (!$paginationEvent->isPropagationStopped()) {
|
||||
throw new \RuntimeException('One of listeners must create pagination view');
|
||||
}
|
||||
// pagination class can be different, with different rendering methods
|
||||
$paginationView = $paginationEvent->getPagination();
|
||||
$paginationView->setCustomParameters($itemsEvent->getCustomPaginationParameters());
|
||||
$paginationView->setCurrentPageNumber($page);
|
||||
$paginationView->setItemNumberPerPage($limit);
|
||||
$paginationView->setTotalItemCount($itemsEvent->count);
|
||||
$paginationView->setPaginatorOptions($options);
|
||||
$paginationView->setItems($itemsEvent->items);
|
||||
|
||||
// after
|
||||
$afterEvent = new Event\AfterEvent($paginationView);
|
||||
$this->eventDispatcher->dispatch($afterEvent, 'knp_pager.after');
|
||||
|
||||
return $paginationView;
|
||||
}
|
||||
}
|
47
vendor/knplabs/knp-components/src/Knp/Component/Pager/PaginatorInterface.php
vendored
Normal file
47
vendor/knplabs/knp-components/src/Knp/Component/Pager/PaginatorInterface.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Component\Pager;
|
||||
|
||||
use Knp\Component\Pager\Pagination\PaginationInterface;
|
||||
|
||||
/**
|
||||
* PaginatorInterface
|
||||
*/
|
||||
interface PaginatorInterface
|
||||
{
|
||||
public const DEFAULT_SORT_FIELD_NAME = 'defaultSortFieldName';
|
||||
public const DEFAULT_SORT_DIRECTION = 'defaultSortDirection';
|
||||
public const DEFAULT_FILTER_FIELDS = 'defaultFilterFields';
|
||||
public const SORT_FIELD_PARAMETER_NAME = 'sortFieldParameterName';
|
||||
public const SORT_FIELD_ALLOW_LIST = 'sortFieldAllowList';
|
||||
public const SORT_DIRECTION_PARAMETER_NAME = 'sortDirectionParameterName';
|
||||
public const PAGE_PARAMETER_NAME = 'pageParameterName';
|
||||
public const FILTER_FIELD_PARAMETER_NAME = 'filterFieldParameterName';
|
||||
public const FILTER_VALUE_PARAMETER_NAME = 'filterValueParameterName';
|
||||
public const FILTER_FIELD_ALLOW_LIST = 'filterFieldAllowList';
|
||||
public const DISTINCT = 'distinct';
|
||||
public const PAGE_OUT_OF_RANGE = 'pageOutOfRange';
|
||||
public const DEFAULT_LIMIT = 'defaultLimit';
|
||||
public const ODM_QUERY_OPTIONS = 'odmQueryOptions';
|
||||
|
||||
public const PAGE_OUT_OF_RANGE_IGNORE = 'ignore'; // do nothing (default)
|
||||
public const PAGE_OUT_OF_RANGE_FIX = 'fix'; // replace page number out of range with max page
|
||||
public const PAGE_OUT_OF_RANGE_THROW_EXCEPTION = 'throwException'; // throw PageNumberOutOfRangeException
|
||||
public const DEFAULT_LIMIT_VALUE = 10;
|
||||
|
||||
/**
|
||||
* Paginates anything (depending on event listeners)
|
||||
* into Pagination object, which is a view targeted
|
||||
* pagination object (might be aggregated helper object)
|
||||
* responsible for the pagination result representation
|
||||
*
|
||||
* @param mixed $target anything what needs to be paginated
|
||||
* @param int $page page number, starting from 1
|
||||
* @param int|null $limit number of items per page
|
||||
* @param array $options less used options:
|
||||
* bool $distinct default true for distinction of results
|
||||
* string $alias pagination alias, default none
|
||||
* array $sortFieldAllowList sortable allow list for target fields being paginated
|
||||
*/
|
||||
public function paginate($target, int $page = 1, int $limit = null, array $options = []): PaginationInterface;
|
||||
}
|
19
vendor/knplabs/knp-paginator-bundle/LICENSE
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2011 Knplabs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
330
vendor/knplabs/knp-paginator-bundle/README.md
vendored
Normal file
330
vendor/knplabs/knp-paginator-bundle/README.md
vendored
Normal file
@ -0,0 +1,330 @@
|
||||
# Intro to KnpPaginatorBundle
|
||||
|
||||
Friendly Symfony paginator to paginate everything
|
||||
|
||||
[](https://github.com/KnpLabs/KnpPaginatorBundle/actions)
|
||||
|
||||
Generally this bundle is based on [Knp Pager component][knp_component_pager]. This
|
||||
component introduces a different way of pagination handling. You can read more about the
|
||||
internal logic on the given documentation link.
|
||||
|
||||
[](http://knpbundles.com/KnpLabs/KnpPaginatorBundle)
|
||||
|
||||
**Note:** Keep **knp-components** in sync with this bundle. If you want to use
|
||||
older version of KnpPaginatorBundle - use **v3.0** or **v4.X** tags in the repository which is
|
||||
suitable to paginate **ODM MongoDB** and **ORM 2.0** queries
|
||||
|
||||
## Latest updates
|
||||
|
||||
For notes about the latest changes please read [`CHANGELOG`](https://github.com/KnpLabs/KnpPaginatorBundle/blob/master/CHANGELOG.md),
|
||||
for required changes in your code please read [`UPGRADE`](https://github.com/KnpLabs/KnpPaginatorBundle/blob/master/docs/upgrade.md)
|
||||
chapter of the documentation.
|
||||
|
||||
## Requirements:
|
||||
|
||||
- Knp Pager component `>=2.0`.
|
||||
- KnpPaginatorBundle's master is compatible with Symfony `>=4.4` versions.
|
||||
- Twig `>=2.0` version is required if you use the Twig templating engine.
|
||||
|
||||
## Features:
|
||||
|
||||
- Does not require initializing specific adapters.
|
||||
- Can be customized in any way needed, etc.: pagination view, event subscribers.
|
||||
- Possibility to add custom filtering, sorting functionality depending on request parameters.
|
||||
- Separation of concerns, paginator is responsible for generating the pagination view only,
|
||||
pagination view - for representation purposes.
|
||||
|
||||
**Note:** using multiple paginators requires setting the **alias** in order to keep non
|
||||
conflicting parameters.
|
||||
|
||||
## More detailed documentation:
|
||||
|
||||
- Creating [custom pagination subscribers][doc_custom_pagination_subscriber]
|
||||
- [Extending pagination](#) class (todo, may require some refactoring)
|
||||
- [Customizing view][doc_templates] templates and arguments
|
||||
|
||||
## Installation and configuration:
|
||||
|
||||
### Pretty simple with [Composer](http://packagist.org), run
|
||||
|
||||
```sh
|
||||
composer require knplabs/knp-paginator-bundle
|
||||
```
|
||||
|
||||
### Add PaginatorBundle to your application kernel
|
||||
|
||||
If you don't use flex (you should), you need to manually enable bundle:
|
||||
|
||||
```php
|
||||
// app/AppKernel.php
|
||||
public function registerBundles()
|
||||
{
|
||||
return [
|
||||
// ...
|
||||
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
|
||||
// ...
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
<a name="configuration"></a>
|
||||
|
||||
### Configuration example
|
||||
|
||||
You can configure default query parameter names and templates
|
||||
|
||||
#### YAML:
|
||||
```yaml
|
||||
knp_paginator:
|
||||
page_range: 5 # number of links shown in the pagination menu (e.g: you have 10 pages, a page_range of 3, on the 5th page you'll see links to page 4, 5, 6)
|
||||
default_options:
|
||||
page_name: page # page query parameter name
|
||||
sort_field_name: sort # sort field query parameter name
|
||||
sort_direction_name: direction # sort direction query parameter name
|
||||
distinct: true # ensure distinct results, useful when ORM queries are using GROUP BY statements
|
||||
filter_field_name: filterField # filter field query parameter name
|
||||
filter_value_name: filterValue # filter value query parameter name
|
||||
template:
|
||||
pagination: '@KnpPaginator/Pagination/sliding.html.twig' # sliding pagination controls template
|
||||
sortable: '@KnpPaginator/Pagination/sortable_link.html.twig' # sort link template
|
||||
filtration: '@KnpPaginator/Pagination/filtration.html.twig' # filters template
|
||||
```
|
||||
#### PHP:
|
||||
```php
|
||||
// config/packages/paginator.php
|
||||
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $configurator): void
|
||||
{
|
||||
$configurator->extension('knp_paginator', [
|
||||
'page_range' => 5, // number of links shown in the pagination menu (e.g: you have 10 pages, a page_range of 3, on the 5th page you'll see links
|
||||
'default_options' => [
|
||||
'page_name' => 'page', // page query parameter name
|
||||
'sort_field_name' => 'sort', // sort field query parameter name
|
||||
'sort_direction_name' => 'direction', // sort direction query parameter name
|
||||
'distinct' => true, // ensure distinct results, useful when ORM queries are using GROUP BY statements
|
||||
'filter_field_name' => 'filterField', // filter field query parameter name
|
||||
'filter_value_name' => 'filterValue' // filter value query parameter name
|
||||
],
|
||||
'template' => [
|
||||
'pagination' => '@KnpPaginator/Pagination/sliding.html.twig', // sliding pagination controls template
|
||||
'sortable' => '@KnpPaginator/Pagination/sortable_link.html.twig', // sort link template
|
||||
'filtration' => '@KnpPaginator/Pagination/filtration.html.twig' // filters template
|
||||
]
|
||||
]);
|
||||
};
|
||||
```
|
||||
|
||||
#### Additional pagination templates
|
||||
That could be used out of the box in `knp_paginator.template.pagination` key:
|
||||
|
||||
* `@KnpPaginator/Pagination/sliding.html.twig` (by default)
|
||||
* `@KnpPaginator/Pagination/bootstrap_v5_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/twitter_bootstrap_v4_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/twitter_bootstrap_v3_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/twitter_bootstrap_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/foundation_v6_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/foundation_v5_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/bulma_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/semantic_ui_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/materialize_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/tailwindcss_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/uikit_v3_pagination.html.twig`
|
||||
|
||||
#### Additional sortable templates
|
||||
That could be used out of the box in `knp_paginator.template.sortable` key:
|
||||
|
||||
* `@KnpPaginator/Pagination/sortable_link.html.twig` (by default)
|
||||
* `@KnpPaginator/Pagination/bootstrap_v5_bi_sortable_link.html.twig`
|
||||
* `@KnpPaginator/Pagination/bootstrap_v5_fa_sortable_link.html.twig`
|
||||
* `@KnpPaginator/Pagination/bootstrap_v5_md_sortable_link.html.twig`
|
||||
* `@KnpPaginator/Pagination/twitter_bootstrap_v3_sortable_link.html.twig`
|
||||
* `@KnpPaginator/Pagination/twitter_bootstrap_v4_font_awesome_sortable_link.html.twig`
|
||||
* `@KnpPaginator/Pagination/twitter_bootstrap_v4_material_design_icons_sortable_link.html.twig`
|
||||
* `@KnpPaginator/Pagination/semantic_ui_sortable_link.html.twig`
|
||||
* `@KnpPaginator/Pagination/uikit_v3_sortable.html.twig`
|
||||
|
||||
#### Additional filtration templates
|
||||
That could be used out of the box in `knp_paginator.template.filtration` key:
|
||||
|
||||
* `@KnpPaginator/Pagination/filtration.html.twig` (by default)
|
||||
* `@KnpPaginator/Pagination/bootstrap_v5_filtration.html.twig`
|
||||
* `@KnpPaginator/Pagination/twitter_bootstrap_v4_filtration.html.twig`
|
||||
|
||||
## Usage examples:
|
||||
|
||||
### Controller
|
||||
|
||||
Currently paginator can paginate:
|
||||
|
||||
- `array`
|
||||
- `Doctrine\ORM\Query`
|
||||
- `Doctrine\ORM\QueryBuilder`
|
||||
- `Doctrine\ODM\MongoDB\Query\Query`
|
||||
- `Doctrine\ODM\MongoDB\Query\Builder`
|
||||
- `Doctrine\ODM\PHPCR\Query\Query`
|
||||
- `Doctrine\ODM\PHPCR\Query\Builder\QueryBuilder`
|
||||
- `Doctrine\Common\Collection\ArrayCollection` - any Doctrine relation collection including
|
||||
- `ModelCriteria` - Propel ORM query
|
||||
- array with `Solarium_Client` and `Solarium_Query_Select` as elements
|
||||
|
||||
```php
|
||||
// App\Controller\ArticleController.php
|
||||
|
||||
public function listAction(EntityManagerInterface $em, PaginatorInterface $paginator, Request $request)
|
||||
{
|
||||
$dql = "SELECT a FROM AcmeMainBundle:Article a";
|
||||
$query = $em->createQuery($dql);
|
||||
|
||||
$pagination = $paginator->paginate(
|
||||
$query, /* query NOT result */
|
||||
$request->query->getInt('page', 1), /*page number*/
|
||||
10 /*limit per page*/
|
||||
);
|
||||
|
||||
// parameters to template
|
||||
return $this->render('article/list.html.twig', ['pagination' => $pagination]);
|
||||
}
|
||||
```
|
||||
|
||||
### View
|
||||
|
||||
```twig
|
||||
{# total items count #}
|
||||
<div class="count">
|
||||
{{ pagination.getTotalItemCount }}
|
||||
</div>
|
||||
<table>
|
||||
<tr>
|
||||
{# sorting of properties based on query components #}
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Id', 'a.id') }}</th>
|
||||
<th{% if pagination.isSorted('a.Title') %} class="sorted"{% endif %}>
|
||||
{{ knp_pagination_sortable(pagination, 'Title', 'a.title') }}
|
||||
</th>
|
||||
<th{% if pagination.isSorted(['a.date', 'a.time']) %} class="sorted"{% endif %}>
|
||||
{{ knp_pagination_sortable(pagination, 'Release', ['a.date', 'a.time']) }}
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
{# table body #}
|
||||
{% for article in pagination %}
|
||||
<tr {% if loop.index is odd %}class="color"{% endif %}>
|
||||
<td>{{ article.id }}</td>
|
||||
<td>{{ article.title }}</td>
|
||||
<td>{{ article.date | date('Y-m-d') }}, {{ article.time | date('H:i:s') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{# display navigation #}
|
||||
<div class="navigation">
|
||||
{{ knp_pagination_render(pagination) }}
|
||||
</div>
|
||||
```
|
||||
|
||||
### Translation in view
|
||||
For translating the following text:
|
||||
* `%foo% name` with translation key `table_header_name`. The translation is in the domain `messages`.
|
||||
* `{0} No author|{1} Author|[2,Inf] Authors` with translation key `table_header_author`. The translation is in the domain `messages`.
|
||||
|
||||
translationCount and translationParameters can be combined.
|
||||
|
||||
```twig
|
||||
<table>
|
||||
<tr>
|
||||
{# sorting of properties based on query components #}
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Id'|trans({foo:'bar'},'messages'), 'a.id' )|raw }}</th>
|
||||
<th{% if pagination.isSorted('a.Title') %} class="sorted"{% endif %}>{{ knp_pagination_sortable(pagination, 'Title', 'a.title')|raw }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Author'|trans({}, 'messages'), 'a.author' )|raw }}</th>
|
||||
</tr>
|
||||
|
||||
<!-- Content of the table -->
|
||||
</table>
|
||||
```
|
||||
|
||||
### Adding translation files
|
||||
You can also override translations by creating a translation file in the following name format: `domain.locale.format`.
|
||||
So, to create a translation file for this bundle you need to create for instance `KnpPaginatorBundle.tr.yaml` file under `project_root/translations/`
|
||||
and add your translations there:
|
||||
```yaml
|
||||
label_previous: "Önceki"
|
||||
label_next: "Sonraki"
|
||||
filter_searchword: "Arama kelimesi"
|
||||
```
|
||||
If you set default translation for configuration accordingly:
|
||||
```yaml
|
||||
framework:
|
||||
default_locale: tr
|
||||
```
|
||||
Symfony will pick it automatically.
|
||||
|
||||
### Dependency Injection
|
||||
|
||||
You can automatically inject a paginator service into another service by using the `knp_paginator.injectable` DIC tag.
|
||||
The tag takes one optional argument `paginator`, which is the ID of the paginator service that should be injected.
|
||||
It defaults to `knp_paginator`.
|
||||
|
||||
The class that receives the KnpPaginator service must implement `Knp\Bundle\PaginatorBundle\Definition\PaginatorAwareInterface`.
|
||||
If you're too lazy you can also just extend the `Knp\Bundle\PaginatorBundle\Definition\PaginatorAware` base class.
|
||||
|
||||
> **⚠ Warning** using `PaginatorAwareInterface` is discouraged, and could be removed in a future version. You should not rely on setter
|
||||
> injection, but only on proper constructor injection. Using Symfony built-in autowiring mechanism is the suggested way to go.
|
||||
|
||||
#### Lazy service
|
||||
|
||||
The `knp_paginator` service will be created lazily if the package `symfony/proxy-manager-bridge` is installed.
|
||||
|
||||
For more information about lazy services, consult the [Symfony documentation on dependency injection](https://symfony.com/doc/current/service_container/lazy_services.html).
|
||||
|
||||
###### XML configuration example
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<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 http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<parameters>
|
||||
<parameter key="my_bundle.paginator_aware.class">MyBundle\Repository\PaginatorAwareRepository</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
<service id="my_bundle.paginator_aware" class="my_bundle.paginator_aware.class">
|
||||
<tag name="knp_paginator.injectable" paginator="knp_paginator" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
```
|
||||
|
||||
[knp_component_pager]: https://github.com/KnpLabs/knp-components/blob/master/docs/pager/intro.md "Knp Pager component introduction"
|
||||
[doc_custom_pagination_subscriber]: https://github.com/KnpLabs/KnpPaginatorBundle/tree/master/docs/custom_pagination_subscribers.md "Custom pagination subscribers"
|
||||
[doc_templates]: https://github.com/KnpLabs/KnpPaginatorBundle/tree/master/docs/templates.md "Customizing Pagination templates"
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Make sure the translator is activated in your Symfony config:
|
||||
|
||||
```yaml
|
||||
framework:
|
||||
translator: { fallbacks: ['%locale%'] }
|
||||
```
|
||||
|
||||
- If your locale is not available, create your own translation file in
|
||||
`translations/KnpPaginatorBundle.en.yml` (substitute "en" for your own language code if needed).
|
||||
Then add these lines:
|
||||
|
||||
```yaml
|
||||
label_next: Next
|
||||
label_previous: Previous
|
||||
```
|
||||
|
||||
## Maintainers
|
||||
|
||||
Please read [this post](https://knplabs.com/en/blog/news-for-our-foss-projects-maintenance) first.
|
||||
|
||||
This library is maintained by the following people (alphabetically sorted) :
|
||||
- @garak
|
||||
- @polc
|
52
vendor/knplabs/knp-paginator-bundle/composer.json
vendored
Normal file
52
vendor/knplabs/knp-paginator-bundle/composer.json
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "knplabs/knp-paginator-bundle",
|
||||
"type": "symfony-bundle",
|
||||
"description": "Paginator bundle for Symfony to automate pagination and simplify sorting and other features",
|
||||
"keywords": ["pager", "paginator", "pagination", "symfony", "bundle", "knp", "knplabs"],
|
||||
"homepage": "http://github.com/KnpLabs/KnpPaginatorBundle",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "KnpLabs Team",
|
||||
"homepage": "http://knplabs.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "http://github.com/KnpLabs/KnpPaginatorBundle/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.3 || ^8.0",
|
||||
"knplabs/knp-components": "^2.4 || ^3.0",
|
||||
"symfony/config": "^4.4 || ^5.4 || ^6.0",
|
||||
"symfony/dependency-injection": "^4.4 || ^5.4 || ^6.0",
|
||||
"symfony/event-dispatcher": "^4.4 || ^5.4 || ^6.0",
|
||||
"symfony/http-foundation": "^4.4 || ^5.4 || ^6.0",
|
||||
"symfony/http-kernel": "^4.4 || ^5.4 || ^6.0",
|
||||
"symfony/routing": "^4.4 || ^5.4 || ^6.0",
|
||||
"symfony/translation": "^4.4 || ^5.4 || ^6.0",
|
||||
"twig/twig": "^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.2",
|
||||
"phpunit/phpunit": "^8.5 || ^9.5",
|
||||
"symfony/expression-language": "^4.4 || ^5.4 || ^6.0",
|
||||
"symfony/templating": "^4.4 || ^5.4 || ^6.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Knp\\Bundle\\PaginatorBundle\\": "src"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vendor/bin/phpunit"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
50
vendor/knplabs/knp-paginator-bundle/config/paginator.xml
vendored
Normal file
50
vendor/knplabs/knp-paginator-bundle/config/paginator.xml
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<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 http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<services>
|
||||
<service id="knp_paginator" class="Knp\Component\Pager\Paginator" public="true" lazy="true">
|
||||
<argument type="service" id="event_dispatcher" />
|
||||
<argument type="service" id="request_stack" />
|
||||
<tag name="proxy" interface="Knp\Component\Pager\PaginatorInterface" />
|
||||
</service>
|
||||
|
||||
<service id="Knp\Component\Pager\PaginatorInterface" alias="knp_paginator" />
|
||||
|
||||
<service id="knp_paginator.subscriber.paginate" class="Knp\Component\Pager\Event\Subscriber\Paginate\PaginationSubscriber">
|
||||
<tag name="kernel.event_subscriber" />
|
||||
</service>
|
||||
|
||||
<service id="knp_paginator.subscriber.sortable" class="Knp\Component\Pager\Event\Subscriber\Sortable\SortableSubscriber">
|
||||
<tag name="kernel.event_subscriber" />
|
||||
</service>
|
||||
|
||||
<service id="knp_paginator.subscriber.filtration" class="Knp\Component\Pager\Event\Subscriber\Filtration\FiltrationSubscriber">
|
||||
<tag name="kernel.event_subscriber" />
|
||||
</service>
|
||||
|
||||
<service id="knp_paginator.subscriber.sliding_pagination" class="Knp\Bundle\PaginatorBundle\Subscriber\SlidingPaginationSubscriber">
|
||||
<argument type="collection">
|
||||
<argument key="defaultPaginationTemplate">%knp_paginator.template.pagination%</argument>
|
||||
<argument key="defaultSortableTemplate">%knp_paginator.template.sortable%</argument>
|
||||
<argument key="defaultFiltrationTemplate">%knp_paginator.template.filtration%</argument>
|
||||
<argument key="defaultPageRange">%knp_paginator.page_range%</argument>
|
||||
<argument key="defaultPageLimit">%knp_paginator.page_limit%</argument>
|
||||
</argument>
|
||||
<tag name="kernel.event_subscriber" />
|
||||
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
|
||||
</service>
|
||||
|
||||
<service id="knp_paginator.helper.processor" class="Knp\Bundle\PaginatorBundle\Helper\Processor">
|
||||
<argument type="service" id="router" />
|
||||
<argument type="service" id="translator" />
|
||||
</service>
|
||||
|
||||
<service id="knp_paginator.twig.extension.pagination" class="Knp\Bundle\PaginatorBundle\Twig\Extension\PaginationExtension">
|
||||
<argument type="service" id="knp_paginator.helper.processor" />
|
||||
<tag name="twig.extension" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
18
vendor/knplabs/knp-paginator-bundle/config/templating_php.xml
vendored
Normal file
18
vendor/knplabs/knp-paginator-bundle/config/templating_php.xml
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<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 http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<parameters>
|
||||
<parameter key="knp_paginator.templating.helper.pagination.class">Knp\Bundle\PaginatorBundle\Templating\PaginationHelper</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
<service id="knp_paginator.templating.helper.pagination" class="%knp_paginator.templating.helper.pagination.class%">
|
||||
<argument type="service" id="knp_paginator.helper.processor" />
|
||||
<argument type="service" id="templating.engine.php" />
|
||||
<tag name="templating.helper" alias="knp_pagination" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
145
vendor/knplabs/knp-paginator-bundle/docs/custom_pagination_subscribers.md
vendored
Normal file
145
vendor/knplabs/knp-paginator-bundle/docs/custom_pagination_subscribers.md
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
# Creating custom subscriber
|
||||
|
||||
Let's say we want to paginate a directory content, which might be quite interesting.
|
||||
And when we have such a handy **Finder** component in symfony, it's easily achievable.
|
||||
|
||||
## Prepare environment
|
||||
|
||||
I will assume we you just installed [Symfony demo](https://github.com/symfony/demo)
|
||||
and you install [KnpPaginatorBundle](https://github.com/knplabs/KnpPaginatorBundle).
|
||||
Follow the installation guide on these repositories, it's very easy to set up.
|
||||
|
||||
## Create subscriber
|
||||
|
||||
Next, let's extend our subscriber.
|
||||
Create a file named **src/Subscriber/PaginateDirectorySubscriber.php**
|
||||
|
||||
``` php
|
||||
<?php
|
||||
|
||||
// file: src/Subscriber/PaginateDirectorySubscriber.php
|
||||
// requires Symfony\Component\Finder\Finder
|
||||
|
||||
namespace App\Subscriber;
|
||||
|
||||
use Knp\Component\Pager\Event\ItemsEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
final class PaginateDirectorySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function items(ItemsEvent $event): void
|
||||
{
|
||||
if (!is_string($event->target) || !is_dir($event->target)) {
|
||||
return;
|
||||
}
|
||||
$finder = new Finder();
|
||||
$finder
|
||||
->files()
|
||||
->depth('< 4') // 3 levels
|
||||
->in($event->target)
|
||||
;
|
||||
$iterator = $finder->getIterator();
|
||||
$files = iterator_to_array($iterator);
|
||||
$event->count = count($files);
|
||||
$event->items = array_slice($files, $event->getOffset(), $event->getLimit());
|
||||
$event->stopPropagation();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.items' => ['items', 1/* increased priority to override any internal */]
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Class above is the simple event subscriber, which listens to **knp_pager.items** event.
|
||||
Creates a finder and looks in this directory for files. To be more specific it will look
|
||||
for the **files** in the directory being paginated, max in 3 level depth.
|
||||
|
||||
## Register subscriber as service
|
||||
|
||||
Next we need to tell **knp_paginator** about our new fancy subscriber which we intend
|
||||
to use in pagination. It is also very simple, add few line to your service config file
|
||||
(usually **config/services.xml**)
|
||||
|
||||
``` xml
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<!-- file: config/services.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 http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<services>
|
||||
<!-- ... -->
|
||||
|
||||
<service id="acme.directory.subscriber" class="App\Subscriber\PaginateDirectorySubscriber">
|
||||
<tag name="kernel.event_subscriber" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
```
|
||||
|
||||
## Controller action
|
||||
|
||||
Finally, we are done with configuration, now let's create actual controller action.
|
||||
Modify controller: **src/Controller/DemoController.php**
|
||||
And add the following action, which paginates the previous directory
|
||||
|
||||
``` php
|
||||
<?php
|
||||
|
||||
use ...
|
||||
|
||||
/**
|
||||
* @Route("/test", name="_demo_test")
|
||||
*/
|
||||
public function test(KnpPaginatorInterface $paginator, Request $request): Response
|
||||
{
|
||||
$pagination = $paginator->paginate(__DIR__.'/../', $request->query->getInt('page', 1), 10);
|
||||
|
||||
return $this->render('demo/test.html.twig', ['pagination' => $pagination]);
|
||||
}
|
||||
```
|
||||
|
||||
## Template
|
||||
|
||||
And the last thing is the template, create: **templates/demo/test.html.twig**
|
||||
|
||||
``` html
|
||||
{% extends "layout.html.twig" %}
|
||||
|
||||
{% block title "My demo" %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Demo</h1>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
{# sorting of properties based on query components #}
|
||||
<th>base name</th>
|
||||
<th>path</th>
|
||||
</tr>
|
||||
|
||||
{# table body #}
|
||||
{% for file in pagination %}
|
||||
<tr{% if loop.index is odd %} class="color"{% endif %}>
|
||||
<td>{{ file.baseName }}</td>
|
||||
<td>{{ file.path }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{# display navigation #}
|
||||
<div id="navigation">
|
||||
{{ knp_pagination_render(pagination) }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
Do not forget to reload the cache: **php bin/console cache:clear**
|
||||
|
||||
You should find some files paginated if you open the url: **http://baseurl/index.php/demo/test**
|
32
vendor/knplabs/knp-paginator-bundle/docs/manual_counting.md
vendored
Normal file
32
vendor/knplabs/knp-paginator-bundle/docs/manual_counting.md
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
# Manual counting
|
||||
|
||||
**Note:** this documentation concerns more advanced usage of ORM
|
||||
query pagination. Paginator cannot support two **FROM** components
|
||||
or composite identifiers, because it cannot predict the total count
|
||||
in the database.
|
||||
|
||||
The solution to that is simple and direct, you can provide the **count**
|
||||
manually through the hint on the query.
|
||||
|
||||
## Usage example
|
||||
|
||||
``` php
|
||||
<?php
|
||||
|
||||
$paginator = new Paginator();
|
||||
|
||||
$count = $entityManager
|
||||
->createQuery('SELECT COUNT(c) FROM Entity\CompositeKey c')
|
||||
->getSingleScalarResult()
|
||||
;
|
||||
|
||||
$query = $entityManager
|
||||
->createQuery('SELECT c FROM Entity\CompositeKey c')
|
||||
->setHint('knp_paginator.count', $count)
|
||||
;
|
||||
$pagination = $paginator->paginate($query, 1, 10, ['distinct' => false]);
|
||||
```
|
||||
|
||||
Distinction in this case also cannot be determined by paginator. It will take direct result
|
||||
of the query and limit with offset. In some cases you may need to use **GROUP BY**
|
||||
|
34
vendor/knplabs/knp-paginator-bundle/docs/paginator_configuration.md
vendored
Normal file
34
vendor/knplabs/knp-paginator-bundle/docs/paginator_configuration.md
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# Configuring paginator
|
||||
|
||||
There's an easy way to configure paginator - just add a `knp_paginator` entry to your configuration and change default values.
|
||||
Location of your configuration file depends on your Symfony versions: most common places are `config/packages/knp_paginator.yaml`
|
||||
for recent versions of Symfony and `app/config.yml` for older versions. If you can't find a configuration file, you can create it.
|
||||
|
||||
## Default options
|
||||
|
||||
``` yaml
|
||||
knp_paginator:
|
||||
page_range: 5 # default page range used in pagination control
|
||||
page_limit: 100 # page limit for pagination control; to disable set this field to ~ (null)
|
||||
convert_exception: false # convert paginator exception (e.g. non-positive page and/or limit) into 404 error
|
||||
default_options:
|
||||
page_name: page # page query parameter name
|
||||
sort_field_name: sort # sort field query parameter name; to disable sorting set this field to ~ (null)
|
||||
sort_direction_name: direction # sort direction query parameter name
|
||||
distinct: true # ensure distinct results, useful when ORM queries are using GROUP BY statements
|
||||
page_out_of_range: ignore # if page number exceeds the last page. Options: 'fix'(return last page); 'throwException'
|
||||
default_limit: 10 # default number of items per page
|
||||
template:
|
||||
pagination: @KnpPaginator/Pagination/sliding.html.twig # sliding pagination controls template
|
||||
sortable: @KnpPaginator/Pagination/sortable_link.html.twig # sort link template
|
||||
```
|
||||
|
||||
There are a few additional pagination templates, that could be used out of the box in `knp_paginator.template.pagination` key:
|
||||
|
||||
* `@KnpPaginator/Pagination/sliding.html.twig` (by default)
|
||||
* `@KnpPaginator/Pagination/twitter_bootstrap_v4_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/twitter_bootstrap_v3_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/twitter_bootstrap_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/foundation_v6_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/foundation_v5_pagination.html.twig`
|
||||
* `@KnpPaginator/Pagination/bulma_pagination.html.twig`
|
216
vendor/knplabs/knp-paginator-bundle/docs/templates.md
vendored
Normal file
216
vendor/knplabs/knp-paginator-bundle/docs/templates.md
vendored
Normal file
@ -0,0 +1,216 @@
|
||||
|
||||
# Templates
|
||||
|
||||
This document will describe how pagination can be rendered, extended and used in
|
||||
templates. For now there's only a sliding pagination supported, so all documentation
|
||||
will reference it.
|
||||
|
||||
## Overriding default pagination template
|
||||
|
||||
There are few ways to override templates
|
||||
|
||||
### Configuration
|
||||
|
||||
This way it will override it globally for all default pagination rendering.
|
||||
|
||||
You can override templates in [configuration of
|
||||
paginator](http://github.com/KnpLabs/KnpPaginatorBundle/blob/master/README.md#configuration)
|
||||
|
||||
Or place this parameter in **config/packages/knp_paginator.yaml**
|
||||
|
||||
knp_paginator.template.pagination: my_pagination.html.twig
|
||||
|
||||
Same for sorting link template:
|
||||
|
||||
knp_paginator.template.sortable: my_sortable.html.twig
|
||||
|
||||
### Directly in pagination
|
||||
|
||||
``` php
|
||||
$paginator = $this->get('knp_paginator');
|
||||
$pagination = $paginator->paginate($target, $page);
|
||||
$pagination->setTemplate('my_pagination.html.twig');
|
||||
$pagination->setSortableTemplate('my_sortable.html.twig');
|
||||
```
|
||||
|
||||
or in view
|
||||
|
||||
``` html
|
||||
{% do pagination.setTemplate('my_pagination.html.twig') %}
|
||||
```
|
||||
|
||||
### In render method
|
||||
|
||||
```twig
|
||||
{{ knp_pagination_render(pagination, 'my_pagination.html.twig') }}
|
||||
```
|
||||
|
||||
or by specifying path to your custom template that is located under your project's `templates` directory:
|
||||
```twig
|
||||
{{ knp_pagination_sortable(pagination, 'date', 'c.publishedAt', {}, {}, 'KnpPaginator/Pagination/bootstrap_v4_sortable_link.html.twig') }}
|
||||
{{ knp_pagination_render(pagination, 'KnpPaginator/Pagination/bootstrap_v4_pagination.html.twig') }}
|
||||
```
|
||||
|
||||
## Other useful parameters
|
||||
|
||||
By default when render method is triggered, pagination renders the template
|
||||
with standard arguments provided:
|
||||
|
||||
- pagination parameters, like pages in range, current page and so on..
|
||||
- route - which is used to generate page, sorting urls
|
||||
- request query, which contains all GET request parameters
|
||||
- extra pagination template parameters
|
||||
|
||||
Except from pagination parameters, others can be modified or adapted to some
|
||||
use cases. Usually it's possible, you might need setting a route if default is not
|
||||
matched correctly (because of rendering in sub requests). Or adding additional
|
||||
query or view parameters.
|
||||
|
||||
### Setting a route and query parameters to use for pagination urls
|
||||
|
||||
``` php
|
||||
<?php
|
||||
$paginator = $this->get('knp_paginator');
|
||||
$pagination = $paginator->paginate($target, $page);
|
||||
$pagination->setUsedRoute('blog_articles');
|
||||
```
|
||||
|
||||
In case if route requires additional parameters
|
||||
|
||||
``` php
|
||||
<?php
|
||||
$pagination->setParam('category', 'news');
|
||||
```
|
||||
|
||||
This would set additional query parameter
|
||||
|
||||
### Additional pagination template parameters
|
||||
|
||||
If you need custom parameters in pagination template, use:
|
||||
|
||||
``` php
|
||||
<?php
|
||||
// set an array of custom parameters
|
||||
$pagination->setCustomParameters([
|
||||
'align' => 'center', # center|right (for template: twitter_bootstrap_v4_pagination and foundation_v6_pagination)
|
||||
'size' => 'large', # small|large (for template: twitter_bootstrap_v4_pagination)
|
||||
'style' => 'bottom',
|
||||
'span_class' => 'whatever',
|
||||
]);
|
||||
```
|
||||
|
||||
### You can also change the page range
|
||||
|
||||
Default page range is 5 pages in sliding pagination. Doing it in controller:
|
||||
|
||||
``` php
|
||||
<?php
|
||||
$pagination->setPageRange(7);
|
||||
```
|
||||
|
||||
In template:
|
||||
|
||||
``` php
|
||||
{% do pagination.setPageRange(7) %}
|
||||
```
|
||||
|
||||
### Setting a page limit
|
||||
|
||||
The default page limit is unlimited, but if for some reason you want to limit
|
||||
the number of pages you can do so. Doing it in controller:
|
||||
|
||||
``` php
|
||||
<?php
|
||||
$pagination->setPageLimit(25);
|
||||
```
|
||||
|
||||
In template:
|
||||
|
||||
``` php
|
||||
{% do pagination.setPageLimit(25) %}
|
||||
```
|
||||
|
||||
## Choose the sorting direction
|
||||
|
||||
The `knp_pagination_sortable()` template automatically switches the sorting direction but sometimes you need to propose that your users select the sorting direction.
|
||||
You can add an array at the end of `knp_pagination_sortable()` to choose the direction.
|
||||
|
||||
``` html
|
||||
{{ knp_pagination_sortable(pagination, 'Title A-Z', 'a.title', {}, {'direction': 'asc'}) }}
|
||||
{{ knp_pagination_sortable(pagination, 'Title Z-A', 'a.title', {}, {'direction': 'desc'}) }}
|
||||
```
|
||||
(Assuming you use the default configuration value of sort_direction_name)
|
||||
|
||||
<a name="query-parameters"></a>
|
||||
|
||||
## Query parameters
|
||||
|
||||
If you need to change query parameters for paginator or use multiple paginators for the same page.
|
||||
You can customize these parameter names through [configuration](http://github.com/KnpLabs/KnpPaginatorBundle/blob/master/README.md#configuration)
|
||||
or manually with paginator options.
|
||||
|
||||
``` php
|
||||
<?php // controller
|
||||
|
||||
// will change "page" query parameter into "section" and sort direction "direction" into "dir"
|
||||
$paginator = $this->get('knp_paginator');
|
||||
$pagination = $paginator->paginate(
|
||||
$query, // target to paginate
|
||||
$this->get('request')->query->getInt('section', 1), // page parameter, now section
|
||||
10, // limit per page
|
||||
['pageParameterName' => 'section', 'sortDirectionParameterName' => 'dir']
|
||||
);
|
||||
```
|
||||
|
||||
Or even in Twig:
|
||||
|
||||
```jinja
|
||||
{{ knp_pagination_render(
|
||||
pagination,
|
||||
'@KnpPaginator/Pagination/twitter_bootstrap_v4_pagination.html.twig',
|
||||
{
|
||||
'queryParam1': 'param1 value',
|
||||
'queryParam2': 'param2 value'
|
||||
},
|
||||
{
|
||||
'viewParam1': 'param1 value',
|
||||
'viewParam2': 'param2 value'
|
||||
},
|
||||
) }}
|
||||
```
|
||||
|
||||
## Filter your query
|
||||
|
||||
Only include this lines and enjoy the pagination :
|
||||
``` html
|
||||
{{ knp_pagination_filter(pagination, {
|
||||
'entity.name': 'Name',
|
||||
}) }}
|
||||
```
|
||||
|
||||
## Customize rendering
|
||||
|
||||
### Bulma
|
||||
|
||||
You can configure the position, the size, and make the buttons rounded or not:
|
||||
- `align`: `'left'`, `'center'`, or `'right'`. By default align is not modified
|
||||
- `size`: `'small'`, `'medium'`, or `'large'`. By default, size is not modified
|
||||
- `rounded`: `true` or `false`. By default it's `false`
|
||||
|
||||
In your controller:
|
||||
```php
|
||||
$pagination->setCustomParameters([
|
||||
'align' => 'center',
|
||||
'size' => 'large',
|
||||
'rounded' => true,
|
||||
]);
|
||||
```
|
||||
|
||||
or in the view:
|
||||
```twig
|
||||
{{ knp_pagination_render(pagination, null, {}, {
|
||||
'align': 'center',
|
||||
'size': 'large',
|
||||
'rounded': true,
|
||||
}) }}
|
||||
```
|
34
vendor/knplabs/knp-paginator-bundle/src/Definition/AbstractPaginatorAware.php
vendored
Normal file
34
vendor/knplabs/knp-paginator-bundle/src/Definition/AbstractPaginatorAware.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\Definition;
|
||||
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
|
||||
/**
|
||||
* This is a base class that can be extended if you're too lazy to implement PaginatorAwareInterface yourself.
|
||||
*/
|
||||
abstract class AbstractPaginatorAware implements PaginatorAwareInterface
|
||||
{
|
||||
/**
|
||||
* @var PaginatorInterface
|
||||
*/
|
||||
private $paginator;
|
||||
|
||||
/**
|
||||
* Sets the KnpPaginator instance.
|
||||
*/
|
||||
public function setPaginator(PaginatorInterface $paginator): PaginatorAwareInterface
|
||||
{
|
||||
$this->paginator = $paginator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the KnpPaginator instance.
|
||||
*/
|
||||
public function getPaginator(): PaginatorInterface
|
||||
{
|
||||
return $this->paginator;
|
||||
}
|
||||
}
|
16
vendor/knplabs/knp-paginator-bundle/src/Definition/PaginatorAware.php
vendored
Normal file
16
vendor/knplabs/knp-paginator-bundle/src/Definition/PaginatorAware.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\Definition;
|
||||
|
||||
@\trigger_error(sprintf('The %s class is deprecated since knplabs/knp-paginator-bundle 5.x. Use %s instead.', PaginatorAware::class, AbstractPaginatorAware::class), \E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Class PaginatorAware.
|
||||
*
|
||||
* This is a base class that can be extended if you're too lazy to implement PaginatorAwareInterface yourself.
|
||||
*
|
||||
* @deprecated since knplabs/knp-paginator-bundle 5.x
|
||||
*/
|
||||
abstract class PaginatorAware extends AbstractPaginatorAware
|
||||
{
|
||||
}
|
19
vendor/knplabs/knp-paginator-bundle/src/Definition/PaginatorAwareInterface.php
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/src/Definition/PaginatorAwareInterface.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\Definition;
|
||||
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
|
||||
/**
|
||||
* Interface PaginatorAwareInterface.
|
||||
*
|
||||
* PaginatorAwareInterface can be implemented by classes that depend on a KnpPaginator service.
|
||||
* You should avoid this solution: use autowiring instead.
|
||||
*/
|
||||
interface PaginatorAwareInterface
|
||||
{
|
||||
/**
|
||||
* Sets the KnpPaginator instance.
|
||||
*/
|
||||
public function setPaginator(PaginatorInterface $paginator): self;
|
||||
}
|
58
vendor/knplabs/knp-paginator-bundle/src/DependencyInjection/Compiler/PaginatorAwarePass.php
vendored
Normal file
58
vendor/knplabs/knp-paginator-bundle/src/DependencyInjection/Compiler/PaginatorAwarePass.php
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Knp\Bundle\PaginatorBundle\Definition\PaginatorAwareInterface;
|
||||
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Class PaginatorAwarePass.
|
||||
*
|
||||
* This compiler scans for the 'knp_paginator.injectable' tag and injects the Paginator service.
|
||||
*/
|
||||
final class PaginatorAwarePass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const PAGINATOR_AWARE_TAG = 'knp_paginator.injectable';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const PAGINATOR_AWARE_INTERFACE = PaginatorAwareInterface::class;
|
||||
|
||||
/**
|
||||
* Populates all tagged services with the paginator service.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws InvalidDefinitionException
|
||||
*/
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
$defaultAttributes = ['paginator' => 'knp_paginator'];
|
||||
|
||||
foreach ($container->findTaggedServiceIds(self::PAGINATOR_AWARE_TAG) as $id => [$attributes]) {
|
||||
$definition = $container->getDefinition($id);
|
||||
if (null === $class = $definition->getClass()) {
|
||||
throw new \InvalidArgumentException(\sprintf('Service "%s" not found.', $id));
|
||||
}
|
||||
/** @var class-string $class */
|
||||
$refClass = new \ReflectionClass($class);
|
||||
if (!$refClass->implementsInterface(self::PAGINATOR_AWARE_INTERFACE)) {
|
||||
throw new \InvalidArgumentException(\sprintf('Service "%s" must implement interface "%s".', $id, self::PAGINATOR_AWARE_INTERFACE));
|
||||
}
|
||||
|
||||
$attributes = \array_merge($defaultAttributes, $attributes);
|
||||
if (!$container->has($attributes['paginator'])) {
|
||||
throw new InvalidDefinitionException(\sprintf('Paginator service "%s" for tag "%s" on service "%s" could not be found.', $attributes['paginator'], self::PAGINATOR_AWARE_TAG, $id));
|
||||
}
|
||||
|
||||
$definition->addMethodCall('setPaginator', [new Reference($attributes['paginator'])]);
|
||||
$container->setDefinition($id, $definition);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
|
||||
|
||||
final class PaginatorConfigurationPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* Populate the listener service ids.
|
||||
*/
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
// use main symfony dispatcher
|
||||
if (!$container->hasDefinition('event_dispatcher') && !$container->hasAlias('event_dispatcher')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$listeners = $container->findTaggedServiceIds('knp_paginator.listener');
|
||||
$subscribers = $container->findTaggedServiceIds('knp_paginator.subscriber');
|
||||
|
||||
foreach ($listeners as $serviceId => $tags) {
|
||||
@\trigger_error('Using "knp_paginator.listener" tag is deprecated, use "kernel.event_listener" instead.', \E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
foreach ($subscribers as $serviceId => $tags) {
|
||||
@\trigger_error('Using "knp_paginator.subscriber" tag is deprecated, use "kernel.event_subscriber" instead.', \E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (\count($listeners) > 0 || \count($subscribers) > 0) {
|
||||
$pass = new RegisterListenersPass('event_dispatcher', 'knp_paginator.listener', 'knp_paginator.subscriber');
|
||||
$pass->process($container);
|
||||
}
|
||||
}
|
||||
}
|
60
vendor/knplabs/knp-paginator-bundle/src/DependencyInjection/Configuration.php
vendored
Normal file
60
vendor/knplabs/knp-paginator-bundle/src/DependencyInjection/Configuration.php
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\DependencyInjection;
|
||||
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
final class Configuration implements ConfigurationInterface
|
||||
{
|
||||
public function getConfigTreeBuilder(): TreeBuilder
|
||||
{
|
||||
$treeBuilder = new TreeBuilder('knp_paginator');
|
||||
$rootNode = $treeBuilder->getRootNode();
|
||||
|
||||
$rootNode
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->arrayNode('default_options')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->scalarNode('sort_field_name')->defaultValue('sort')->end()
|
||||
->scalarNode('sort_direction_name')->defaultValue('direction')->end()
|
||||
->scalarNode('filter_field_name')->defaultValue('filterField')->end()
|
||||
->scalarNode('filter_value_name')->defaultValue('filterValue')->end()
|
||||
->scalarNode('page_name')->defaultValue('page')->end()
|
||||
->booleanNode('distinct')->defaultTrue()->end()
|
||||
->scalarNode('page_out_of_range')->defaultValue(PaginatorInterface::PAGE_OUT_OF_RANGE_IGNORE)->end()
|
||||
->scalarNode('default_limit')->defaultValue(PaginatorInterface::DEFAULT_LIMIT_VALUE)->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('template')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->scalarNode('pagination')
|
||||
->defaultValue('@KnpPaginator/Pagination/sliding.html.twig')
|
||||
->end()
|
||||
->scalarNode('filtration')
|
||||
->defaultValue('@KnpPaginator/Pagination/filtration.html.twig')
|
||||
->end()
|
||||
->scalarNode('sortable')
|
||||
->defaultValue('@KnpPaginator/Pagination/sortable_link.html.twig')
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('page_range')
|
||||
->defaultValue(5)
|
||||
->end()
|
||||
->integerNode('page_limit')
|
||||
->defaultNull()
|
||||
->end()
|
||||
->booleanNode('convert_exception')
|
||||
->defaultFalse()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
62
vendor/knplabs/knp-paginator-bundle/src/DependencyInjection/KnpPaginatorExtension.php
vendored
Normal file
62
vendor/knplabs/knp-paginator-bundle/src/DependencyInjection/KnpPaginatorExtension.php
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\DependencyInjection;
|
||||
|
||||
use Knp\Bundle\PaginatorBundle\EventListener\ExceptionListener;
|
||||
use Symfony\Component\Config\Definition\Processor;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
|
||||
final class KnpPaginatorExtension extends Extension
|
||||
{
|
||||
/**
|
||||
* Build the extension services.
|
||||
*
|
||||
* @param array<string, array<string, mixed>> $configs
|
||||
*/
|
||||
public function load(array $configs, ContainerBuilder $container): void
|
||||
{
|
||||
$processor = new Processor();
|
||||
|
||||
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../../config'));
|
||||
$loader->load('paginator.xml');
|
||||
|
||||
if ($container->hasParameter('templating.engines')) {
|
||||
/** @var array<string> $engines */
|
||||
$engines = $container->getParameter('templating.engines');
|
||||
if (\in_array('php', $engines, true)) {
|
||||
$loader->load('templating_php.xml');
|
||||
}
|
||||
}
|
||||
|
||||
$configuration = new Configuration();
|
||||
$config = $processor->processConfiguration($configuration, $configs);
|
||||
|
||||
$container->setParameter('knp_paginator.template.pagination', $config['template']['pagination']);
|
||||
$container->setParameter('knp_paginator.template.filtration', $config['template']['filtration']);
|
||||
$container->setParameter('knp_paginator.template.sortable', $config['template']['sortable']);
|
||||
$container->setParameter('knp_paginator.page_range', $config['page_range']);
|
||||
$container->setParameter('knp_paginator.page_limit', $config['page_limit']);
|
||||
|
||||
$paginatorDef = $container->getDefinition('knp_paginator');
|
||||
$paginatorDef->addMethodCall('setDefaultPaginatorOptions', [[
|
||||
'pageParameterName' => $config['default_options']['page_name'],
|
||||
'sortFieldParameterName' => $config['default_options']['sort_field_name'],
|
||||
'sortDirectionParameterName' => $config['default_options']['sort_direction_name'],
|
||||
'filterFieldParameterName' => $config['default_options']['filter_field_name'],
|
||||
'filterValueParameterName' => $config['default_options']['filter_value_name'],
|
||||
'distinct' => $config['default_options']['distinct'],
|
||||
'pageOutOfRange' => $config['default_options']['page_out_of_range'],
|
||||
'defaultLimit' => $config['default_options']['default_limit'],
|
||||
]]);
|
||||
|
||||
if ($config['convert_exception']) {
|
||||
$definition = new Definition(ExceptionListener::class);
|
||||
$definition->addTag('kernel.event_listener', ['event' => 'kernel.exception']);
|
||||
$container->setDefinition(ExceptionListener::class, $definition);
|
||||
}
|
||||
}
|
||||
}
|
21
vendor/knplabs/knp-paginator-bundle/src/EventListener/ExceptionListener.php
vendored
Normal file
21
vendor/knplabs/knp-paginator-bundle/src/EventListener/ExceptionListener.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\EventListener;
|
||||
|
||||
use OutOfRangeException;
|
||||
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Intercept OutOfRangeException and throw http-related exceptions instead.
|
||||
*/
|
||||
final class ExceptionListener
|
||||
{
|
||||
public function onKernelException(ExceptionEvent $event): void
|
||||
{
|
||||
$exception = $event->getThrowable();
|
||||
if ($exception instanceof OutOfRangeException) {
|
||||
$event->setThrowable(new NotFoundHttpException('Not Found.', $exception));
|
||||
}
|
||||
}
|
||||
}
|
205
vendor/knplabs/knp-paginator-bundle/src/Helper/Processor.php
vendored
Normal file
205
vendor/knplabs/knp-paginator-bundle/src/Helper/Processor.php
vendored
Normal file
@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\Helper;
|
||||
|
||||
use Knp\Bundle\PaginatorBundle\Pagination\SlidingPaginationInterface;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Pagination data processor.
|
||||
*
|
||||
* Common data processor for all templating engines
|
||||
*
|
||||
* @author Rafał Wrzeszcz <rafal.wrzeszcz@wrzasq.pl>
|
||||
*/
|
||||
final class Processor
|
||||
{
|
||||
/**
|
||||
* @var UrlGeneratorInterface
|
||||
*/
|
||||
private $router;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
public function __construct(UrlGeneratorInterface $router, TranslatorInterface $translator)
|
||||
{
|
||||
$this->router = $router;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates pagination template data.
|
||||
*
|
||||
* @param SlidingPaginationInterface<mixed> $pagination
|
||||
* @param array<string, mixed> $queryParams
|
||||
* @param array<string, mixed> $viewParams
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function render(SlidingPaginationInterface $pagination, array $queryParams = [], array $viewParams = []): array
|
||||
{
|
||||
$data = $pagination->getPaginationData();
|
||||
|
||||
$data['route'] = $pagination->getRoute();
|
||||
$data['query'] = \array_merge($pagination->getParams(), $queryParams);
|
||||
|
||||
return \array_merge(
|
||||
$pagination->getPaginatorOptions() ?? [], // options given to paginator when paginated
|
||||
$pagination->getCustomParameters() ?? [], // all custom parameters for view
|
||||
$viewParams, // additional custom parameters for view
|
||||
$data // merging base route parameters last, to avoid broke of integrity
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sort url for the field named $title
|
||||
* and identified by $key which consists of
|
||||
* alias and field. $options holds all link
|
||||
* parameters like "alt, class" and so on.
|
||||
*
|
||||
* $key examples: "article.title" or "['article.title', 'article.subtitle']"
|
||||
*
|
||||
* @param SlidingPaginationInterface<mixed> $pagination
|
||||
* @param string|array<string, mixed> $title
|
||||
* @param string|array<string, mixed> $key
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $params
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function sortable(SlidingPaginationInterface $pagination, $title, $key, array $options = [], array $params = []): array
|
||||
{
|
||||
$options = \array_merge([
|
||||
'absolute' => UrlGeneratorInterface::ABSOLUTE_PATH,
|
||||
'translationParameters' => [],
|
||||
'translationDomain' => null,
|
||||
'translationCount' => null,
|
||||
], $options);
|
||||
|
||||
$hasFixedDirection = null !== $pagination->getPaginatorOption('sortDirectionParameterName')
|
||||
&& isset($params[$pagination->getPaginatorOption('sortDirectionParameterName')])
|
||||
;
|
||||
|
||||
$params = \array_merge($pagination->getParams(), $params);
|
||||
|
||||
$direction = $options['defaultDirection'] ?? 'asc';
|
||||
if (null !== $pagination->getPaginatorOption('sortDirectionParameterName')) {
|
||||
if (isset($params[$pagination->getPaginatorOption('sortDirectionParameterName')])) {
|
||||
$direction = $params[$pagination->getPaginatorOption('sortDirectionParameterName')];
|
||||
} elseif (isset($options[$pagination->getPaginatorOption('sortDirectionParameterName')])) {
|
||||
$direction = $options[$pagination->getPaginatorOption('sortDirectionParameterName')];
|
||||
}
|
||||
}
|
||||
|
||||
$sorted = $pagination->isSorted($key, $params);
|
||||
|
||||
if ($sorted) {
|
||||
if (!$hasFixedDirection) {
|
||||
$direction = 'asc' === \strtolower($direction) ? 'desc' : 'asc';
|
||||
}
|
||||
|
||||
$class = 'asc' === $direction ? 'desc' : 'asc';
|
||||
} else {
|
||||
$class = 'sortable';
|
||||
}
|
||||
|
||||
if (isset($options['class'])) {
|
||||
$options['class'] .= ' '.$class;
|
||||
} else {
|
||||
$options['class'] = $class;
|
||||
}
|
||||
|
||||
if (\is_array($title) && \array_key_exists($direction, $title)) {
|
||||
$title = $title[$direction];
|
||||
}
|
||||
|
||||
if (\is_array($key)) {
|
||||
$key = \implode('+', $key);
|
||||
}
|
||||
|
||||
$params = \array_merge(
|
||||
$params,
|
||||
[
|
||||
$pagination->getPaginatorOption('sortFieldParameterName') => $key,
|
||||
$pagination->getPaginatorOption('sortDirectionParameterName') => $direction,
|
||||
$pagination->getPaginatorOption('pageParameterName') => 1, // reset to 1 on sort
|
||||
]
|
||||
);
|
||||
|
||||
$options['href'] = $this->router->generate($pagination->getRoute(), $params, $options['absolute']);
|
||||
|
||||
if (null !== $options['translationDomain']) {
|
||||
if (null === $options['translationCount']) {
|
||||
$translationParameters = $options['translationParameters'];
|
||||
} else {
|
||||
$translationParameters = $options['translationParameters'] + ['%count%' => $options['translationCount']];
|
||||
}
|
||||
$title = $this->translator->trans($title, $translationParameters, $options['translationDomain']);
|
||||
}
|
||||
|
||||
if (!isset($options['title'])) {
|
||||
$options['title'] = $title;
|
||||
}
|
||||
|
||||
unset($options['absolute'], $options['translationParameters'], $options['translationDomain'], $options['translationCount']);
|
||||
|
||||
return \array_merge(
|
||||
$pagination->getPaginatorOptions() ?? [],
|
||||
$pagination->getCustomParameters() ?? [],
|
||||
\compact('options', 'title', 'direction', 'sorted', 'key')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a filter url for the field named $title
|
||||
* and identified by $key which consists of
|
||||
* alias and field. $options holds all link
|
||||
* parameters like "alt, class" and so on.
|
||||
*
|
||||
* $key example: "article.title"
|
||||
*
|
||||
* @param SlidingPaginationInterface<mixed> $pagination
|
||||
* @param array<string, mixed> $fields
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $params
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function filter(SlidingPaginationInterface $pagination, array $fields, array $options = [], array $params = []): array
|
||||
{
|
||||
$options = \array_merge([
|
||||
'absolute' => UrlGeneratorInterface::ABSOLUTE_PATH,
|
||||
'translationParameters' => [],
|
||||
'translationDomain' => null,
|
||||
'button' => 'Filter',
|
||||
], $options);
|
||||
|
||||
$params = \array_merge($pagination->getParams(), $params);
|
||||
$params[$pagination->getPaginatorOption('pageParameterName')] = 1; // reset to 1 on filter
|
||||
|
||||
$filterFieldName = $pagination->getPaginatorOption('filterFieldParameterName');
|
||||
$filterValueName = $pagination->getPaginatorOption('filterValueParameterName');
|
||||
|
||||
$selectedField = $params[$filterFieldName] ?? null;
|
||||
$selectedValue = $params[$filterValueName] ?? null;
|
||||
|
||||
$action = $this->router->generate($pagination->getRoute(), $params, $options['absolute']);
|
||||
|
||||
foreach ($fields as $field => $title) {
|
||||
$fields[$field] = $this->translator->trans($title, $options['translationParameters'], $options['translationDomain']);
|
||||
}
|
||||
$options['button'] = $this->translator->trans($options['button'], $options['translationParameters'], $options['translationDomain']);
|
||||
|
||||
unset($options['absolute'], $options['translationDomain'], $options['translationParameters']);
|
||||
|
||||
return \array_merge(
|
||||
$pagination->getPaginatorOptions() ?? [],
|
||||
$pagination->getCustomParameters() ?? [],
|
||||
\compact('fields', 'action', 'filterFieldName', 'filterValueName', 'selectedField', 'selectedValue', 'options')
|
||||
);
|
||||
}
|
||||
}
|
31
vendor/knplabs/knp-paginator-bundle/src/KnpPaginatorBundle.php
vendored
Normal file
31
vendor/knplabs/knp-paginator-bundle/src/KnpPaginatorBundle.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* (c) Thibault Duplessis <thibault.duplessis@gmail.com>.
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle;
|
||||
|
||||
use Knp\Bundle\PaginatorBundle\DependencyInjection\Compiler\PaginatorAwarePass;
|
||||
use Knp\Bundle\PaginatorBundle\DependencyInjection\Compiler\PaginatorConfigurationPass;
|
||||
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
final class KnpPaginatorBundle extends Bundle
|
||||
{
|
||||
public function build(ContainerBuilder $container): void
|
||||
{
|
||||
parent::build($container);
|
||||
$container->addCompilerPass(new PaginatorConfigurationPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
$container->addCompilerPass(new PaginatorAwarePass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
}
|
||||
|
||||
public function getPath(): string
|
||||
{
|
||||
return \dirname(__DIR__);
|
||||
}
|
||||
}
|
245
vendor/knplabs/knp-paginator-bundle/src/Pagination/SlidingPagination.php
vendored
Normal file
245
vendor/knplabs/knp-paginator-bundle/src/Pagination/SlidingPagination.php
vendored
Normal file
@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\Pagination;
|
||||
|
||||
use Knp\Component\Pager\Pagination\AbstractPagination;
|
||||
|
||||
final class SlidingPagination extends AbstractPagination implements SlidingPaginationInterface
|
||||
{
|
||||
/** @var string|null */
|
||||
private $route;
|
||||
|
||||
/** @var array<string, mixed> */
|
||||
private $params;
|
||||
|
||||
/** @var int */
|
||||
private $pageRange = 5;
|
||||
|
||||
/** @var int|null */
|
||||
private $pageLimit = null;
|
||||
|
||||
/** @var string|null */
|
||||
private $template;
|
||||
|
||||
/** @var string|null */
|
||||
private $sortableTemplate;
|
||||
|
||||
/** @var string|null */
|
||||
private $filtrationTemplate;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $params
|
||||
*/
|
||||
public function __construct(array $params)
|
||||
{
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
public function setUsedRoute(?string $route): void
|
||||
{
|
||||
$this->route = $route;
|
||||
}
|
||||
|
||||
public function getRoute(): ?string
|
||||
{
|
||||
return $this->route;
|
||||
}
|
||||
|
||||
public function setSortableTemplate(string $template): void
|
||||
{
|
||||
$this->sortableTemplate = $template;
|
||||
}
|
||||
|
||||
public function getSortableTemplate(): ?string
|
||||
{
|
||||
return $this->sortableTemplate;
|
||||
}
|
||||
|
||||
public function setFiltrationTemplate(string $template): void
|
||||
{
|
||||
$this->filtrationTemplate = $template;
|
||||
}
|
||||
|
||||
public function getFiltrationTemplate(): ?string
|
||||
{
|
||||
return $this->filtrationTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setParam(string $name, $value): void
|
||||
{
|
||||
$this->params[$name] = $value;
|
||||
}
|
||||
|
||||
public function getParams(): array
|
||||
{
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
public function setTemplate(string $template): void
|
||||
{
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
public function getTemplate(): ?string
|
||||
{
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
public function setPageRange(int $range): void
|
||||
{
|
||||
$this->pageRange = \abs($range);
|
||||
}
|
||||
|
||||
public function setPageLimit(?int $limit): void
|
||||
{
|
||||
$this->pageLimit = $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get url query with all parameters.
|
||||
*
|
||||
* @param array<string, mixed> $additionalQueryParams
|
||||
*
|
||||
* @return array<string, mixed> - list of query parameters
|
||||
*/
|
||||
public function getQuery(array $additionalQueryParams = []): array
|
||||
{
|
||||
return \array_merge($this->params, $additionalQueryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[]|string|null $key
|
||||
* @param array<string, mixed> $params
|
||||
*/
|
||||
public function isSorted($key = null, array $params = []): bool
|
||||
{
|
||||
$params = \array_merge($this->params, $params);
|
||||
|
||||
if (null === $key) {
|
||||
return isset($params[$this->getPaginatorOption('sortFieldParameterName')]);
|
||||
}
|
||||
|
||||
if (\is_array($key)) {
|
||||
$key = \implode('+', $key);
|
||||
}
|
||||
|
||||
return isset($params[$this->getPaginatorOption('sortFieldParameterName')]) && $params[$this->getPaginatorOption('sortFieldParameterName')] === $key;
|
||||
}
|
||||
|
||||
public function getPage(): ?int
|
||||
{
|
||||
return $this->params[$this->getPaginatorOption('pageParameterName')] ?? null;
|
||||
}
|
||||
|
||||
public function getSort(): ?string
|
||||
{
|
||||
return $this->params[$this->getPaginatorOption('sortFieldParameterName')] ?? null;
|
||||
}
|
||||
|
||||
public function getDirection(): ?string
|
||||
{
|
||||
return $this->params[$this->getPaginatorOption('sortDirectionParameterName')] ?? null;
|
||||
}
|
||||
|
||||
public function getPaginationData(): array
|
||||
{
|
||||
$pageCount = $this->getPageCount();
|
||||
$current = $this->currentPageNumber;
|
||||
|
||||
if ($pageCount < $current) {
|
||||
$this->currentPageNumber = $current = $pageCount;
|
||||
}
|
||||
|
||||
if ($this->pageRange > $pageCount) {
|
||||
$this->pageRange = $pageCount;
|
||||
}
|
||||
|
||||
$delta = \ceil($this->pageRange / 2);
|
||||
|
||||
if ($current - $delta > $pageCount - $this->pageRange) {
|
||||
$pages = \range($pageCount - $this->pageRange + 1, $pageCount);
|
||||
} else {
|
||||
if ($current - $delta < 0) {
|
||||
$delta = $current;
|
||||
}
|
||||
|
||||
$offset = $current - $delta;
|
||||
$pages = \range($offset + 1, $offset + $this->pageRange);
|
||||
}
|
||||
|
||||
$proximity = \floor($this->pageRange / 2);
|
||||
|
||||
$startPage = $current - $proximity;
|
||||
$endPage = $current + $proximity;
|
||||
|
||||
if ($startPage < 1) {
|
||||
$endPage = \min($endPage + (1 - $startPage), $pageCount);
|
||||
$startPage = 1;
|
||||
}
|
||||
|
||||
if ($endPage > $pageCount) {
|
||||
$startPage = \max($startPage - ($endPage - $pageCount), 1);
|
||||
$endPage = $pageCount;
|
||||
}
|
||||
|
||||
$viewData = [
|
||||
'last' => $pageCount,
|
||||
'current' => $current,
|
||||
'numItemsPerPage' => $this->numItemsPerPage,
|
||||
'first' => 1,
|
||||
'pageCount' => $pageCount,
|
||||
'totalCount' => $this->totalCount,
|
||||
'pageRange' => $this->pageRange,
|
||||
'startPage' => $startPage,
|
||||
'endPage' => $endPage,
|
||||
];
|
||||
|
||||
if ($current > 1) {
|
||||
$viewData['previous'] = $current - 1;
|
||||
}
|
||||
|
||||
if ($current < $pageCount) {
|
||||
$viewData['next'] = $current + 1;
|
||||
}
|
||||
|
||||
$viewData['pagesInRange'] = $pages;
|
||||
$viewData['firstPageInRange'] = \min($pages);
|
||||
$viewData['lastPageInRange'] = \max($pages);
|
||||
|
||||
if (null !== $this->getItems()) {
|
||||
$viewData['currentItemCount'] = $this->count();
|
||||
$viewData['firstItemNumber'] = 0;
|
||||
$viewData['lastItemNumber'] = 0;
|
||||
if ($viewData['totalCount'] > 0) {
|
||||
$viewData['firstItemNumber'] = (($current - 1) * $this->numItemsPerPage) + 1;
|
||||
$viewData['lastItemNumber'] = $viewData['firstItemNumber'] + $viewData['currentItemCount'] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $viewData;
|
||||
}
|
||||
|
||||
public function getPageCount(): int
|
||||
{
|
||||
$count = (int) \ceil($this->totalCount / $this->numItemsPerPage);
|
||||
|
||||
if (null !== $this->pageLimit) {
|
||||
return \min($count, $this->pageLimit);
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
public function getPaginatorOptions(): ?array
|
||||
{
|
||||
return $this->paginatorOptions;
|
||||
}
|
||||
|
||||
public function getCustomParameters(): ?array
|
||||
{
|
||||
return $this->customParameters;
|
||||
}
|
||||
}
|
36
vendor/knplabs/knp-paginator-bundle/src/Pagination/SlidingPaginationInterface.php
vendored
Normal file
36
vendor/knplabs/knp-paginator-bundle/src/Pagination/SlidingPaginationInterface.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\Pagination;
|
||||
|
||||
use Knp\Component\Pager\Pagination\PaginationInterface;
|
||||
|
||||
interface SlidingPaginationInterface extends PaginationInterface
|
||||
{
|
||||
public function getRoute(): ?string;
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getParams(): array;
|
||||
|
||||
/**
|
||||
* @param string[]|string|null $key
|
||||
* @param array<string, mixed> $params
|
||||
*/
|
||||
public function isSorted($key = null, array $params = []): bool;
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getPaginationData(): array;
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getPaginatorOptions(): ?array;
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getCustomParameters(): ?array;
|
||||
}
|
96
vendor/knplabs/knp-paginator-bundle/src/Subscriber/SlidingPaginationSubscriber.php
vendored
Normal file
96
vendor/knplabs/knp-paginator-bundle/src/Subscriber/SlidingPaginationSubscriber.php
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\Subscriber;
|
||||
|
||||
use Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination;
|
||||
use Knp\Component\Pager\Event\PaginationEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
final class SlidingPaginationSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $route;
|
||||
|
||||
/** @var array<string, mixed> */
|
||||
private $params = [];
|
||||
|
||||
/** @var array<string, mixed> */
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function __construct(array $options)
|
||||
{
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
public function onKernelRequest(RequestEvent $event): void
|
||||
{
|
||||
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
|
||||
$this->route = $request->attributes->get('_route');
|
||||
$this->params = \array_replace($request->query->all(), $request->attributes->get('_route_params', []));
|
||||
foreach ($this->params as $key => $param) {
|
||||
if (\strpos($key, '_') === 0) {
|
||||
unset($this->params[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function pagination(PaginationEvent $event): void
|
||||
{
|
||||
// default sort field and order
|
||||
$eventOptions = $event->options;
|
||||
|
||||
if (isset($eventOptions['defaultSortFieldName']) && !isset($this->params[$eventOptions['sortFieldParameterName']])) {
|
||||
$this->params[$eventOptions['sortFieldParameterName']] = $eventOptions['defaultSortFieldName'];
|
||||
}
|
||||
|
||||
if (isset($eventOptions['defaultSortDirection']) && !isset($this->params[$eventOptions['sortDirectionParameterName']])) {
|
||||
$this->params[$eventOptions['sortDirectionParameterName']] = $eventOptions['defaultSortDirection'];
|
||||
}
|
||||
|
||||
// remove default sort params from pagination links
|
||||
if (isset($eventOptions['removeDefaultSortParams']) && true === $eventOptions['removeDefaultSortParams']) {
|
||||
$defaultSortFieldName = $eventOptions['defaultSortFieldName'];
|
||||
$sortFieldParameterName = $this->params[$eventOptions['sortFieldParameterName']];
|
||||
$isFieldEqual = $defaultSortFieldName === $sortFieldParameterName;
|
||||
$defaultSortDirection = $eventOptions['defaultSortDirection'];
|
||||
$sortDirectionParameterName = $this->params[$eventOptions['sortDirectionParameterName']];
|
||||
$isDirectionEqual = $defaultSortDirection === $sortDirectionParameterName;
|
||||
|
||||
if (isset($defaultSortFieldName, $sortFieldParameterName, $defaultSortDirection, $sortDirectionParameterName) && $isFieldEqual && $isDirectionEqual) {
|
||||
unset($this->params[$eventOptions['sortFieldParameterName']], $this->params[$eventOptions['sortDirectionParameterName']]);
|
||||
}
|
||||
}
|
||||
|
||||
$pagination = new SlidingPagination($this->params);
|
||||
|
||||
$pagination->setUsedRoute($this->route);
|
||||
$pagination->setTemplate($this->options['defaultPaginationTemplate']);
|
||||
$pagination->setSortableTemplate($this->options['defaultSortableTemplate']);
|
||||
$pagination->setFiltrationTemplate($this->options['defaultFiltrationTemplate']);
|
||||
$pagination->setPageRange($this->options['defaultPageRange']);
|
||||
$pagination->setPageLimit($this->options['defaultPageLimit']);
|
||||
|
||||
$event->setPagination($pagination);
|
||||
$event->stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<int, int|string>>
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'knp_pager.pagination' => ['pagination', 1],
|
||||
];
|
||||
}
|
||||
}
|
99
vendor/knplabs/knp-paginator-bundle/src/Templating/PaginationHelper.php
vendored
Normal file
99
vendor/knplabs/knp-paginator-bundle/src/Templating/PaginationHelper.php
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\Templating;
|
||||
|
||||
use Knp\Bundle\PaginatorBundle\Helper\Processor;
|
||||
use Knp\Bundle\PaginatorBundle\Pagination\SlidingPaginationInterface;
|
||||
use Symfony\Component\Templating\Helper\Helper;
|
||||
use Symfony\Component\Templating\PhpEngine;
|
||||
|
||||
/**
|
||||
* Pagination PHP helper.
|
||||
*
|
||||
* Basically provides access to KnpPaginator from PHP templates
|
||||
*
|
||||
* @author Rafa³ Wrzeszcz <rafal.wrzeszcz@wrzasq.pl>
|
||||
*/
|
||||
final class PaginationHelper extends Helper
|
||||
{
|
||||
/**
|
||||
* @var PhpEngine
|
||||
*/
|
||||
protected $templating;
|
||||
|
||||
/**
|
||||
* @var Processor
|
||||
*/
|
||||
protected $processor;
|
||||
|
||||
public function __construct(Processor $processor, PhpEngine $templating)
|
||||
{
|
||||
$this->processor = $processor;
|
||||
$this->templating = $templating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the pagination template.
|
||||
*
|
||||
* @param \Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination<mixed> $pagination
|
||||
* @param array<string, mixed> $queryParams
|
||||
* @param array<string, mixed> $viewParams
|
||||
*/
|
||||
public function render(SlidingPaginationInterface $pagination, ?string $template = null, array $queryParams = [], array $viewParams = []): string
|
||||
{
|
||||
return $this->templating->render(
|
||||
$template ?: $pagination->getTemplate(),
|
||||
$this->processor->render($pagination, $queryParams, $viewParams)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sort url for the field named $title
|
||||
* and identified by $key which consists of
|
||||
* alias and field. $options holds all link
|
||||
* parameters like "alt, class" and so on.
|
||||
*
|
||||
* $key example: "article.title"
|
||||
*
|
||||
* @param \Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination<mixed> $pagination
|
||||
* @param string|array<string, mixed> $key
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $params
|
||||
*/
|
||||
public function sortable(SlidingPaginationInterface $pagination, string $title, $key, array $options = [], array $params = [], ?string $template = null): string
|
||||
{
|
||||
return $this->templating->render(
|
||||
$template ?: $pagination->getSortableTemplate(),
|
||||
$this->processor->sortable($pagination, $title, $key, $options, $params)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a filter url for the field named $title
|
||||
* and identified by $key which consists of
|
||||
* alias and field. $options holds all link
|
||||
* parameters like "alt, class" and so on.
|
||||
*
|
||||
* $key example: "article.title"
|
||||
*
|
||||
* @param \Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination<mixed> $pagination
|
||||
* @param array<string, mixed> $fields
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $params
|
||||
*/
|
||||
public function filter(SlidingPaginationInterface $pagination, array $fields, array $options = [], array $params = [], ?string $template = null): string
|
||||
{
|
||||
return $this->templating->render(
|
||||
$template ?: $pagination->getFiltrationTemplate(),
|
||||
$this->processor->filter($pagination, $fields, $options, $params)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get helper name.
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'knp_pagination';
|
||||
}
|
||||
}
|
88
vendor/knplabs/knp-paginator-bundle/src/Twig/Extension/PaginationExtension.php
vendored
Normal file
88
vendor/knplabs/knp-paginator-bundle/src/Twig/Extension/PaginationExtension.php
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Knp\Bundle\PaginatorBundle\Twig\Extension;
|
||||
|
||||
use Knp\Bundle\PaginatorBundle\Helper\Processor;
|
||||
use Knp\Bundle\PaginatorBundle\Pagination\SlidingPaginationInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
final class PaginationExtension extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* @var Processor
|
||||
*/
|
||||
private $processor;
|
||||
|
||||
public function __construct(Processor $processor)
|
||||
{
|
||||
$this->processor = $processor;
|
||||
}
|
||||
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('knp_pagination_render', [$this, 'render'], ['is_safe' => ['html'], 'needs_environment' => true]),
|
||||
new TwigFunction('knp_pagination_sortable', [$this, 'sortable'], ['is_safe' => ['html'], 'needs_environment' => true]),
|
||||
new TwigFunction('knp_pagination_filter', [$this, 'filter'], ['is_safe' => ['html'], 'needs_environment' => true]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the pagination template.
|
||||
*
|
||||
* @param \Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination<mixed> $pagination
|
||||
* @param array<string, mixed> $queryParams
|
||||
* @param array<string, mixed> $viewParams
|
||||
*/
|
||||
public function render(Environment $env, SlidingPaginationInterface $pagination, ?string $template = null, ?array $queryParams = [], ?array $viewParams = []): string
|
||||
{
|
||||
return $env->render(
|
||||
$template ?: $pagination->getTemplate(),
|
||||
$this->processor->render($pagination, $queryParams ?? [], $viewParams ?? [])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sort url for the field named $title
|
||||
* and identified by $key which consists of
|
||||
* alias and field. $options holds all link
|
||||
* parameters like "alt, class" and so on.
|
||||
*
|
||||
* $key example: "article.title"
|
||||
*
|
||||
* @param \Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination<mixed> $pagination
|
||||
* @param string|array<string, mixed> $key
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed> $params
|
||||
*/
|
||||
public function sortable(Environment $env, SlidingPaginationInterface $pagination, string $title, $key, array $options = [], array $params = [], ?string $template = null): string
|
||||
{
|
||||
return $env->render(
|
||||
$template ?: $pagination->getSortableTemplate(),
|
||||
$this->processor->sortable($pagination, $title, $key, $options, $params)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a filter url for the field named $title
|
||||
* and identified by $key which consists of
|
||||
* alias and field. $options holds all link
|
||||
* parameters like "alt, class" and so on.
|
||||
*
|
||||
* $key example: "article.title"
|
||||
*
|
||||
* @param \Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination<mixed> $pagination
|
||||
* @param array<string, mixed> $fields
|
||||
* @param array<string, mixed> $options
|
||||
* @param array<string, mixed>|null $params
|
||||
*/
|
||||
public function filter(Environment $env, SlidingPaginationInterface $pagination, array $fields, ?array $options = [], ?array $params = [], ?string $template = null): string
|
||||
{
|
||||
return $env->render(
|
||||
$template ?: $pagination->getFiltrationTemplate(),
|
||||
$this->processor->filter($pagination, $fields, $options ?? [], $params ?? [])
|
||||
);
|
||||
}
|
||||
}
|
23
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bootstrap_v5_bi_sortable_link.html.twig
vendored
Normal file
23
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bootstrap_v5_bi_sortable_link.html.twig
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Bootstrap v5 with Bootstrap Icons Sorting control implementation.
|
||||
*
|
||||
* Install Icon Set: https://icons.getbootstrap.com/#install
|
||||
* Overview: https://icons.getbootstrap.com/
|
||||
*/
|
||||
#}
|
||||
<a{% for attr, value in options %} {{ attr }}="{{ value }}"{% endfor %}>
|
||||
<span class="float-end">
|
||||
{% if sorted %}
|
||||
{% if direction == 'desc' %}
|
||||
<i class="bi bi-sort-down"></i>
|
||||
{% else %}
|
||||
<i class="bi bi-sort-up"></i>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<i class="bi bi-filter-left"></i>
|
||||
{% endif %}
|
||||
</span>
|
||||
{{ title }}
|
||||
</a>
|
20
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bootstrap_v5_fa_sortable_link.html.twig
vendored
Normal file
20
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bootstrap_v5_fa_sortable_link.html.twig
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Bootstrap v5 with Font Awesome Sorting control implementation.
|
||||
*/
|
||||
#}
|
||||
<a{% for attr, value in options %} {{ attr }}="{{ value }}"{% endfor %}>
|
||||
<span class="float-end">
|
||||
{% if sorted %}
|
||||
{% if direction == 'desc' %}
|
||||
<i class="fa fa-sort-down"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-sort-up"></i>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<i class="fa fa-sort"></i>
|
||||
{% endif %}
|
||||
</span>
|
||||
{{ title }}
|
||||
</a>
|
24
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bootstrap_v5_filtration.html.twig
vendored
Normal file
24
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bootstrap_v5_filtration.html.twig
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Bootstrap v5 Filter control implementation.
|
||||
*
|
||||
* View that can be used with the filter module
|
||||
*/
|
||||
#}
|
||||
<form method="get" action="{{ action }}" enctype="application/x-www-form-urlencoded">
|
||||
<div class="input-group mb-3">
|
||||
{% if fields|length > 1 %}
|
||||
<select class="form-select" name="{{ filterFieldName }}">
|
||||
{% for field, label in fields %}
|
||||
<option value="{{ field }}"{% if selectedField == field %} selected="selected"{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% else %}
|
||||
<input type="hidden" name="{{ filterFieldName }}" value="{{ fields|keys|first }}"/>
|
||||
{% endif %}
|
||||
<input class="form-control" type="search" value="{{ selectedValue }}" name="{{ filterValueName }}"
|
||||
placeholder="{{ 'filter_searchword'|trans({}, 'KnpPaginatorBundle') }}"/>
|
||||
<button class="btn btn-primary">{{ options.button }}</button>
|
||||
</div>
|
||||
</form>
|
23
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bootstrap_v5_md_sortable_link.html.twig
vendored
Normal file
23
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bootstrap_v5_md_sortable_link.html.twig
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Bootstrap v5 with Material Design Icons Sorting control implementation.
|
||||
*
|
||||
* Install Icon Set: https://google.github.io/material-design-icons/
|
||||
* Overview: https://material.io/resources/icons/?style=baseline
|
||||
*/
|
||||
#}
|
||||
<a{% for attr, value in options %} {{ attr }}="{{ value }}"{% endfor %}>
|
||||
<span class="float-end">
|
||||
{% if sorted %}
|
||||
{% if direction == 'desc' %}
|
||||
<i class="material-icons">expand_more</i>
|
||||
{% else %}
|
||||
<i class="material-icons">expand_less</i>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<i class="material-icons">unfold_more</i>
|
||||
{% endif %}
|
||||
</span>
|
||||
{{ title }}
|
||||
</a>
|
11
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bootstrap_v5_pagination.html.twig
vendored
Normal file
11
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bootstrap_v5_pagination.html.twig
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Bootstrap v5 Sliding pagination control implementation.
|
||||
*
|
||||
* View that can be used with the pagination module
|
||||
* from the Bootstrap CSS Framework
|
||||
* https://getbootstrap.com/docs/5.0/components/pagination/
|
||||
*/
|
||||
#}
|
||||
{% extends '@KnpPaginator/Pagination/twitter_bootstrap_v4_pagination.html.twig' %}
|
69
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bulma_pagination.html.twig
vendored
Normal file
69
vendor/knplabs/knp-paginator-bundle/templates/Pagination/bulma_pagination.html.twig
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
{# bulma Sliding pagination control implementation #}
|
||||
|
||||
{% set position = position|default('left') %}
|
||||
{% set rounded = rounded|default(false) %}
|
||||
{% set size = size|default(null) %}
|
||||
|
||||
{% set classes = ['pagination'] %}
|
||||
|
||||
{% if position != 'left' %}{% set classes = classes|merge(['is-' ~ position]) %}{% endif %}
|
||||
{% if rounded %}{% set classes = classes|merge(['is-rounded']) %}{% endif %}
|
||||
{% if size != null %}{% set classes = classes|merge(['is-' ~ size]) %}{% endif %}
|
||||
|
||||
{% if pageCount > 1 %}
|
||||
<nav class="{{ classes|join(' ') }}" role="navigation" aria-label="pagination">
|
||||
{% if previous is defined %}
|
||||
<a rel="prev" class="pagination-previous" href="{{ path(route, query|merge({(pageParameterName): previous})) }}">{{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}</a>
|
||||
{% else %}
|
||||
<a class="pagination-previous" disabled>{{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}</a>
|
||||
{% endif %}
|
||||
|
||||
{% if next is defined %}
|
||||
<a rel="next" class="pagination-next" href="{{ path(route, query|merge({(pageParameterName): next})) }}">{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }}</a>
|
||||
{% else %}
|
||||
<a class="pagination-next" disabled>{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }}</a>
|
||||
{% endif %}
|
||||
|
||||
<ul class="pagination-list">
|
||||
<li>
|
||||
{% if current == first %}
|
||||
<a class="pagination-link is-current" aria-label="Page {{ current }}" aria-current="page" href="{{ path(route, query|merge({(pageParameterName): first})) }}">1</a>
|
||||
{% else %}
|
||||
<a class="pagination-link" href="{{ path(route, query|merge({(pageParameterName): first})) }}">1</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
|
||||
{% if pagesInRange[0] - first >= 2 %}
|
||||
<li>
|
||||
<span class="pagination-ellipsis">…</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if first != page and page != last %}
|
||||
<li>
|
||||
{% if page == current %}
|
||||
<a class="pagination-link is-current" aria-label="Page {{ current }}" aria-current="page" href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>
|
||||
{% else %}
|
||||
<a class="pagination-link" aria-label="Goto page {{ page }}" href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if last - pagesInRange[pagesInRange|length - 1] >= 2 %}
|
||||
<li>
|
||||
<span class="pagination-ellipsis">…</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li>
|
||||
{% if current == last %}
|
||||
<a class="pagination-link is-current" aria-label="Page {{ current }}" aria-current="page" href="{{ path(route, query|merge({(pageParameterName): last})) }}">{{ last }}</a>
|
||||
{% else %}
|
||||
<a class="pagination-link" href="{{ path(route, query|merge({(pageParameterName): last})) }}">{{ last }}</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
17
vendor/knplabs/knp-paginator-bundle/templates/Pagination/filtration.html.twig
vendored
Normal file
17
vendor/knplabs/knp-paginator-bundle/templates/Pagination/filtration.html.twig
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<form method="get" action="{{ action }}" enctype="application/x-www-form-urlencoded">
|
||||
|
||||
{% if fields|length > 1 %}
|
||||
<select name="{{ filterFieldName }}">
|
||||
{% for field, label in fields %}
|
||||
<option value="{{ field }}"{% if selectedField == field %} selected="selected"{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% else %}
|
||||
<input type="hidden" name="{{ filterFieldName }}" value="{{ fields|keys|first }}" />
|
||||
{% endif %}
|
||||
|
||||
<input type="text" value="{{ selectedValue }}" name="{{ filterValueName }}" />
|
||||
|
||||
<button>{{ options.button }}</button>
|
||||
|
||||
</form>
|
97
vendor/knplabs/knp-paginator-bundle/templates/Pagination/foundation_v5_pagination.html.twig
vendored
Normal file
97
vendor/knplabs/knp-paginator-bundle/templates/Pagination/foundation_v5_pagination.html.twig
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Foundation 5 Sliding pagination control implementation.
|
||||
*
|
||||
* View that can be used with the pagination module
|
||||
* from the Foundation 5 CSS Toolkit
|
||||
* https://get.foundation/sites/docs-v5/components/pagination.html
|
||||
*
|
||||
* @author Vincent Loy <vincent.loy1@gmail.com>
|
||||
*
|
||||
* This view have been ported from twitter bootstrap v3 pagination control implementation
|
||||
* from:
|
||||
* @author Pablo Díez <pablodip@gmail.com>
|
||||
* @author Jan Sorgalla <jsorgalla@gmail.com>
|
||||
* @author Artem Ponomarenko <imenem@inbox.ru>
|
||||
* @author Artem Zabelin <artjomzabelin@gmail.com>
|
||||
*/
|
||||
#}
|
||||
{% if pageCount > 1 %}
|
||||
<ul class="pagination">
|
||||
{% if previous is defined %}
|
||||
<li class="arrow">
|
||||
<a rel="prev" href="{{ path(route, query|merge({(pageParameterName): previous})) }}">« {{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="arrow unavailable">
|
||||
<a>
|
||||
« {{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if startPage > 1 %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): 1})) }}">1</a>
|
||||
</li>
|
||||
{% if startPage == 3 %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): 2})) }}">2</a>
|
||||
</li>
|
||||
{% elseif startPage != 2 %}
|
||||
<li class="unavailable">
|
||||
<a>…</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if page != current %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): page})) }}">
|
||||
{{ page }}
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="current">
|
||||
<a>{{ page }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% if pageCount > endPage %}
|
||||
{% if pageCount > (endPage + 1) %}
|
||||
{% if pageCount > (endPage + 2) %}
|
||||
<li class="unavailable">
|
||||
<a>…</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): (pageCount - 1)})) }}">
|
||||
{{ pageCount -1 }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): pageCount})) }}">{{ pageCount }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if next is defined %}
|
||||
<li class="arrow">
|
||||
<a rel="next" href="{{ path(route, query|merge({(pageParameterName): next})) }}">
|
||||
{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }} »
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="arrow unavailable">
|
||||
<a>
|
||||
{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }} »
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endif %}
|
74
vendor/knplabs/knp-paginator-bundle/templates/Pagination/foundation_v6_pagination.html.twig
vendored
Normal file
74
vendor/knplabs/knp-paginator-bundle/templates/Pagination/foundation_v6_pagination.html.twig
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
{% if pageCount > 1 %}
|
||||
<nav aria-label="Pagination">
|
||||
{% set classAlign = (align is defined) ? " text-#{align}" : '' %}
|
||||
<ul class="pagination{{ classAlign }}">
|
||||
|
||||
{% if previous is defined %}
|
||||
<li class="pagination-previous">
|
||||
<a rel="prev" href="{{ path(route, query|merge({(pageParameterName): previous})) }}">
|
||||
{{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="pagination-previous disabled">
|
||||
{{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if startPage > 1 %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): 1})) }}">1</a>
|
||||
</li>
|
||||
{% if startPage == 3 %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): 2})) }}">2</a>
|
||||
</li>
|
||||
{% elseif startPage != 2 %}
|
||||
<li class="ellipsis"></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if page != current %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): page})) }}">
|
||||
{{ page }}
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="current">{{ page }}</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if pageCount > endPage %}
|
||||
{% if pageCount > (endPage + 1) %}
|
||||
{% if pageCount > (endPage + 2) %}
|
||||
<li class="ellipsis"></li>
|
||||
{% else %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): (pageCount - 1)})) }}">
|
||||
{{ pageCount -1 }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): pageCount})) }}">{{ pageCount }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if next is defined %}
|
||||
<li class="pagination-next">
|
||||
<a rel="next" href="{{ path(route, query|merge({(pageParameterName): next})) }}">
|
||||
{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }}
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="pagination-next disabled">
|
||||
{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
83
vendor/knplabs/knp-paginator-bundle/templates/Pagination/materialize_pagination.html.twig
vendored
Normal file
83
vendor/knplabs/knp-paginator-bundle/templates/Pagination/materialize_pagination.html.twig
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Materialize pagination control implementation.
|
||||
*
|
||||
* View that can be used with the pagination module
|
||||
* from the Materialize CSS
|
||||
* https://materializecss.com/pagination.html
|
||||
*
|
||||
* @author Leonardo Bressan Motyczka <leomoty@gmail.com>
|
||||
*/
|
||||
#}
|
||||
{% if pageCount > 1 %}
|
||||
<ul class="pagination">
|
||||
{% if first is defined and current != first %}
|
||||
<li class="waves-effect">
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): first})) }}">
|
||||
<i class="material-icons">first_page</i>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="disabled">
|
||||
<a href="#!">
|
||||
<i class="material-icons">first_page</i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if previous is defined %}
|
||||
<li class="waves-effect">
|
||||
<a rel="prev" href="{{ path(route, query|merge({(pageParameterName): previous})) }}">
|
||||
<i class="material-icons">chevron_left</i>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="disabled">
|
||||
<a href="#!">
|
||||
<i class="material-icons">chevron_left</i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if page != current %}
|
||||
<li class="waves-effect">
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="active">
|
||||
<a href="#!">{{ page }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if next is defined %}
|
||||
<li class="waves-effect">
|
||||
<a rel="next" href="{{ path(route, query|merge({(pageParameterName): next})) }}">
|
||||
<i class="material-icons">chevron_right</i>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="disabled">
|
||||
<a href="#!">
|
||||
<i class="material-icons">chevron_right</i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if last is defined and current != last %}
|
||||
<li class="waves-effect">
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): last})) }}">
|
||||
<i class="material-icons">last_page</i>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="disabled">
|
||||
<a href="#!">
|
||||
<i class="material-icons">last_page</i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endif %}
|
46
vendor/knplabs/knp-paginator-bundle/templates/Pagination/semantic_ui_pagination.html.twig
vendored
Normal file
46
vendor/knplabs/knp-paginator-bundle/templates/Pagination/semantic_ui_pagination.html.twig
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Semantic UI Sliding pagination control implementation.
|
||||
*
|
||||
* View that can be used with the pagination module
|
||||
* from the Semantic UI CSS Toolkit
|
||||
* https://semantic-ui.com/collections/menu.html#pagination
|
||||
*
|
||||
* @author Valerian Dorcy <valerian.dorcy@gmail.com>
|
||||
*/
|
||||
#}
|
||||
<div class="ui pagination menu">
|
||||
{% if first is defined and current != first %}
|
||||
<a class="icon item" href="{{ path(route, query|merge({(pageParameterName): first})) }}">
|
||||
<i class="angle double left icon"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if previous is defined %}
|
||||
<a rel="prev" class="item icon" href="{{ path(route, query|merge({(pageParameterName): previous})) }}">
|
||||
<i class="angle left icon"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if page != current %}
|
||||
<a class="item" href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>
|
||||
{% else %}
|
||||
<span class="active item">{{ page }}</span>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% if next is defined %}
|
||||
<a rel="next" class="icon item" href="{{ path(route, query|merge({(pageParameterName): next})) }}">
|
||||
<i class="angle right icon"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if last is defined and current != last %}
|
||||
<a class="icon item" href="{{ path(route, query|merge({(pageParameterName): last})) }}">
|
||||
<i class="angle right double icon"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
14
vendor/knplabs/knp-paginator-bundle/templates/Pagination/semantic_ui_sortable_link.html.twig
vendored
Normal file
14
vendor/knplabs/knp-paginator-bundle/templates/Pagination/semantic_ui_sortable_link.html.twig
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<a{% for attr, value in options %} {{ attr }}="{{ value }}"{% endfor %}>
|
||||
<span class="right floated">
|
||||
{% if sorted %}
|
||||
{% if direction == 'desc' %}
|
||||
<i class="sort down icon"></i>
|
||||
{% else %}
|
||||
<i class="sort up icon"></i>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<i class="sort icon"></i>
|
||||
{% endif %}
|
||||
</span>
|
||||
{{ title }}
|
||||
</a>
|
38
vendor/knplabs/knp-paginator-bundle/templates/Pagination/sliding.html.twig
vendored
Normal file
38
vendor/knplabs/knp-paginator-bundle/templates/Pagination/sliding.html.twig
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
{# default Sliding pagination control implementation #}
|
||||
{% if pageCount > 1 %}
|
||||
<div class="pagination">
|
||||
{% if first is defined and current != first %}
|
||||
<span class="first">
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): first})) }}"><<</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if previous is defined %}
|
||||
<span class="previous">
|
||||
<a rel="prev" href="{{ path(route, query|merge({(pageParameterName): previous})) }}"><</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if page != current %}
|
||||
<span class="page">
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="current">{{ page }}</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if next is defined %}
|
||||
<span class="next">
|
||||
<a rel="next" href="{{ path(route, query|merge({(pageParameterName): next})) }}">></a>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if last is defined and current != last %}
|
||||
<span class="last">
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): last})) }}">>></a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
1
vendor/knplabs/knp-paginator-bundle/templates/Pagination/sortable_link.html.twig
vendored
Normal file
1
vendor/knplabs/knp-paginator-bundle/templates/Pagination/sortable_link.html.twig
vendored
Normal file
@ -0,0 +1 @@
|
||||
<a{% for attr, value in options %} {{ attr }}="{{ value }}"{% endfor %}>{{ title }}</a>
|
40
vendor/knplabs/knp-paginator-bundle/templates/Pagination/tailwindcss_pagination.html.twig
vendored
Normal file
40
vendor/knplabs/knp-paginator-bundle/templates/Pagination/tailwindcss_pagination.html.twig
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
{# tailwindcss Sliding pagination control implementation #}
|
||||
{% if pageCount > 1 %}
|
||||
<div class="inline-block">
|
||||
<div class="flex items-baseline flex-row border border-gray-400 rounded-sm w-auto">
|
||||
{% if first is defined and current != first %}
|
||||
<span class="bg-white text-blue-600 px-3 py-2 text-lg border-r border-gray-400 font-bold">
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): first})) }}"><<</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if previous is defined %}
|
||||
<span class="bg-white text-blue-600 px-3 text-lg py-2 border-r border-gray-400">
|
||||
<a rel="prev" href="{{ path(route, query|merge({(pageParameterName): previous})) }}"><</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if page != current %}
|
||||
<span class="bg-white text-blue-600 px-3 py-2 text-lg border-r border-gray-400">
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="bg-blue-600 text-white px-3 py-2 text-lg font-bold">{{ page }}</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if next is defined %}
|
||||
<span class="bg-white text-blue-600 px-3 py-2 text-lg border-r border-gray-400">
|
||||
<a rel="next" href="{{ path(route, query|merge({(pageParameterName): next})) }}">></a>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if last is defined and current != last %}
|
||||
<span class="bg-white text-blue-600 px-3 py-2 text-lg border-gray-400 font-bold">
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): last})) }}">>></a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
89
vendor/knplabs/knp-paginator-bundle/templates/Pagination/twitter_bootstrap_pagination.html.twig
vendored
Normal file
89
vendor/knplabs/knp-paginator-bundle/templates/Pagination/twitter_bootstrap_pagination.html.twig
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Twitter Bootstrap Sliding pagination control implementation.
|
||||
*
|
||||
* View that can be used with the pagination module
|
||||
* from the Twitter Bootstrap CSS Toolkit
|
||||
* https://getbootstrap.com/2.3.2/components.html#pagination
|
||||
*
|
||||
* This view has been ported from Pagerfanta progect
|
||||
* https://github.com/whiteoctober/Pagerfanta/
|
||||
* https://github.com/whiteoctober/Pagerfanta/blob/master/src/Pagerfanta/View/TwitterBootstrapView.php
|
||||
*
|
||||
* @author Pablo Díez <pablodip@gmail.com>
|
||||
* @author Jan Sorgalla <jsorgalla@gmail.com>
|
||||
* @author Artem Ponomarenko <imenem@inbox.ru>
|
||||
*/
|
||||
#}
|
||||
{% if pageCount > 1 %}
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
|
||||
{% if previous is defined %}
|
||||
<li>
|
||||
<a rel="prev" href="{{ path(route, query|merge({(pageParameterName): previous})) }}">« {{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="disabled">
|
||||
<span>« {{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if startPage > 1 %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): 1})) }}">1</a>
|
||||
</li>
|
||||
{% if startPage == 3 %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): 2})) }}">2</a>
|
||||
</li>
|
||||
{% elseif startPage != 2 %}
|
||||
<li class="disabled">
|
||||
<span>…</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if page != current %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="active">
|
||||
<span>{{ page }}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% if pageCount > endPage %}
|
||||
{% if pageCount > (endPage + 1) %}
|
||||
{% if pageCount > (endPage + 2) %}
|
||||
<li class="disabled">
|
||||
<span>…</span>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): (pageCount - 1)})) }}">{{ pageCount -1 }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): pageCount})) }}">{{ pageCount }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if next is defined %}
|
||||
<li>
|
||||
<a rel="next" href="{{ path(route, query|merge({(pageParameterName): next})) }}">{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }} »</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="disabled">
|
||||
<span>{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }} »</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
@ -0,0 +1,84 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Twitter Bootstrap v3 Sliding pagination control implementation.
|
||||
*
|
||||
* View that can be used with the pagination module
|
||||
* from the Twitter Bootstrap CSS Toolkit
|
||||
* https://getbootstrap.com/docs/3.4/components/#pagination
|
||||
*
|
||||
* @author Pablo Díez <pablodip@gmail.com>
|
||||
* @author Jan Sorgalla <jsorgalla@gmail.com>
|
||||
* @author Artem Ponomarenko <imenem@inbox.ru>
|
||||
* @author Artem Zabelin <artjomzabelin@gmail.com>
|
||||
*/
|
||||
#}
|
||||
{% if pageCount > 1 %}
|
||||
<ul class="pagination justify-content-center">
|
||||
|
||||
{% if previous is defined %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" rel="prev" href="{{ path(route, query|merge({(pageParameterName): previous})) }}">« {{ 'label_previous'|trans([], 'KnpPaginatorBundle') }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="disabled page-item">
|
||||
<a class="page-link">« {{ 'label_previous'|trans([], 'KnpPaginatorBundle') }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if startPage > 1 %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path(route, query|merge({(pageParameterName): 1})) }}">1</a>
|
||||
</li>
|
||||
{% if startPage == 3 %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path(route, query|merge({(pageParameterName): 2})) }}">2</a>
|
||||
</li>
|
||||
{% elseif startPage != 2 %}
|
||||
<li class="disabled page-item">
|
||||
<a class="page-link">…</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if page != current %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="active">
|
||||
<a class="page-link">{{ page }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% if pageCount > endPage %}
|
||||
{% if pageCount > (endPage + 1) %}
|
||||
{% if pageCount > (endPage + 2) %}
|
||||
<li class="disabled page-item">
|
||||
<a class="page-link">…</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path(route, query|merge({(pageParameterName): (pageCount - 1)})) }}">{{ pageCount -1 }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path(route, query|merge({(pageParameterName): pageCount})) }}">{{ pageCount }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if next is defined %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" rel="next" href="{{ path(route, query|merge({(pageParameterName): next})) }}">{{ 'label_next'|trans([], 'KnpPaginatorBundle') }} »</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="disabled page-item">
|
||||
<a class="page-link">{{ 'label_next'|trans([], 'KnpPaginatorBundle') }} »</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endif %}
|
@ -0,0 +1,22 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Twitter Bootstrap v3 Sorting control implementation.
|
||||
*
|
||||
* @author Afolabi Olayinka <folabiolayinka@gmail.com>
|
||||
*/
|
||||
#}
|
||||
<a{% for attr, value in options %} {{ attr }}="{{ value }}"{% endfor %} style="color: #000;">
|
||||
<span class="pull-right">
|
||||
{% if sorted %}
|
||||
{% if direction == 'desc' %}
|
||||
<i class="glyphicon glyphicon-sort-by-attributes-alt"></i>
|
||||
{% else %}
|
||||
<i class="glyphicon glyphicon-sort-by-attributes"></i>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<i class="glyphicon glyphicon-sort" style="color: #d2d6de;"></i>
|
||||
{% endif %}
|
||||
</span>
|
||||
{{ title }}
|
||||
</a>
|
@ -0,0 +1,23 @@
|
||||
<form class="form-inline" method="get" action="{{ action }}" enctype="application/x-www-form-urlencoded">
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
{% if fields|length > 1 %}
|
||||
<select class="form-control" name="{{ filterFieldName }}">
|
||||
{% for field, label in fields %}
|
||||
<option value="{{ field }}"{% if selectedField == field %} selected="selected"{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% else %}
|
||||
<input type="hidden" name="{{ filterFieldName }}" value="{{ fields|keys|first }}" />
|
||||
{% endif %}
|
||||
|
||||
<input class="form-control" type="search" value="{{ selectedValue }}" name="{{ filterValueName }}" placeholder="{{ 'filter_searchword'|trans({}, 'KnpPaginatorBundle') }}" />
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary">{{ options.button }}</button>
|
||||
</div>
|
||||
|
||||
</form>
|
@ -0,0 +1,22 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Twitter Bootstrap - Font Awesome Sorting control implementation.
|
||||
*
|
||||
* @author Rodrigo Régis Palmeira <regisbsb@gmail.com>
|
||||
*/
|
||||
#}
|
||||
<a{% for attr, value in options %} {{ attr }}="{{ value }}"{% endfor %}>
|
||||
<span class="float-right">
|
||||
{% if sorted %}
|
||||
{% if direction == 'desc' %}
|
||||
<i class="fa fa-sort-down"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-sort-up"></i>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<i class="fa fa-sort"></i>
|
||||
{% endif %}
|
||||
</span>
|
||||
{{ title }}
|
||||
</a>
|
@ -0,0 +1,25 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Twitter Bootstrap - Material Design Icons Sorting control implementation.
|
||||
*
|
||||
* Install Icon Set: https://google.github.io/material-design-icons/
|
||||
* Overview: https://material.io/resources/icons/?style=baseline
|
||||
*
|
||||
* @author Mike Stuebbe <mike.stuebbe@gmail.com>
|
||||
*/
|
||||
#}
|
||||
<a{% for attr, value in options %} {{ attr }}="{{ value }}"{% endfor %}>
|
||||
<span class="float-right">
|
||||
{% if sorted %}
|
||||
{% if direction == 'desc' %}
|
||||
<i class="material-icons">expand_more</i>
|
||||
{% else %}
|
||||
<i class="material-icons">expand_less</i>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<i class="material-icons">unfold_more</i>
|
||||
{% endif %}
|
||||
</span>
|
||||
{{ title }}
|
||||
</a>
|
@ -0,0 +1,84 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Twitter Bootstrap v4 Sliding pagination control implementation.
|
||||
*
|
||||
* View that can be used with the pagination module
|
||||
* from the Twitter Bootstrap CSS Toolkit
|
||||
* https://getbootstrap.com/docs/4.5/components/pagination/
|
||||
*
|
||||
*/
|
||||
#}
|
||||
{% if pageCount > 1 %}
|
||||
<nav>
|
||||
{% set classAlign = (align is not defined) ? '' : align=='center' ? ' justify-content-center' : (align=='right' ? ' justify-content-end' : '') %}
|
||||
{% set classSize = (size is not defined) ? '' : size=='large' ? ' pagination-lg' : (size=='small' ? ' pagination-sm' : '') %}
|
||||
<ul class="pagination{{ classAlign }}{{ classSize }}">
|
||||
|
||||
{% if previous is defined %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" rel="prev" href="{{ path(route, query|merge({(pageParameterName): previous})) }}">« {{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item disabled">
|
||||
<span class="page-link">« {{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if startPage > 1 %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path(route, query|merge({(pageParameterName): 1})) }}">1</a>
|
||||
</li>
|
||||
{% if startPage == 3 %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path(route, query|merge({(pageParameterName): 2})) }}">2</a>
|
||||
</li>
|
||||
{% elseif startPage != 2 %}
|
||||
<li class="page-item disabled">
|
||||
<span class="page-link">…</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if page != current %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item active">
|
||||
<span class="page-link">{{ page }}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% if pageCount > endPage %}
|
||||
{% if pageCount > (endPage + 1) %}
|
||||
{% if pageCount > (endPage + 2) %}
|
||||
<li class="page-item disabled">
|
||||
<span class="page-link">…</span>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path(route, query|merge({(pageParameterName): (pageCount - 1)})) }}">{{ pageCount -1 }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path(route, query|merge({(pageParameterName): pageCount})) }}">{{ pageCount }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if next is defined %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" rel="next" href="{{ path(route, query|merge({(pageParameterName): next})) }}">{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }} »</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item disabled">
|
||||
<span class="page-link">{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }} »</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
82
vendor/knplabs/knp-paginator-bundle/templates/Pagination/uikit_v3_pagination.html.twig
vendored
Normal file
82
vendor/knplabs/knp-paginator-bundle/templates/Pagination/uikit_v3_pagination.html.twig
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* UIkit 3.0 pagination control implementation.
|
||||
*
|
||||
* View that can be used with the pagination module
|
||||
* from the UIKit Toolkit
|
||||
* https://getuikit.com/docs/pagination
|
||||
*
|
||||
*
|
||||
* @author KULDIP PIPALIYA <kuldipem@gmail.com>
|
||||
*/
|
||||
#}
|
||||
{% if pageCount > 1 %}
|
||||
<ul class="uk-pagination uk-flex-center uk-margin-medium-top">
|
||||
|
||||
{% if previous is defined %}
|
||||
<li>
|
||||
<a rel="prev" href="{{ path(route, query|merge({(pageParameterName): previous})) }}">« {{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="uk-disabled">
|
||||
<span>« {{ 'label_previous'|trans({}, 'KnpPaginatorBundle') }}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if startPage > 1 %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): 1})) }}">1</a>
|
||||
</li>
|
||||
{% if startPage == 3 %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): 2})) }}">2</a>
|
||||
</li>
|
||||
{% elseif startPage != 2 %}
|
||||
<li class="uk-disabled">
|
||||
<span>…</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% for page in pagesInRange %}
|
||||
{% if page != current %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="uk-active">
|
||||
<span>{{ page }}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% if pageCount > endPage %}
|
||||
{% if pageCount > (endPage + 1) %}
|
||||
{% if pageCount > (endPage + 2) %}
|
||||
<li class="uk-disabled">
|
||||
<span>…</span>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): (pageCount - 1)})) }}">{{ pageCount -1 }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{{ path(route, query|merge({(pageParameterName): pageCount})) }}">{{ pageCount }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if next is defined %}
|
||||
<li>
|
||||
<a rel="next" href="{{ path(route, query|merge({(pageParameterName): next})) }}">{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }} »</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="uk-disabled">
|
||||
<span>{{ 'label_next'|trans({}, 'KnpPaginatorBundle') }} »</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endif %}
|
22
vendor/knplabs/knp-paginator-bundle/templates/Pagination/uikit_v3_sortable.html.twig
vendored
Normal file
22
vendor/knplabs/knp-paginator-bundle/templates/Pagination/uikit_v3_sortable.html.twig
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* UIKit 3.0 Sorting control implementation.
|
||||
*
|
||||
* @author KULDIP PIPALIYA <kuldipem@gmail.com>
|
||||
*/
|
||||
#}
|
||||
<a{% for attr, value in options %} {{ attr }}="{{ value }}"{% endfor %} style="color: #000;">
|
||||
<span class="pull-right">
|
||||
{% if sorted %}
|
||||
{% if direction == 'desc' %}
|
||||
<i data-uk-icon="triangle-down"></i>
|
||||
{% else %}
|
||||
<i data-uk-icon="triangle-up"></i>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<i></i>
|
||||
{% endif %}
|
||||
</span>
|
||||
{{ title }}
|
||||
</a>
|
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.ar.xliff
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.ar.xliff
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" target-language="ar" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="0" resname="label_previous">
|
||||
<source>label_previous</source>
|
||||
<target>السابق</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1" resname="label_next">
|
||||
<source>label_next</source>
|
||||
<target>التالي</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2" resname="filter_searchword">
|
||||
<source>filter_searchword</source>
|
||||
<target>بحث...</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.bg.xliff
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.bg.xliff
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" target-language="bg" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="0" resname="label_previous">
|
||||
<source>label_previous</source>
|
||||
<target>Предишна</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1" resname="label_next">
|
||||
<source>label_next</source>
|
||||
<target>Следваща</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2" resname="filter_searchword">
|
||||
<source>filter_searchword</source>
|
||||
<target>търсене...</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.ca.xliff
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.ca.xliff
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" target-language="ca" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="0" resname="label_previous">
|
||||
<source>label_previous</source>
|
||||
<target>Anterior</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1" resname="label_next">
|
||||
<source>label_next</source>
|
||||
<target>Següent</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2" resname="filter_searchword">
|
||||
<source>filter_searchword</source>
|
||||
<target>Cercar...</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.cs.xliff
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.cs.xliff
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" target-language="cs" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="0" resname="label_previous">
|
||||
<source>label_previous</source>
|
||||
<target>Předchozí</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1" resname="label_next">
|
||||
<source>label_next</source>
|
||||
<target>Další</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2" resname="filter_searchword">
|
||||
<source>filter_searchword</source>
|
||||
<target>Vyhledávat...</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.da.xliff
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.da.xliff
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" target-language="da" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="0" resname="label_previous">
|
||||
<source>label_previous</source>
|
||||
<target>Forrige</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1" resname="label_next">
|
||||
<source>label_next</source>
|
||||
<target>Næste</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2" resname="filter_searchword">
|
||||
<source>filter_searchword</source>
|
||||
<target>Søg...</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.de.xliff
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.de.xliff
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" target-language="de" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="0" resname="label_previous">
|
||||
<source>label_previous</source>
|
||||
<target>Vorherige</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1" resname="label_next">
|
||||
<source>label_next</source>
|
||||
<target>Nächste</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2" resname="filter_searchword">
|
||||
<source>filter_searchword</source>
|
||||
<target>Suchbegriff...</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.en.xliff
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.en.xliff
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" target-language="en" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="0" resname="label_previous">
|
||||
<source>label_previous</source>
|
||||
<target>Previous</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1" resname="label_next">
|
||||
<source>label_next</source>
|
||||
<target>Next</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2" resname="filter_searchword">
|
||||
<source>filter_searchword</source>
|
||||
<target>Searchword...</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.es.xliff
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.es.xliff
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" target-language="es" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="0" resname="label_previous">
|
||||
<source>label_previous</source>
|
||||
<target>Anterior</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1" resname="label_next">
|
||||
<source>label_next</source>
|
||||
<target>Siguiente</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2" resname="filter_searchword">
|
||||
<source>filter_searchword</source>
|
||||
<target>Buscar...</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.eu.xliff
vendored
Normal file
19
vendor/knplabs/knp-paginator-bundle/translations/KnpPaginatorBundle.eu.xliff
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" target-language="eu" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="0" resname="label_previous">
|
||||
<source>label_previous</source>
|
||||
<target>Aurrekoa</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="1" resname="label_next">
|
||||
<source>label_next</source>
|
||||
<target>Hurrengoa</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2" resname="filter_searchword">
|
||||
<source>filter_searchword</source>
|
||||
<target>Bilatu...</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user