Completed
Push — master ( 7d3672...a34d6f )
by Simonas
357:48 queued 292:56
created

SingleTermChoice::getViewData()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 33
rs 8.439
cc 5
eloc 19
nc 12
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\Filter\TermFilter;
17
use ONGR\ElasticsearchDSL\Search;
18
use ONGR\ElasticsearchBundle\Result\Aggregation\ValueAggregation;
19
use ONGR\ElasticsearchBundle\Result\DocumentIterator;
20
use ONGR\FilterManagerBundle\Filter\FilterState;
21
use ONGR\FilterManagerBundle\Filter\Helper\SizeAwareTrait;
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\AbstractSingleRequestValueFilter;
26
use ONGR\FilterManagerBundle\Filter\Helper\FieldAwareInterface;
27
use ONGR\FilterManagerBundle\Filter\Helper\FieldAwareTrait;
28
use ONGR\FilterManagerBundle\Search\SearchRequest;
29
30
/**
31
 * This class provides single terms choice.
32
 */
33
class SingleTermChoice extends AbstractSingleRequestValueFilter implements FieldAwareInterface, ViewDataFactoryInterface
34
{
35
    use FieldAwareTrait, SizeAwareTrait;
36
37
    /**
38
     * @var array
39
     */
40
    private $sortType;
41
42
    /**
43
     * @param array $sortType
44
     */
45
    public function setSortType($sortType)
46
    {
47
        $this->sortType = $sortType;
48
    }
49
50
    /**
51
     * @return array
52
     */
53
    public function getSortType()
54
    {
55
        return $this->sortType;
56
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function modifySearch(Search $search, FilterState $state = null, SearchRequest $request = null)
62
    {
63
        if ($state && $state->isActive()) {
64
            $search->addPostFilter(new TermFilter($this->getField(), $state->getValue()));
65
        }
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function preProcessSearch(Search $search, Search $relatedSearch, FilterState $state = null)
72
    {
73
        $name = $state ? $state->getName() : $this->getField();
74
        $aggregation = new TermsAggregation($name, $this->getField());
75
76
        if ($this->getSortType()) {
77
            $aggregation->addParameter('order', [$this->getSortType()['type'] => $this->getSortType()['order']]);
78
        }
79
80
        $aggregation->addParameter('size', 0);
81
        if ($this->getSize() > 0) {
82
            $aggregation->addParameter('size', $this->getSize());
83
        }
84
85
        if ($relatedSearch->getPostFilters()) {
86
            $filterAggregation = new FilterAggregation($name . '-filter');
87
            $filterAggregation->setFilter($relatedSearch->getPostFilters());
88
            $filterAggregation->addAggregation($aggregation);
89
            $search->addAggregation($filterAggregation);
90
        } else {
91
            $search->addAggregation($aggregation);
92
        }
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function createViewData()
99
    {
100
        return new ChoicesAwareViewData();
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function getViewData(DocumentIterator $result, ViewData $data)
107
    {
108
        /** @var ChoicesAwareViewData $data */
109
110
        $unsortedChoices = [];
111
112
        /** @var ValueAggregation $bucket */
113
        foreach ($this->fetchAggregation($result, $data->getName()) as $bucket) {
114
            $bucket = $bucket->getValue();
115
            $active = $this->isChoiceActive($bucket['key'], $data);
116
            $choice = new ViewData\Choice();
117
            $choice->setLabel($bucket['key']);
118
            $choice->setCount($bucket['doc_count']);
119
            $choice->setActive($active);
120
            if ($active) {
121
                $choice->setUrlParameters($this->getUnsetUrlParameters($bucket['key'], $data));
122
            } else {
123
                $choice->setUrlParameters($this->getOptionUrlParameters($bucket['key'], $data));
124
            }
125
            $unsortedChoices[$bucket['key']] = $choice;
126
        }
127
128
        // Add the prioritized choices first.
129
        if ($this->getSortType()) {
130
            $unsortedChoices = $this->addPriorityChoices($unsortedChoices, $data);
131
        }
132
133
        foreach ($unsortedChoices as $choice) {
134
            $data->addChoice($choice);
135
        }
136
137
        return $data;
138
    }
139
140
    /**
141
     * Adds prioritized choices.
142
     *
143
     * @param array                $unsortedChoices
144
     * @param ChoicesAwareViewData $data
145
     *
146
     * @return array
147
     */
148
    protected function addPriorityChoices(array $unsortedChoices, ChoicesAwareViewData $data)
149
    {
150
        foreach ($this->getSortType()['priorities'] as $name) {
151
            if (array_key_exists($name, $unsortedChoices)) {
152
                $data->addChoice($unsortedChoices[$name]);
153
                unset($unsortedChoices[$name]);
154
            }
155
        }
156
157
        return $unsortedChoices;
158
    }
159
160
    /**
161
     * Fetches buckets from search results.
162
     *
163
     * @param DocumentIterator $result Search results.
164
     * @param string           $name   Filter name.
165
     *
166
     * @return array Buckets.
167
     */
168
    protected function fetchAggregation(DocumentIterator $result, $name)
169
    {
170
        $aggregation = $result->getAggregation($name);
171
        if (isset($aggregation)) {
172
            return $aggregation;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $aggregation; (ONGR\ElasticsearchBundle...gation\ValueAggregation) 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...
173
        }
174
175
        $buckets = $result->getAggregations()->find(sprintf('%s-filter.%s', $name, $name));
176
177
        if (isset($buckets)) {
178
            return $buckets;
179
        }
180
181
        return [];
182
    }
183
184
    /**
185
     * @param string   $key
186
     * @param ViewData $data
187
     *
188
     * @return array
189
     */
190
    protected function getOptionUrlParameters($key, ViewData $data)
191
    {
192
        $parameters = $data->getResetUrlParameters();
193
        $parameters[$this->getRequestField()] = $key;
194
195
        return $parameters;
196
    }
197
198
    /**
199
     * Returns url with selected term disabled.
200
     *
201
     * @param string   $key
202
     * @param ViewData $data
203
     *
204
     * @return array
205
     */
206
    protected function getUnsetUrlParameters($key, ViewData $data)
207
    {
208
        return $data->getResetUrlParameters();
209
    }
210
211
    /**
212
     * Returns whether choice with the specified key is active.
213
     *
214
     * @param string   $key
215
     * @param ViewData $data
216
     *
217
     * @return bool
218
     */
219
    protected function isChoiceActive($key, ViewData $data)
220
    {
221
        return $data->getState()->isActive() && $data->getState()->getValue() == $key;
222
    }
223
}
224