1 | <?php |
||
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) |
|
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) |
|
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() |
|
119 | |||
120 | /** |
||
121 | * Builds facet parameters for field facets |
||
122 | * |
||
123 | * @param array $facetConfiguration The facet's configuration |
||
124 | * @return array |
||
125 | */ |
||
126 | 27 | protected function buildFacetParameters(array $facetConfiguration) |
|
155 | |||
156 | /** |
||
157 | * Adds filters specified through HTTP GET as filter query parameters to |
||
158 | * the Solr query. |
||
159 | * |
||
160 | */ |
||
161 | 27 | protected function addFacetQueryFilters() |
|
162 | { |
||
163 | // todo refactor to use a request object |
||
164 | 27 | $resultParameters = GeneralUtility::_GET('tx_solr'); |
|
165 | |||
166 | // format for filter URL parameter: |
||
167 | // tx_solr[filter]=$facetName0:$facetValue0,$facetName1:$facetValue1,$facetName2:$facetValue2 |
||
168 | 27 | if (is_array($resultParameters['filter'])) { |
|
169 | 4 | $filters = array_map('urldecode', $resultParameters['filter']); |
|
170 | // $filters look like array('name:value1','name:value2','fieldname2:foo') |
||
171 | 4 | $configuredFacets = $this->getConfiguredFacets(); |
|
172 | // first group the filters by facetName - so that we can |
||
173 | // decide later whether we need to do AND or OR for multiple |
||
174 | // filters for a certain facet/field |
||
175 | // $filtersByFacetName look like array('name' => array ('value1', 'value2'), 'fieldname2' => array('foo')) |
||
176 | 4 | $filtersByFacetName = array(); |
|
177 | 4 | foreach ($filters as $filter) { |
|
178 | // only split by the first colon to allow using colons in the filter value itself |
||
179 | 4 | list($filterFacetName, $filterValue) = explode(':', $filter, 2); |
|
180 | 4 | if (in_array($filterFacetName, $configuredFacets)) { |
|
181 | 4 | $filtersByFacetName[$filterFacetName][] = $filterValue; |
|
182 | 4 | } |
|
183 | 4 | } |
|
184 | |||
185 | 4 | foreach ($filtersByFacetName as $facetName => $filterValues) { |
|
186 | 4 | $facetConfiguration = $this->allConfiguredFacets[$facetName . '.']; |
|
187 | 4 | $filterEncoder = $this->facetRendererFactory->getFacetFilterEncoderByFacetName($facetName); |
|
188 | |||
189 | 4 | $tag = ''; |
|
190 | 4 | if ($facetConfiguration['keepAllOptionsOnSelection'] == 1 |
|
191 | 4 | || $this->configuration->getSearchFacetingKeepAllFacetsOnSelection() |
|
192 | 4 | ) { |
|
193 | 3 | $tag = '{!tag=' . addslashes($facetConfiguration['field']) . '}'; |
|
194 | 3 | } |
|
195 | |||
196 | 4 | $filterParts = array(); |
|
197 | 4 | foreach ($filterValues as $filterValue) { |
|
198 | 4 | if (!is_null($filterEncoder)) { |
|
199 | $filterOptions = $facetConfiguration[$facetConfiguration['type'] . '.']; |
||
200 | if (empty($filterOptions)) { |
||
201 | $filterOptions = array(); |
||
202 | } |
||
203 | |||
204 | $filterValue = $filterEncoder->decodeFilter($filterValue, |
||
205 | $filterOptions); |
||
206 | $filterParts[] = $facetConfiguration['field'] . ':' . $filterValue; |
||
207 | } else { |
||
208 | 4 | $filterParts[] = $facetConfiguration['field'] . ':"' . addslashes($filterValue) . '"'; |
|
209 | } |
||
210 | 4 | } |
|
211 | |||
212 | 4 | $operator = ($facetConfiguration['operator'] == 'OR') ? ' OR ' : ' AND '; |
|
213 | 4 | $this->facetFilters[] = $tag . '(' . implode($operator, |
|
214 | 4 | $filterParts) . ')'; |
|
215 | 4 | } |
|
216 | 4 | } |
|
217 | 27 | } |
|
218 | |||
219 | /** |
||
220 | * Gets the facets as configured through TypoScript |
||
221 | * |
||
222 | * @return array An array of facet names as specified in TypoScript |
||
223 | */ |
||
224 | 4 | protected function getConfiguredFacets() |
|
241 | } |
||
242 |