Completed
Push — master ( 8386c2...ffd2be )
by Simonas
61:26
created

SingleTermChoice::createViewData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
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
     * Adds prioritized choices.
139
     *
140
     * @param array                $unsortedChoices
141
     * @param ChoicesAwareViewData $data
142
     *
143
     * @return array
144
     */
145
    protected function addPriorityChoices(array $unsortedChoices, ChoicesAwareViewData $data)
146
    {
147
        foreach ($this->getSortType()['priorities'] as $name) {
148
            if (array_key_exists($name, $unsortedChoices)) {
149
                $data->addChoice($unsortedChoices[$name]);
150
                unset($unsortedChoices[$name]);
151
            }
152
        }
153
154
        return $unsortedChoices;
155
    }
156
157
    /**
158
     * Fetches buckets from search results.
159
     *
160
     * @param DocumentIterator $result Search results.
161
     * @param string           $name   Filter name.
162
     *
163
     * @return array Buckets.
164
     */
165
    protected function fetchAggregation(DocumentIterator $result, $name)
166
    {
167
        $aggregation = $result->getAggregation($name);
168
        if (isset($aggregation)) {
169
            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...
170
        }
171
172
        $aggregation = $result->getAggregation(sprintf('%s-filter', $name));
173
        if (isset($aggregation)) {
174
            return $aggregation->find($name);
175
        }
176
177
        return [];
178
    }
179
180
    /**
181
     * @param string   $key
182
     * @param ViewData $data
183
     *
184
     * @return array
185
     */
186
    protected function getOptionUrlParameters($key, ViewData $data)
187
    {
188
        $parameters = $data->getResetUrlParameters();
189
        $parameters[$this->getRequestField()] = $key;
190
191
        return $parameters;
192
    }
193
194
    /**
195
     * Returns url with selected term disabled.
196
     *
197
     * @param string   $key
198
     * @param ViewData $data
199
     *
200
     * @return array
201
     */
202
    protected function getUnsetUrlParameters($key, ViewData $data)
203
    {
204
        return $data->getResetUrlParameters();
205
    }
206
207
    /**
208
     * Returns whether choice with the specified key is active.
209
     *
210
     * @param string   $key
211
     * @param ViewData $data
212
     *
213
     * @return bool
214
     */
215
    protected function isChoiceActive($key, ViewData $data)
216
    {
217
        return $data->getState()->isActive() && $data->getState()->getValue() == $key;
218
    }
219
}
220