Completed
Branch master (33af51)
by Timo
04:12
created

Faceting::buildFacetParameters()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 18
cts 18
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 19
nc 6
nop 1
crap 5
1
<?php
2
namespace ApacheSolrForTypo3\Solr\Query\Modifier;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2009-2015 Ingo Renner <[email protected]>
8
 *  All rights reserved
9
 *
10
 *  This script is part of the TYPO3 project. The TYPO3 project is
11
 *  free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 2 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  The GNU General Public License can be found at
17
 *  http://www.gnu.org/copyleft/gpl.html.
18
 *
19
 *  This script is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  This copyright notice MUST APPEAR in all copies of the script!
25
 ***************************************************************/
26
27
use ApacheSolrForTypo3\Solr\Query;
28
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration;
29
use ApacheSolrForTypo3\Solr\Util;
30
use TYPO3\CMS\Core\Utility\GeneralUtility;
31
32
/**
33
 * Modifies a query to add faceting parameters
34
 *
35
 * @author Ingo Renner <[email protected]>
36
 * @author Daniel Poetzinger <[email protected]>
37
 * @author Sebastian Kurfuerst <[email protected]>
38
 */
39
class Faceting implements Modifier
40
{
41
    /**
42
     * @var \ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration|array
43
     */
44
    protected $configuration;
45
46
    protected $facetParameters = array();
47
48
    protected $facetFilters = array();
49
50
    protected $facetRendererFactory = null;
51
52
    /**
53
     * @var array
54
     */
55
    protected $allConfiguredFacets = array();
56
57
    /**
58
     * @param TypoScriptConfiguration $solrConfiguration
59
     */
60 27
    public function __construct($solrConfiguration = null)
61
    {
62 27
        if (!is_null($solrConfiguration)) {
63 7
            $this->configuration = $solrConfiguration;
64
        } else {
65 20
            $this->configuration = Util::getSolrConfiguration();
66
        }
67
68 27
        $this->allConfiguredFacets = $this->configuration->getSearchFacetingFacets();
69 27
        $this->facetRendererFactory = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Facet\\FacetRendererFactory',
70 27
            $this->allConfiguredFacets);
71 27
    }
72
73
    /**
74
     * Modifies the given query and adds the parameters necessary for faceted
75
     * search.
76
     *
77
     * @param Query $query The query to modify
78
     * @return Query The modified query with faceting parameters
79
     */
80 27
    public function modifyQuery(Query $query)
81
    {
82 27
        $query->setFaceting();
83 27
        $this->buildFacetingParameters();
84 27
        $this->addFacetQueryFilters();
85
86 27
        foreach ($this->facetParameters as $facetParameter => $value) {
87 27
            $query->addQueryParameter($facetParameter, $value);
88
        }
89
90 27
        foreach ($this->facetFilters as $filter) {
91 4
            $query->addFilter($filter);
92
        }
93
94 27
        return $query;
95
    }
96
97
    /**
98
     * Delegates the parameter building to specialized functions depending on
99
     * the type of facet to add.
100
     *
101
     */
102 27
    protected function buildFacetingParameters()
103
    {
104 27
        $facetParameters = array();
0 ignored issues
show
Unused Code introduced by
$facetParameters is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
105 27
        foreach ($this->allConfiguredFacets as $facetName => $facetConfiguration) {
106 27
            $facetName = substr($facetName, 0, -1);
107
108 27
            $facetParameterBuilder = $this->facetRendererFactory->getQueryFacetBuilderByFacetName($facetName);
109 27
            if (!is_null($facetParameterBuilder)) {
110
                $facetParameters = $facetParameterBuilder->buildFacetParameters($facetName,
111
                    $facetConfiguration);
112
            } else {
113 27
                $facetParameters = $this->buildFacetParameters($facetConfiguration);
114
            }
115
116 27
            $this->facetParameters = array_merge_recursive($this->facetParameters,
117
                $facetParameters);
118
        }
119 27
    }
120
121
    /**
122
     * Builds facet parameters for field facets
123
     *
124
     * @param array $facetConfiguration The facet's configuration
125
     * @return array
126
     */
127 27
    protected function buildFacetParameters(array $facetConfiguration)
128
    {
129 27
        $facetParameters = array();
130
131
        // simple for now, may add overrides f.<field_name>.facet.* later
132 27
        if ($this->configuration->getSearchFacetingKeepAllFacetsOnSelection()) {
133 2
            $facets = array();
134 2
            foreach ($this->allConfiguredFacets as $facet) {
135 2
                $facets[] = $facet['field'];
136
            }
137
138 2
            $facetParameters['facet.field'][] =
139 2
                '{!ex=' . implode(',', $facets) . '}'
140 2
                . $facetConfiguration['field'];
141 25
        } elseif ($facetConfiguration['keepAllOptionsOnSelection'] == 1) {
142 22
            $facetParameters['facet.field'][] =
143 22
                '{!ex=' . $facetConfiguration['field'] . '}'
144 22
                . $facetConfiguration['field'];
145
        } else {
146 25
            $facetParameters['facet.field'][] = $facetConfiguration['field'];
147
        }
148
149 27
        if (in_array($facetConfiguration['sortBy'],
150 27
            array('alpha', 'index', 'lex'))) {
151 1
            $facetParameters['f.' . $facetConfiguration['field'] . '.facet.sort'] = 'lex';
152
        }
153
154 27
        return $facetParameters;
155
    }
156
157
    /**
158
     * Adds filters specified through HTTP GET as filter query parameters to
159
     * the Solr query.
160
     *
161
     */
162 27
    protected function addFacetQueryFilters()
163
    {
164
        // todo refactor to use a request object
165 27
        $resultParameters = GeneralUtility::_GET('tx_solr');
166
167
        // format for filter URL parameter:
168
        // tx_solr[filter]=$facetName0:$facetValue0,$facetName1:$facetValue1,$facetName2:$facetValue2
169 27
        if (is_array($resultParameters['filter'])) {
170 4
            $filters = array_map('urldecode', $resultParameters['filter']);
171
            // $filters look like array('name:value1','name:value2','fieldname2:foo')
172 4
            $configuredFacets = $this->getConfiguredFacets();
173
            // first group the filters by facetName - so that we can
174
            // decide later whether we need to do AND or OR for multiple
175
            // filters for a certain facet/field
176
            // $filtersByFacetName look like array('name' => array ('value1', 'value2'), 'fieldname2' => array('foo'))
177 4
            $filtersByFacetName = array();
178 4
            foreach ($filters as $filter) {
179
                // only split by the first colon to allow using colons in the filter value itself
180 4
                list($filterFacetName, $filterValue) = explode(':', $filter, 2);
181 4
                if (in_array($filterFacetName, $configuredFacets)) {
182 4
                    $filtersByFacetName[$filterFacetName][] = $filterValue;
183
                }
184
            }
185
186 4
            foreach ($filtersByFacetName as $facetName => $filterValues) {
187 4
                $facetConfiguration = $this->allConfiguredFacets[$facetName . '.'];
188 4
                $filterEncoder = $this->facetRendererFactory->getFacetFilterEncoderByFacetName($facetName);
189
190 4
                $tag = '';
191 4
                if ($facetConfiguration['keepAllOptionsOnSelection'] == 1
192 4
                   || $this->configuration->getSearchFacetingKeepAllFacetsOnSelection()
193
                ) {
194 3
                    $tag = '{!tag=' . addslashes($facetConfiguration['field']) . '}';
195
                }
196
197 4
                $filterParts = array();
198 4
                foreach ($filterValues as $filterValue) {
199 4
                    if (!is_null($filterEncoder)) {
200
                        $filterOptions = $facetConfiguration[$facetConfiguration['type'] . '.'];
201
                        if (empty($filterOptions)) {
202
                            $filterOptions = array();
203
                        }
204
205
                        $filterValue = $filterEncoder->decodeFilter($filterValue,
206
                            $filterOptions);
207
                        $filterParts[] = $facetConfiguration['field'] . ':' . $filterValue;
208
                    } else {
209 4
                        $filterParts[] = $facetConfiguration['field'] . ':"' . addslashes($filterValue) . '"';
210
                    }
211
                }
212
213 4
                $operator = ($facetConfiguration['operator'] == 'OR') ? ' OR ' : ' AND ';
214 4
                $this->facetFilters[] = $tag . '(' . implode($operator,
215 4
                        $filterParts) . ')';
216
            }
217
        }
218 27
    }
219
220
    /**
221
     * Gets the facets as configured through TypoScript
222
     *
223
     * @return array An array of facet names as specified in TypoScript
224
     */
225 4
    protected function getConfiguredFacets()
226
    {
227 4
        $facets = array();
228
229 4
        foreach ($this->allConfiguredFacets as $facetName => $facetConfiguration) {
230 4
            $facetName = substr($facetName, 0, -1);
231
232 4
            if (empty($facetConfiguration['field'])) {
233
                // TODO later check for query and date, too
234
                continue;
235
            }
236
237 4
            $facets[] = $facetName;
238
        }
239
240 4
        return $facets;
241
    }
242
}
243