Completed
Push — master ( c3ad39...fd7849 )
by Simonas
62:35
created

Filter/Widget/Choice/SingleTermChoice.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\Filter\Widget\Choice;
13
14
use ONGR\ElasticsearchBundle\Result\Aggregation\AggregationValue;
15
use ONGR\ElasticsearchDSL\Aggregation\Bucketing\FilterAggregation;
16
use ONGR\ElasticsearchDSL\Aggregation\Bucketing\TermsAggregation;
17
use ONGR\ElasticsearchDSL\Query\TermLevel\TermQuery;
18
use ONGR\ElasticsearchDSL\Search;
19
use ONGR\ElasticsearchBundle\Result\DocumentIterator;
20
use ONGR\FilterManagerBundle\Filter\FilterState;
21
use ONGR\FilterManagerBundle\Filter\Helper\SortAwareTrait;
22
use ONGR\FilterManagerBundle\Filter\Helper\ViewDataFactoryInterface;
23
use ONGR\FilterManagerBundle\Filter\ViewData\ChoicesAwareViewData;
24
use ONGR\FilterManagerBundle\Filter\ViewData;
25
use ONGR\FilterManagerBundle\Filter\Widget\AbstractFilter;
26
use ONGR\FilterManagerBundle\Search\SearchRequest;
27
28
/**
29
 * This class provides single terms choice.
30
 */
31
class SingleTermChoice extends AbstractFilter implements ViewDataFactoryInterface
32
{
33
    use SortAwareTrait;
34
35
    /**
36
     * {@inheritdoc}
37
     */
38
    public function modifySearch(Search $search, FilterState $state = null, SearchRequest $request = null)
39
    {
40
        if ($state && $state->isActive()) {
41
            $search->addPostFilter(new TermQuery($this->getDocumentField(), $state->getValue()));
42
        }
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48
    public function preProcessSearch(Search $search, Search $relatedSearch, FilterState $state = null)
49
    {
50
        $name = $state ? $state->getName() : $this->getDocumentField();
51
        $aggregation = new TermsAggregation($name, $this->getDocumentField());
52
53
        if ($this->getSortOrder()) {
54
            $aggregation->addParameter('order', [
55
                $this->getSortType() => $this->getSortOrder()
56
            ]);
57
        }
58
59
        if ($this->getOption('size') > 0) {
60
            $aggregation->addParameter('size', $this->getOption('size'));
61
        }
62
63
        if ($relatedSearch->getPostFilters()) {
64
            $filterAggregation = new FilterAggregation($name . '-filter');
65
            $filterAggregation->setFilter($relatedSearch->getPostFilters());
66
            $filterAggregation->addAggregation($aggregation);
67
            $search->addAggregation($filterAggregation);
68
69
            if ($this->getOption('show_zero_choices')) {
70
                $unfilteredAggregation = clone $aggregation;
71
                $unfilteredAggregation->setName($name . '-unfiltered');
72
                $search->addAggregation($unfilteredAggregation);
73
            }
74
        } else {
75
            $search->addAggregation($aggregation);
76
        }
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function createViewData()
83
    {
84
        return new ChoicesAwareViewData();
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function getViewData(DocumentIterator $result, ViewData $data)
91
    {
92
        /** @var ChoicesAwareViewData $data */
93
94
        $unsortedChoices = [];
95
        $zeroValueChoices = [];
96
97
        if ($this->getOption('show_zero_choices') && $agg = $result->getAggregation($data->getName() . '-unfiltered')) {
98
            foreach ($agg as $bucket) {
99
                $zeroValueChoices[$bucket['key']] = $bucket['doc_count'];
100
            }
101
        }
102
103
        foreach ($this->fetchAggregation($result, $data->getName()) as $bucket) {
104
            $active = $this->isChoiceActive($bucket['key'], $data);
105
            $choice = new ViewData\ChoiceAwareViewData();
106
            $choice->setLabel($bucket['key']);
107
            $choice->setCount($bucket['doc_count']);
108
            $choice->setActive($active);
109
            if ($active) {
110
                $choice->setUrlParameters($this->getUnsetUrlParameters($bucket['key'], $data));
111
            } else {
112
                $choice->setUrlParameters($this->getOptionUrlParameters($bucket['key'], $data));
113
            }
114
            $unsortedChoices[$bucket['key']] = $choice;
115
116
            if (!empty($zeroValueChoices)) {
117
                unset($zeroValueChoices[$bucket['key']]);
118
            }
119
        }
120
121
        foreach ($zeroValueChoices as $choiceLabel => $value) {
122
            $choice = new ViewData\ChoiceAwareViewData();
123
            $choice->setLabel($choiceLabel);
124
            $choice->setCount(0);
125
            $choice->setActive(false);
126
            $choice->setUrlParameters($data->getResetUrlParameters());
127
            $unsortedChoices[$choiceLabel] = $choice;
128
        }
129
130
        $unsortedChoices = $this->addPriorityChoices($unsortedChoices, $data);
131
132
        foreach ($unsortedChoices as $choice) {
133
            $data->addChoice($choice);
134
        }
135
136
        return $data;
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142
    public function isRelated()
143
    {
144
        return true;
145
    }
146
147
    /**
148
     * Adds prioritized choices.
149
     *
150
     * @param array                $unsortedChoices
151
     * @param ChoicesAwareViewData $data
152
     *
153
     * @return array
154
     */
155
    protected function addPriorityChoices(array $unsortedChoices, ChoicesAwareViewData $data)
156
    {
157
        foreach ($this->getSortPriority() as $name) {
158
            if (array_key_exists($name, $unsortedChoices)) {
159
                $data->addChoice($unsortedChoices[$name]);
160
                unset($unsortedChoices[$name]);
161
            }
162
        }
163
164
        return $unsortedChoices;
165
    }
166
167
    /**
168
     * Fetches buckets from search results.
169
     *
170
     * @param DocumentIterator $result Search results.
171
     * @param string           $name   Filter name.
172
     *
173
     * @return AggregationValue.
0 ignored issues
show
The doc-type AggregationValue. could not be parsed: Unknown type name "AggregationValue." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
174
     */
175
    protected function fetchAggregation(DocumentIterator $result, $name)
176
    {
177
        $aggregation = $result->getAggregation($name);
178
        if (isset($aggregation)) {
179
            return $aggregation;
180
        }
181
182
        $aggregation = $result->getAggregation(sprintf('%s-filter', $name));
183
        return $aggregation->find($name);
184
    }
185
186
    /**
187
     * @param string   $key
188
     * @param ViewData $data
189
     *
190
     * @return array
191
     */
192
    protected function getOptionUrlParameters($key, ViewData $data)
193
    {
194
        $parameters = $data->getResetUrlParameters();
195
        $parameters[$this->getRequestField()] = $key;
196
197
        return $parameters;
198
    }
199
200
    /**
201
     * Returns url with selected term disabled.
202
     *
203
     * @param string   $key
204
     * @param ViewData $data
205
     *
206
     * @return array
207
     */
208
    protected function getUnsetUrlParameters($key, ViewData $data)
209
    {
210
        return $data->getResetUrlParameters();
211
    }
212
213
    /**
214
     * Returns whether choice with the specified key is active.
215
     *
216
     * @param string   $key
217
     * @param ViewData $data
218
     *
219
     * @return bool
220
     */
221
    protected function isChoiceActive($key, ViewData $data)
222
    {
223
        return $data->getState()->isActive() && $data->getState()->getValue() == $key;
224
    }
225
}
226