Completed
Push — master ( 76ac79...60ae6d )
by Simonas
64:57
created

Search/FilterManager.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[email protected]>
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 ONGR\FilterManagerBundle\Search;
13
14
use ONGR\ElasticsearchDSL\Search;
15
use ONGR\ElasticsearchBundle\Service\Repository;
16
use ONGR\ElasticsearchBundle\Result\DocumentIterator;
17
use ONGR\FilterManagerBundle\Event\PreSearchEvent;
18
use ONGR\FilterManagerBundle\Event\SearchResponseEvent;
19
use ONGR\FilterManagerBundle\Filter\FilterInterface;
20
use ONGR\FilterManagerBundle\Filter\FilterState;
21
use ONGR\FilterManagerBundle\Filter\Helper\ViewDataFactoryInterface;
22
use ONGR\FilterManagerBundle\Filter\ViewData;
23
use ONGR\FilterManagerBundle\ONGRFilterManagerEvents;
24
use ONGR\FilterManagerBundle\Relation\ExcludeRelation;
25
use ONGR\FilterManagerBundle\Relation\FilterIterator;
26
use ONGR\FilterManagerBundle\Relation\LogicalJoin\AndRelation;
27
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
28
use Symfony\Component\HttpFoundation\Request;
29
30
/**
31
 * This class is entry point for search request execution.
32
 */
33
class FilterManager implements FilterManagerInterface
34
{
35
    /**
36
     * @var FilterContainer
37
     */
38
    private $container;
39
40
    /**
41
     * @var Repository
42
     */
43
    private $repository;
44
45
    /**
46
     * @var EventDispatcherInterface
47
     */
48
    private $eventDispatcher;
49
    
50
    /**
51
     * @param FilterContainer          $container
52
     * @param Repository               $repository
53
     * @param EventDispatcherInterface $eventDispatcher
54
     */
55
    public function __construct(
56
        FilterContainer $container,
57
        Repository $repository,
58
        EventDispatcherInterface $eventDispatcher
59
    ) {
60
        $this->container = $container;
61
        $this->repository = $repository;
62
        $this->eventDispatcher = $eventDispatcher;
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68
    public function handleRequest(Request $request)
69
    {
70
        return $this->search($this->container->buildSearchRequest($request));
71
    }
72
73
    /**
74
     * Executes search.
75
     *
76
     * @param SearchRequest $request
77
     *
78
     * @return SearchResponse
79
     */
80
    public function search(SearchRequest $request)
81
    {
82
        $this->eventDispatcher->dispatch(ONGRFilterManagerEvents::PRE_SEARCH, new PreSearchEvent($request));
83
84
        $search = $this->container->buildSearch($request);
85
86
        /** @var FilterInterface $filter */
87
        foreach ($this->container->all() as $name => $filter) {
88
            $relatedSearch = new Search();
89
90
            if ($filter->isRelated()) {
91
                // We simply exclude not related filters and current filter itself.
92
                $relatedFilters = $this->container->getFiltersByRelation(
93
                    new AndRelation([$filter->getSearchRelation(), new ExcludeRelation([$name])])
94
                );
95
                $relatedSearch = $this->container->buildSearch($request, $relatedFilters);
96
            }
97
98
            $filter->preProcessSearch(
99
                $search,
100
                $relatedSearch,
101
                $request->get($name)
102
            );
103
        }
104
105
        $result = $this->repository->execute($search);
0 ignored issues
show
Deprecated Code introduced by
The method ONGR\ElasticsearchBundle...e\Repository::execute() has been deprecated with message: Use strict execute functions instead. e.g. executeIterator, executeRawIterator.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
106
        $this->eventDispatcher->dispatch(ONGRFilterManagerEvents::SEARCH_RESPONSE, new SearchResponseEvent($result));
107
108
        return new SearchResponse(
109
            $this->getFiltersViewData($result, $request),
110
            $result,
111
            $this->composeUrlParameters($request)
112
        );
113
    }
114
115
    /**
116
     * Composes url parameters related to given filter.
117
     *
118
     * @param SearchRequest   $request Search request.
119
     * @param FilterInterface $filter  Filter.
120
     * @param array           $exclude Additional names of filters to exclude.
121
     *
122
     * @return array
123
     */
124
    protected function composeUrlParameters(SearchRequest $request, FilterInterface $filter = null, $exclude = [])
125
    {
126
        $out = [];
127
128
        $and = [];
129
130
        if ($filter) {
131
            $and[] = $filter->getResetRelation();
132
        }
133
134
        if (!empty($exclude)) {
135
            $and[] = new ExcludeRelation($exclude);
136
        }
137
138
        /** @var FilterState[] $states */
139
        $states = new FilterIterator(new \IteratorIterator($request), new AndRelation($and));
140
141
        foreach ($states as $state) {
142
            $out = array_merge($out, $state->getUrlParameters());
143
        }
144
145
        return $out;
146
    }
147
148
    /**
149
     * Creates view data for each filter.
150
     *
151
     * @param DocumentIterator $result
152
     * @param SearchRequest    $request
153
     *
154
     * @return ViewData[]
155
     */
156
    protected function getFiltersViewData(DocumentIterator $result, SearchRequest $request)
157
    {
158
        $out = [];
159
160
        /** @var FilterInterface[] $filters */
161
        $filters = $this->container->all();
162
163
        foreach ($filters as $name => $filter) {
164
            if ($filter instanceof ViewDataFactoryInterface) {
165
                $viewData = $filter->createViewData();
166
            } else {
167
                $viewData = new ViewData();
168
            }
169
            $viewData->setName($name);
170
            $viewData->setUrlParameters($this->composeUrlParameters($request, $filter));
171
            $viewData->setState($request->get($name));
172
            $viewData->setTags($filter->getTags());
173
            $viewData->setResetUrlParameters($this->composeUrlParameters($request, $filter, [$name]));
174
            $out[$name] = $filter->getViewData($result, $viewData);
175
        }
176
177
        return $out;
178
    }
179
}
180