Completed
Push — master ( 650132...5e5f70 )
by Simonas
8s
created

SingleTermChoice::fetchAggregation()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 14
rs 9.4285
cc 3
eloc 8
nc 3
nop 2
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\ElasticsearchDSL\Aggregation\FilterAggregation;
15
use ONGR\ElasticsearchDSL\Aggregation\TermsAggregation;
16
use ONGR\ElasticsearchDSL\Query\TermQuery;
17
use ONGR\ElasticsearchDSL\Search;
18
use ONGR\ElasticsearchBundle\Result\DocumentIterator;
19
use ONGR\FilterManagerBundle\Filter\FilterState;
20
use ONGR\FilterManagerBundle\Filter\Helper\SizeAwareTrait;
21
use ONGR\FilterManagerBundle\Filter\Helper\ViewDataFactoryInterface;
22
use ONGR\FilterManagerBundle\Filter\ViewData\ChoicesAwareViewData;
23
use ONGR\FilterManagerBundle\Filter\ViewData;
24
use ONGR\FilterManagerBundle\Filter\Widget\AbstractSingleRequestValueFilter;
25
use ONGR\FilterManagerBundle\Filter\Helper\FieldAwareInterface;
26
use ONGR\FilterManagerBundle\Filter\Helper\FieldAwareTrait;
27
use ONGR\FilterManagerBundle\Search\SearchRequest;
28
29
/**
30
 * This class provides single terms choice.
31
 */
32
class SingleTermChoice extends AbstractSingleRequestValueFilter implements FieldAwareInterface, ViewDataFactoryInterface
33
{
34
    use FieldAwareTrait, SizeAwareTrait;
35
36
    /**
37
     * @var array
38
     */
39
    private $sortType;
40
41
    /**
42
     * @param array $sortType
43
     */
44
    public function setSortType($sortType)
45
    {
46
        $this->sortType = $sortType;
47
    }
48
49
    /**
50
     * @return array
51
     */
52
    public function getSortType()
53
    {
54
        return $this->sortType;
55
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60
    public function modifySearch(Search $search, FilterState $state = null, SearchRequest $request = null)
61
    {
62
        if ($state && $state->isActive()) {
63
            $search->addPostFilter(new TermQuery($this->getField(), $state->getValue()));
64
        }
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70
    public function preProcessSearch(Search $search, Search $relatedSearch, FilterState $state = null)
71
    {
72
        $name = $state ? $state->getName() : $this->getField();
73
        $aggregation = new TermsAggregation($name, $this->getField());
74
75
        if ($this->getSortType()) {
76
            $aggregation->addParameter('order', [$this->getSortType()['type'] => $this->getSortType()['order']]);
77
        }
78
79
        $aggregation->addParameter('size', 0);
80
        if ($this->getSize() > 0) {
81
            $aggregation->addParameter('size', $this->getSize());
82
        }
83
84
        if ($relatedSearch->getPostFilters()) {
85
            $filterAggregation = new FilterAggregation($name . '-filter');
86
            $filterAggregation->setFilter($relatedSearch->getPostFilters());
87
            $filterAggregation->addAggregation($aggregation);
88
            $search->addAggregation($filterAggregation);
89
        } else {
90
            $search->addAggregation($aggregation);
91
        }
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function createViewData()
98
    {
99
        return new ChoicesAwareViewData();
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105
    public function getViewData(DocumentIterator $result, ViewData $data)
106
    {
107
        /** @var ChoicesAwareViewData $data */
108
109
        $unsortedChoices = [];
110
111
        foreach ($this->fetchAggregation($result, $data->getName()) as $bucket) {
112
            $active = $this->isChoiceActive($bucket['key'], $data);
113
            $choice = new ViewData\Choice();
114
            $choice->setLabel($bucket['key']);
115
            $choice->setCount($bucket['doc_count']);
116
            $choice->setActive($active);
117
            if ($active) {
118
                $choice->setUrlParameters($this->getUnsetUrlParameters($bucket['key'], $data));
119
            } else {
120
                $choice->setUrlParameters($this->getOptionUrlParameters($bucket['key'], $data));
121
            }
122
            $unsortedChoices[$bucket['key']] = $choice;
123
        }
124
125
        // Add the prioritized choices first.
126
        if ($this->getSortType()) {
127
            $unsortedChoices = $this->addPriorityChoices($unsortedChoices, $data);
128
        }
129
130
        foreach ($unsortedChoices as $choice) {
131
            $data->addChoice($choice);
132
        }
133
134
        return $data;
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     */
140
    public function isRelated()
141
    {
142
        return true;
143
    }
144
145
    /**
146
     * Adds prioritized choices.
147
     *
148
     * @param array                $unsortedChoices
149
     * @param ChoicesAwareViewData $data
150
     *
151
     * @return array
152
     */
153
    protected function addPriorityChoices(array $unsortedChoices, ChoicesAwareViewData $data)
154
    {
155
        foreach ($this->getSortType()['priorities'] as $name) {
156
            if (array_key_exists($name, $unsortedChoices)) {
157
                $data->addChoice($unsortedChoices[$name]);
158
                unset($unsortedChoices[$name]);
159
            }
160
        }
161
162
        return $unsortedChoices;
163
    }
164
165
    /**
166
     * Fetches buckets from search results.
167
     *
168
     * @param DocumentIterator $result Search results.
169
     * @param string           $name   Filter name.
170
     *
171
     * @return array Buckets.
172
     */
173
    protected function fetchAggregation(DocumentIterator $result, $name)
174
    {
175
        $aggregation = $result->getAggregation($name);
176
        if (isset($aggregation)) {
177
            return $aggregation;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $aggregation; (ONGR\ElasticsearchBundle...gation\AggregationValue) is incompatible with the return type documented by ONGR\FilterManagerBundle...hoice::fetchAggregation of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

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