vendor/ibexa/fieldtype-query/src/lib/ContentView/QueryResultsInjector.php line 51

Open in your IDE?
  1. <?php
  2. /**
  3. * @copyright Copyright (C) Ibexa AS. All rights reserved.
  4. * @license For full copyright and license information view LICENSE file distributed with this source code.
  5. */
  6. namespace Ibexa\FieldTypeQuery\ContentView;
  7. use Ibexa\Contracts\FieldTypeQuery\QueryFieldLocationService;
  8. use Ibexa\Contracts\FieldTypeQuery\QueryFieldServiceInterface;
  9. use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
  10. use Ibexa\Core\MVC\Symfony\View\ContentValueView;
  11. use Ibexa\Core\MVC\Symfony\View\Event\FilterViewParametersEvent;
  12. use Ibexa\Core\MVC\Symfony\View\LocationValueView;
  13. use Ibexa\Core\MVC\Symfony\View\ViewEvents;
  14. use Pagerfanta\Pagerfanta;
  15. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16. use Symfony\Component\HttpFoundation\RequestStack;
  17. final class QueryResultsInjector implements EventSubscriberInterface
  18. {
  19. /** @var \Ibexa\Contracts\FieldTypeQuery\QueryFieldServiceInterface&\Ibexa\Contracts\FieldTypeQuery\QueryFieldLocationService */
  20. private $queryFieldService;
  21. /** @var array */
  22. private $views;
  23. /** @var \Symfony\Component\HttpFoundation\RequestStack */
  24. private $requestStack;
  25. public function __construct(QueryFieldServiceInterface $queryFieldService, array $views, RequestStack $requestStack)
  26. {
  27. if (!isset($views['item']) || !isset($views['field'])) {
  28. throw new \InvalidArgumentException("Both 'item' and 'field' views must be provided");
  29. }
  30. $this->queryFieldService = $queryFieldService;
  31. $this->views = $views;
  32. $this->requestStack = $requestStack;
  33. }
  34. public static function getSubscribedEvents()
  35. {
  36. return [ViewEvents::FILTER_VIEW_PARAMETERS => 'injectQueryResults'];
  37. }
  38. /**
  39. * {@inheritdoc}
  40. */
  41. public function injectQueryResults(FilterViewParametersEvent $event): void
  42. {
  43. if ($event->getView()->getViewType() === $this->views['field']) {
  44. $builderParameters = $event->getBuilderParameters();
  45. if (!isset($builderParameters['queryFieldDefinitionIdentifier'])) {
  46. throw new InvalidArgumentException('queryFieldDefinitionIdentifier', 'missing');
  47. }
  48. $parameters = [
  49. 'itemViewType' => $event->getBuilderParameters()['itemViewType'] ?? $this->views['item'],
  50. 'items' => $this->buildResults($event),
  51. 'fieldIdentifier' => $builderParameters['queryFieldDefinitionIdentifier'],
  52. ];
  53. $parameters['isPaginationEnabled'] = ($parameters['items'] instanceof Pagerfanta);
  54. if ($parameters['isPaginationEnabled']) {
  55. $parameters['pageParameter'] = sprintf('[%s_page]', $parameters['fieldIdentifier']);
  56. }
  57. $event->getParameterBag()->add($parameters);
  58. }
  59. }
  60. /**
  61. * @param \Ibexa\Core\MVC\Symfony\View\Event\FilterViewParametersEvent $event
  62. *
  63. * @return iterable<\Ibexa\Contracts\Core\Repository\Values\Content\Content>
  64. *
  65. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
  66. */
  67. private function buildResults(FilterViewParametersEvent $event): iterable
  68. {
  69. $view = $event->getView();
  70. $location = $view instanceof LocationValueView ? $view->getLocation() : null;
  71. $content = $view instanceof ContentValueView ? $view->getContent() : null;
  72. if ($location === null && $content === null) {
  73. throw new \Exception('No content nor location to get query results for');
  74. }
  75. $viewParameters = $event->getBuilderParameters();
  76. $fieldDefinitionIdentifier = $viewParameters['queryFieldDefinitionIdentifier'];
  77. $paginationLimit = $this->queryFieldService->getPaginationConfiguration($content ?? $location->getContent(), $fieldDefinitionIdentifier);
  78. $enablePagination = ($viewParameters['enablePagination'] === true);
  79. $disablePagination = ($viewParameters['disablePagination'] === true);
  80. if ($enablePagination === true && $disablePagination === true) {
  81. // @todo custom exception
  82. throw new \InvalidArgumentException("the 'enablePagination' and 'disablePagination' parameters can not both be true");
  83. }
  84. if (isset($viewParameters['itemsPerPage']) && is_numeric($viewParameters['itemsPerPage'])) {
  85. // @todo custom exception
  86. if ($viewParameters['itemsPerPage'] <= 0) {
  87. throw new \InvalidArgumentException('itemsPerPage must be a positive integer');
  88. }
  89. $paginationLimit = $viewParameters['itemsPerPage'];
  90. }
  91. if (($enablePagination === true) && (!is_numeric($paginationLimit) || $paginationLimit === 0)) {
  92. throw new \InvalidArgumentException("The 'itemsPerPage' parameter must be given with a positive integer value if 'enablePagination' is set");
  93. }
  94. if ($paginationLimit !== 0 && $disablePagination !== true) {
  95. $request = $this->requestStack->getMainRequest();
  96. $queryParameters = $view->hasParameter('query') ? $view->getParameter('query') : [];
  97. $limit = $queryParameters['limit'] ?? $paginationLimit;
  98. $pageParam = sprintf('%s_page', $fieldDefinitionIdentifier);
  99. $page = isset($request) ? $request->get($pageParam, 1) : 1;
  100. if ($location !== null) {
  101. $pager = new Pagerfanta(
  102. new QueryResultsWithLocationPagerFantaAdapter(
  103. $this->queryFieldService,
  104. $location,
  105. $fieldDefinitionIdentifier
  106. )
  107. );
  108. } else {
  109. $pager = new Pagerfanta(
  110. new QueryResultsPagerFantaAdapter(
  111. $this->queryFieldService,
  112. $content,
  113. $fieldDefinitionIdentifier
  114. )
  115. );
  116. }
  117. $pager->setMaxPerPage($limit);
  118. $pager->setCurrentPage($page);
  119. return $pager;
  120. } else {
  121. if ($this->queryFieldService instanceof QueryFieldLocationService && $location !== null) {
  122. return $this->queryFieldService->loadContentItemsForLocation(
  123. $location,
  124. $fieldDefinitionIdentifier
  125. );
  126. } elseif ($content !== null) {
  127. return $this->queryFieldService->loadContentItems(
  128. $content,
  129. $fieldDefinitionIdentifier
  130. );
  131. } else {
  132. throw new \Exception('No content nor location to get query results for');
  133. }
  134. }
  135. }
  136. }
  137. class_alias(QueryResultsInjector::class, 'EzSystems\EzPlatformQueryFieldType\eZ\ContentView\QueryResultsInjector');