Skip to content

Commit

Permalink
Pass ArgumentAccess with the knp_pager.items event (#343)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpdude authored Sep 27, 2024
1 parent a1ccc00 commit 311818b
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 166 deletions.
13 changes: 11 additions & 2 deletions src/Knp/Component/Pager/Event/ItemsEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Knp\Component\Pager\Event;

use Knp\Component\Pager\ArgumentAccess\ArgumentAccessInterface;
use Symfony\Contracts\EventDispatcher\Event;

/**
Expand Down Expand Up @@ -34,8 +35,11 @@ final class ItemsEvent extends Event
*/
private array $customPaginationParams = [];

public function __construct(private readonly int $offset, private readonly int $limit)
{
public function __construct(
private readonly int $offset,
private readonly int $limit,
private readonly ArgumentAccessInterface $argumentAccess
) {
}

public function setCustomPaginationParameter(string $name, mixed $value): void
Expand Down Expand Up @@ -67,4 +71,9 @@ public function getOffset(): int
{
return $this->offset;
}

public function getArgumentAccess(): ArgumentAccessInterface
{
return $this->argumentAccess;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,23 @@

class QuerySubscriber implements EventSubscriberInterface
{
public function __construct(private readonly ArgumentAccessInterface $argumentAccess)
{
}

public function items(ItemsEvent $event): void
{
if (!$event->target instanceof Query) {
return;
}
if (!$this->hasQueryParameter($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME])) {
$argumentAccess = $event->getArgumentAccess();

if (!$argumentAccess->has($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME])) {
return;
}
$filterValue = $this->getQueryParameter($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME]);
$filterValue = $argumentAccess->get($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME]);
if ((empty($filterValue) && $filterValue !== '0')) {
return;
}
$filterName = null;
if ($this->hasQueryParameter($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME])) {
$filterName = $this->getQueryParameter($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME]);
if ($argumentAccess->has($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME])) {
$filterName = $argumentAccess->get($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME]);
}
if (!empty($filterName)) {
$columns = $filterName;
Expand All @@ -40,7 +38,7 @@ public function items(ItemsEvent $event): void
} else {
return;
}
$value = $this->getQueryParameter($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME]);
$value = $argumentAccess->get($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME]);
if (str_contains($value, '*')) {
$value = str_replace('*', '%', $value);
}
Expand All @@ -67,14 +65,4 @@ public static function getSubscribedEvents(): array
'knp_pager.items' => ['items', 0],
];
}

private function hasQueryParameter(string $name): bool
{
return $this->argumentAccess->has($name);
}

private function getQueryParameter(string $name): ?string
{
return $this->argumentAccess->get($name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public function before(BeforeEvent $event): void
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher */
$dispatcher = $event->getEventDispatcher();
// hook all standard filtration subscribers
$dispatcher->addSubscriber(new Doctrine\ORM\QuerySubscriber($event->getArgumentAccess()));
$dispatcher->addSubscriber(new PropelQuerySubscriber($event->getArgumentAccess()));
$dispatcher->addSubscriber(new Doctrine\ORM\QuerySubscriber());
$dispatcher->addSubscriber(new PropelQuerySubscriber());

$this->isLoaded = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,24 @@

namespace Knp\Component\Pager\Event\Subscriber\Filtration;

use Knp\Component\Pager\ArgumentAccess\ArgumentAccessInterface;
use Knp\Component\Pager\Event\ItemsEvent;
use Knp\Component\Pager\Exception\InvalidValueException;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class PropelQuerySubscriber implements EventSubscriberInterface
{
public function __construct(private readonly ArgumentAccessInterface $argumentAccess)
{
}

public function items(ItemsEvent $event): void
{
$query = $event->target;
$argumentAccess = $event->getArgumentAccess();

if ($query instanceof \ModelCriteria) {
if (!$this->argumentAccess->has($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME])) {
if (!$argumentAccess->has($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME])) {
return;
}
if ($this->argumentAccess->has($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME])) {
$columns = $this->argumentAccess->get($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME]);
if ($argumentAccess->has($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME])) {
$columns = $argumentAccess->get($event->options[PaginatorInterface::FILTER_FIELD_PARAMETER_NAME]);
} elseif (!empty($event->options[PaginatorInterface::DEFAULT_FILTER_FIELDS])) {
$columns = $event->options[PaginatorInterface::DEFAULT_FILTER_FIELDS];
} else {
Expand All @@ -39,7 +36,7 @@ public function items(ItemsEvent $event): void
}
}
}
$value = $this->argumentAccess->get($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME]);
$value = $argumentAccess->get($event->options[PaginatorInterface::FILTER_VALUE_PARAMETER_NAME]);
$criteria = \Criteria::EQUAL;
if (str_contains($value, '*')) {
$value = str_replace('*', '%', $value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class ArraySubscriber implements EventSubscriberInterface

private readonly ?PropertyAccessorInterface $propertyAccessor;

public function __construct(private readonly ArgumentAccessInterface $argumentAccess, ?PropertyAccessorInterface $accessor = null)
public function __construct(?PropertyAccessorInterface $accessor = null)
{
if (!$accessor && class_exists(PropertyAccess::class)) {
$accessor = PropertyAccess::createPropertyAccessorBuilder()->enableMagicCall()->getPropertyAccessor();
Expand All @@ -36,24 +36,26 @@ public function __construct(private readonly ArgumentAccessInterface $argumentAc

public function items(ItemsEvent $event): void
{
$argumentAccess = $event->getArgumentAccess();

// Check if the result has already been sorted by another 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->argumentAccess->has($sortField)) {
if (!is_array($event->target) || null === $sortField || !$argumentAccess->has($sortField)) {
return;
}

$event->setCustomPaginationParameter('sorted', true);

if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST]) && !in_array($this->argumentAccess->get($sortField), $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
throw new InvalidValueException("Cannot sort by: [{$this->argumentAccess->get($sortField)}] this field is not in allow list.");
if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST]) && !in_array($argumentAccess->get($sortField), $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
throw new InvalidValueException("Cannot sort by: [{$argumentAccess->get($sortField)}] this field is not in allow list.");
}

$sortFunction = $event->options['sortFunction'] ?? [$this, 'proxySortFunction'];
$sortField = $this->argumentAccess->get($sortField);
$sortField = $argumentAccess->get($sortField);

// compatibility layer
if ($sortField[0] === '.') {
Expand All @@ -63,19 +65,19 @@ public function items(ItemsEvent $event): void
call_user_func_array($sortFunction, [
&$event->target,
$sortField,
$this->getSortDirection($event->options),
$this->getSortDirection($event),
]);
}

/**
* @param array<string, mixed> $options
*/
private function getSortDirection(array $options): string
private function getSortDirection(ItemsEvent $event): string
{
if (!$this->argumentAccess->has($options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME])) {
$argumentAccess = $event->getArgumentAccess();
$options = $event->options;

if (!$argumentAccess->has($options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME])) {
return 'desc';
}
$direction = $this->argumentAccess->get($options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME]);
$direction = $argumentAccess->get($options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME]);
if (strtolower($direction) === 'asc') {
return 'asc';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,17 @@
namespace Knp\Component\Pager\Event\Subscriber\Sortable\Doctrine\ODM\MongoDB;

use Doctrine\ODM\MongoDB\Query\Query;
use Knp\Component\Pager\ArgumentAccess\ArgumentAccessInterface;
use Knp\Component\Pager\Event\ItemsEvent;
use Knp\Component\Pager\Exception\InvalidValueException;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class QuerySubscriber implements EventSubscriberInterface
{
public function __construct(private readonly ArgumentAccessInterface $argumentAccess)
{
}

public function items(ItemsEvent $event): void
{
$argumentAccess = $event->getArgumentAccess();

// Check if the result has already been sorted by another sort subscriber
$customPaginationParameters = $event->getCustomPaginationParameters();
if (!empty($customPaginationParameters['sorted']) ) {
Expand All @@ -27,9 +24,9 @@ public function items(ItemsEvent $event): void
$event->setCustomPaginationParameter('sorted', true);
$sortField = $event->options[PaginatorInterface::SORT_FIELD_PARAMETER_NAME];
$sortDir = $event->options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME];
if (null !== $sortField && $this->argumentAccess->has($sortField)) {
$field = $this->argumentAccess->get($sortField);
$dir = null !== $sortDir && strtolower($this->argumentAccess->get($sortDir)) === 'asc' ? 1 : -1;
if (null !== $sortField && $argumentAccess->has($sortField)) {
$field = $argumentAccess->get($sortField);
$dir = null !== $sortDir && strtolower($argumentAccess->get($sortDir)) === 'asc' ? 1 : -1;

if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST]) && (!in_array($field, $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST]))) {
throw new InvalidValueException("Cannot sort by: [$field] this field is not in allow list.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Knp\Component\Pager\Event\Subscriber\Sortable\Doctrine\ORM;

use Doctrine\ORM\Query;
use Knp\Component\Pager\ArgumentAccess\ArgumentAccessInterface;
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;
Expand All @@ -13,12 +12,10 @@

class QuerySubscriber implements EventSubscriberInterface
{
public function __construct(private readonly ArgumentAccessInterface $argumentAccess)
{
}

public function items(ItemsEvent $event): void
{
$argumentAccess = $event->getArgumentAccess();

// Check if the result has already been sorted by another sort subscriber
$customPaginationParameters = $event->getCustomPaginationParameters();
if (!empty($customPaginationParameters['sorted']) ) {
Expand All @@ -29,14 +26,14 @@ public function items(ItemsEvent $event): void
$event->setCustomPaginationParameter('sorted', true);
$sortField = $event->options[PaginatorInterface::SORT_FIELD_PARAMETER_NAME];
$sortDir = $event->options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME];
if (null !== $sortField && $this->argumentAccess->has($sortField)) {
$dir = null !== $sortDir && $this->argumentAccess->has($sortDir) && strtolower($this->argumentAccess->get($sortDir)) === 'asc' ? 'asc' : 'desc';
if (null !== $sortField && $argumentAccess->has($sortField)) {
$dir = null !== $sortDir && $argumentAccess->has($sortDir) && strtolower($argumentAccess->get($sortDir)) === 'asc' ? 'asc' : 'desc';

if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST]) && !in_array($this->argumentAccess->get($sortField), $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
throw new InvalidValueException("Cannot sort by: [{$this->argumentAccess->get($sortField)}] this field is not in allow list.");
if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST]) && !in_array($argumentAccess->get($sortField), $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
throw new InvalidValueException("Cannot sort by: [{$argumentAccess->get($sortField)}] this field is not in allow list.");
}

$sortFieldParameterNames = $this->argumentAccess->get($sortField);
$sortFieldParameterNames = $argumentAccess->get($sortField);
$fields = [];
$aliases = [];
if (!is_string($sortFieldParameterNames)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,17 @@

use Elastica\Query;
use Elastica\SearchableInterface;
use Knp\Component\Pager\ArgumentAccess\ArgumentAccessInterface;
use Knp\Component\Pager\Event\ItemsEvent;
use Knp\Component\Pager\Exception\InvalidValueException;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ElasticaQuerySubscriber implements EventSubscriberInterface
{
public function __construct(private readonly ArgumentAccessInterface $argumentAccess)
{
}

public function items(ItemsEvent $event): void
{
$argumentAccess = $event->getArgumentAccess();

// Check if the result has already been sorted by another sort subscriber
$customPaginationParameters = $event->getCustomPaginationParameters();
if (!empty($customPaginationParameters['sorted']) ) {
Expand All @@ -29,9 +26,9 @@ public function items(ItemsEvent $event): void
$event->setCustomPaginationParameter('sorted', true);
$sortField = $event->options[PaginatorInterface::SORT_FIELD_PARAMETER_NAME];
$sortDir = $event->options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME];
if (null !== $sortField && $this->argumentAccess->has($sortField)) {
$field = $this->argumentAccess->get($sortField);
$dir = null !== $sortDir && $this->argumentAccess->has($sortDir) && strtolower($this->argumentAccess->get($sortDir)) === 'asc' ? 'asc' : 'desc';
if (null !== $sortField && $argumentAccess->has($sortField)) {
$field = $argumentAccess->get($sortField);
$dir = null !== $sortDir && $argumentAccess->has($sortDir) && strtolower($argumentAccess->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 InvalidValueException(sprintf('Cannot sort by: [%s] this field is not in allow list.', $field));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@

namespace Knp\Component\Pager\Event\Subscriber\Sortable;

use Knp\Component\Pager\ArgumentAccess\ArgumentAccessInterface;
use Knp\Component\Pager\Event\ItemsEvent;
use Knp\Component\Pager\Exception\InvalidValueException;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class PropelQuerySubscriber implements EventSubscriberInterface
{
public function __construct(private readonly ArgumentAccessInterface $argumentAccess)
{
}

public function items(ItemsEvent $event): void
{
$argumentAccess = $event->getArgumentAccess();

// Check if the result has already been sorted by another sort subscriber
$customPaginationParameters = $event->getCustomPaginationParameters();
if (!empty($customPaginationParameters['sorted']) ) {
Expand All @@ -27,13 +24,13 @@ public function items(ItemsEvent $event): void
$event->setCustomPaginationParameter('sorted', true);
$sortField = $event->options[PaginatorInterface::SORT_FIELD_PARAMETER_NAME];
$sortDir = $event->options[PaginatorInterface::SORT_DIRECTION_PARAMETER_NAME];
if (null !== $sortField && $this->argumentAccess->has($sortField)) {
$part = $this->argumentAccess->get($sortField);
$direction = (null !== $sortDir && $this->argumentAccess->has($sortDir) && strtolower($this->argumentAccess->get($sortDir)) === 'asc')
if (null !== $sortField && $argumentAccess->has($sortField)) {
$part = $argumentAccess->get($sortField);
$direction = (null !== $sortDir && $argumentAccess->has($sortDir) && strtolower($argumentAccess->get($sortDir)) === 'asc')
? 'asc' : 'desc';

if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST]) && !in_array($this->argumentAccess->get($sortField), $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
throw new InvalidValueException("Cannot sort by: [{$this->argumentAccess->get($sortField)}] this field is not in allow list.");
if (isset($event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST]) && !in_array($argumentAccess->get($sortField), $event->options[PaginatorInterface::SORT_FIELD_ALLOW_LIST])) {
throw new InvalidValueException("Cannot sort by: [{$argumentAccess->get($sortField)}] this field is not in allow list.");
}

$query->orderBy($part, $direction);
Expand Down
Loading

0 comments on commit 311818b

Please sign in to comment.