Completed
Push — master ( f747d2...0cbc0b )
by Karel
14s queued 11s
created

getSubscribedEvents()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the FOSElasticaBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\ElasticaBundle\Subscriber;
13
14
use FOS\ElasticaBundle\Paginator\PaginatorAdapterInterface;
15
use FOS\ElasticaBundle\Paginator\PartialResultsInterface;
16
use Knp\Component\Pager\Event\ItemsEvent;
17
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\HttpFoundation\RequestStack;
20
21
class PaginateElasticaQuerySubscriber implements EventSubscriberInterface
22
{
23
    /**
24
     * @var RequestStack
25
     */
26
    private $requestStack;
27
28 10
    public function __construct(RequestStack $requestStack)
29
    {
30 10
        $this->requestStack = $requestStack;
31 10
    }
32
33 10
    public function items(ItemsEvent $event)
34
    {
35 10
        if ($event->target instanceof PaginatorAdapterInterface) {
36
            // Add sort to query
37 10
            $this->setSorting($event);
38
39
            /** @var $results PartialResultsInterface */
40 9
            $results = $event->target->getResults($event->getOffset(), $event->getLimit());
41
42 9
            $event->count = $results->getTotalHits();
43 9
            $event->items = $results->toArray();
44 9
            $aggregations = $results->getAggregations();
45 9
            if (null != $aggregations) {
46
                $event->setCustomPaginationParameter('aggregations', $aggregations);
47
            }
48
49 9
            $event->stopPropagation();
50
        }
51 9
    }
52
53
    /**
54
     * @return array
55
     */
56 10
    public static function getSubscribedEvents()
57
    {
58
        return [
59 10
            'knp_pager.items' => ['items', 1],
60
        ];
61
    }
62
63
    /**
64
     * Adds knp paging sort to query.
65
     *
66
     * @param ItemsEvent $event
67
     */
68 10
    protected function setSorting(ItemsEvent $event)
69
    {
70
        // Bugfix for PHP 7.4 as options can be null and generate a "Trying to access array offset on value of type null" error
71 10
        $options = $event->options ?? [];
72 10
        $sortField = $this->getFromRequest($options['sortFieldParameterName'] ?? null);
73
74 10
        if (!$sortField && isset($options['defaultSortFieldName'])) {
75 1
            $sortField = $options['defaultSortFieldName'];
76
        }
77
78 10
        if (!empty($sortField)) {
79 8
            $event->target->getQuery()->setSort([
80 8
                $sortField => $this->getSort($sortField, $options),
81
            ]);
82
        }
83 9
    }
84
85 8
    protected function getSort($sortField, array $options = [])
86
    {
87
        $sort = [
88 8
            'order' => $this->getSortDirection($sortField, $options),
89
        ];
90
91 7
        if (isset($options['sortNestedPath'])) {
92 4
            $path = is_callable($options['sortNestedPath']) ?
93 4
                $options['sortNestedPath']($sortField) : $options['sortNestedPath'];
94
95 4
            if (!empty($path)) {
96 4
                $sort['nested_path'] = $path;
97
            }
98
        }
99
100 7
        if (isset($options['sortNestedFilter'])) {
101 2
            $filter = is_callable($options['sortNestedFilter']) ?
102 2
                $options['sortNestedFilter']($sortField) : $options['sortNestedFilter'];
103
104 2
            if (!empty($filter)) {
105 2
                $sort['nested_filter'] = $filter;
106
            }
107
        }
108
109 7
        return $sort;
110
    }
111
112 8
    protected function getSortDirection($sortField, array $options = [])
113
    {
114 8
        $dir = 'asc';
115 8
        $sortDirection = $this->getFromRequest($options['sortDirectionParameterName']);
116
117 8
        if (empty($sortDirection) && isset($options['defaultSortDirection'])) {
118
            $sortDirection = $options['defaultSortDirection'];
119
        }
120
121 8
        if ('desc' === strtolower($sortDirection)) {
122 1
            $dir = 'desc';
123
        }
124
125
        // check if the requested sort field is in the sort whitelist
126 8
        if (isset($options['sortFieldWhitelist']) && !in_array($sortField, $options['sortFieldWhitelist'], true)) {
127 1
            throw new \UnexpectedValueException(sprintf('Cannot sort by: [%s] this field is not in whitelist', $sortField));
128
        }
129
130 7
        return $dir;
131
    }
132
133 8
    private function getRequest(): ?Request
134
    {
135 8
        return $this->requestStack->getCurrentRequest();
136
    }
137
138
    /**
139
     * @return mixed|null
140
     */
141 10
    private function getFromRequest(?string $key)
142
    {
143 10
        if (null !== $key && null !== $request = $this->getRequest()) {
144 8
            return $request->get($key);
145
        }
146
147 2
        return null;
148
    }
149
}
150