Passed
Push — master ( eb988a...82337b )
by Timo
21:29
created

SearchUriBuilder::getResultGroupItemPageUri()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 3
crap 1
1
<?php
2
namespace ApacheSolrForTypo3\Solr\Domain\Search\Uri;
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Grouping\GroupItem;
18
use ApacheSolrForTypo3\Solr\Domain\Search\SearchRequest;
19
use TYPO3\CMS\Core\Utility\GeneralUtility;
20
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
21
22
/**
23
 * SearchUriBuilder
24
 *
25
 * Responsibility:
26
 *
27
 * The SearchUriBuilder is responsible to build uris, that are used in the
28
 * searchContext. It can use the previous request with it's persistent
29
 * arguments to build the url for a search sub request.
30
 *
31
 * @author Frans Saris <[email protected]>
32
 * @author Timo Hund <[email protected]>
33
 * @package ApacheSolrForTypo3\Solr\Domain\Search\Uri
34
 */
35
36
class SearchUriBuilder
37
{
38
39
    /**
40
     * @var UriBuilder
41
     */
42
    protected $uriBuilder;
43
44
    /**
45
     * @var array
46
     */
47
    protected static $preCompiledLinks = [];
48
49
    /**
50
     * @var integer
51
     */
52
    protected static $hitCount;
53
54
    /**
55
     * @var integer
56
     */
57
    protected static $missCount;
58
59
    /**
60
     * @var array
61
     */
62
    protected static $additionalArgumentsCache = [];
63
64
    /**
65
     * @param UriBuilder $uriBuilder
66
     */
67 42
    public function injectUriBuilder(UriBuilder $uriBuilder)
68
    {
69 42
        $this->uriBuilder = $uriBuilder;
70 42
    }
71
72
    /**
73
     * @param SearchRequest $previousSearchRequest
74
     * @param $facetName
75
     * @param $facetValue
76
     * @return string
77
     */
78 32
    public function getAddFacetValueUri(SearchRequest $previousSearchRequest, $facetName, $facetValue)
79
    {
80
        $persistentAndFacetArguments = $previousSearchRequest
81 32
            ->getCopyForSubRequest()->removeAllGroupItemPages()->addFacetValue($facetName, $facetValue)
82 32
            ->getAsArray();
83
84 32
        $additionalArguments = $this->getAdditionalArgumentsFromRequestConfiguration($previousSearchRequest);
85 32
        $additionalArguments = is_array($additionalArguments) ? $additionalArguments : [];
0 ignored issues
show
introduced by
The condition is_array($additionalArguments) can never be false.
Loading history...
86
87 32
        $arguments = $persistentAndFacetArguments + $additionalArguments;
88
89 32
        $pageUid = $this->getTargetPageUidFromRequestConfiguration($previousSearchRequest);
90 32
        return $this->buildLinkWithInMemoryCache($pageUid, $arguments);
91
    }
92
93
    /**
94
     * Removes all other facet values for this name and only set's the passed value for the facet.
95
     *
96
     * @param SearchRequest $previousSearchRequest
97
     * @param $facetName
98
     * @param $facetValue
99
     * @return string
100
     */
101 1
    public function getSetFacetValueUri(SearchRequest $previousSearchRequest, $facetName, $facetValue)
102
    {
103
        $previousSearchRequest = $previousSearchRequest
104 1
            ->getCopyForSubRequest()->removeAllGroupItemPages()->removeAllFacetValuesByName($facetName);
105
106 1
        return $this->getAddFacetValueUri($previousSearchRequest, $facetName, $facetValue);
107
    }
108
109
    /**
110
     * @param SearchRequest $previousSearchRequest
111
     * @param $facetName
112
     * @param $facetValue
113
     * @return string
114
     */
115 5
    public function getRemoveFacetValueUri(SearchRequest $previousSearchRequest, $facetName, $facetValue)
116
    {
117
        $persistentAndFacetArguments = $previousSearchRequest
118 5
            ->getCopyForSubRequest()->removeAllGroupItemPages()->removeFacetValue($facetName, $facetValue)
119 5
            ->getAsArray();
120
121 5
        $additionalArguments = [];
122 5
        if ($previousSearchRequest->getContextTypoScriptConfiguration()->getSearchFacetingFacetLinkUrlParametersUseForFacetResetLinkUrl()) {
123 4
            $additionalArguments = $this->getAdditionalArgumentsFromRequestConfiguration($previousSearchRequest);
124
        }
125 5
        $arguments = $persistentAndFacetArguments + $additionalArguments;
126
127 5
        $pageUid = $this->getTargetPageUidFromRequestConfiguration($previousSearchRequest);
128 5
        return $this->buildLinkWithInMemoryCache($pageUid, $arguments);
129
    }
130
131
    /**
132
     * @param SearchRequest $previousSearchRequest
133
     * @param $facetName
134
     * @return string
135
     */
136 1
    public function getRemoveFacetUri(SearchRequest $previousSearchRequest, $facetName)
137
    {
138
        $persistentAndFacetArguments = $previousSearchRequest
139 1
            ->getCopyForSubRequest()->removeAllGroupItemPages()->removeAllFacetValuesByName($facetName)
140 1
            ->getAsArray();
141
142 1
        $additionalArguments = [];
143 1
        if ($previousSearchRequest->getContextTypoScriptConfiguration()->getSearchFacetingFacetLinkUrlParametersUseForFacetResetLinkUrl()) {
144
            $additionalArguments = $this->getAdditionalArgumentsFromRequestConfiguration($previousSearchRequest);
145
        }
146
147 1
        $arguments = $persistentAndFacetArguments + $additionalArguments;
148
149 1
        $pageUid = $this->getTargetPageUidFromRequestConfiguration($previousSearchRequest);
150 1
        return $this->buildLinkWithInMemoryCache($pageUid, $arguments);
151
    }
152
153
    /**
154
     * @param SearchRequest $previousSearchRequest
155
     * @return string
156
     */
157 4
    public function getRemoveAllFacetsUri(SearchRequest $previousSearchRequest)
158
    {
159
        $persistentAndFacetArguments = $previousSearchRequest
160 4
            ->getCopyForSubRequest()->removeAllGroupItemPages()->removeAllFacets()
161 4
            ->getAsArray();
162
163 4
        $additionalArguments = [];
164 4
        if ($previousSearchRequest->getContextTypoScriptConfiguration()->getSearchFacetingFacetLinkUrlParametersUseForFacetResetLinkUrl()) {
165 4
            $additionalArguments = $this->getAdditionalArgumentsFromRequestConfiguration($previousSearchRequest);
166
        }
167
168 4
        $arguments = $persistentAndFacetArguments + $additionalArguments;
169
170 4
        $pageUid = $this->getTargetPageUidFromRequestConfiguration($previousSearchRequest);
171 4
        return $this->buildLinkWithInMemoryCache($pageUid, $arguments);
172
    }
173
174
    /**
175
     * @param SearchRequest $previousSearchRequest
176
     * @param $page
177
     * @return string
178
     */
179 10
    public function getResultPageUri(SearchRequest $previousSearchRequest, $page)
180
    {
181
        $persistentAndFacetArguments = $previousSearchRequest
182 10
            ->getCopyForSubRequest()->setPage($page)
183 10
            ->getAsArray();
184
185 10
        $pageUid = $this->getTargetPageUidFromRequestConfiguration($previousSearchRequest);
186 10
        return $this->buildLinkWithInMemoryCache($pageUid, $persistentAndFacetArguments);
187
    }
188
189
    /**
190
     * @param SearchRequest $previousSearchRequest
191
     * @param GroupItem $groupItem
192
     * @param int $page
193
     * @return string
194
     */
195 1
    public function getResultGroupItemPageUri(SearchRequest $previousSearchRequest, GroupItem $groupItem, int $page)
196
    {
197
        $persistentAndFacetArguments = $previousSearchRequest
198 1
            ->getCopyForSubRequest()->setGroupItemPage($groupItem->getGroup()->getGroupName(), $groupItem->getGroupValue(), $page)
199 1
            ->getAsArray();
200 1
        $pageUid = $this->getTargetPageUidFromRequestConfiguration($previousSearchRequest);
201 1
        return $this->buildLinkWithInMemoryCache($pageUid, $persistentAndFacetArguments);
202
    }
203
    /**
204
     * @param SearchRequest $previousSearchRequest
205
     * @param $queryString
206
     * @return string
207
     */
208 33
    public function getNewSearchUri(SearchRequest $previousSearchRequest, $queryString)
209
    {
210
        /** @var $request SearchRequest */
211 33
        $contextConfiguration = $previousSearchRequest->getContextTypoScriptConfiguration();
212 33
        $contextSystemLanguage = $previousSearchRequest->getContextSystemLanguageUid();
213 33
        $contextPageUid = $previousSearchRequest->getContextPageUid();
214
215 33
        $request = GeneralUtility::makeInstance(SearchRequest::class, [], $contextPageUid, $contextSystemLanguage, $contextConfiguration);
0 ignored issues
show
Bug introduced by
$contextPageUid of type integer is incompatible with the type array<integer,mixed> expected by parameter $constructorArguments of TYPO3\CMS\Core\Utility\G...Utility::makeInstance(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

215
        $request = GeneralUtility::makeInstance(SearchRequest::class, [], /** @scrutinizer ignore-type */ $contextPageUid, $contextSystemLanguage, $contextConfiguration);
Loading history...
Bug introduced by
$contextConfiguration of type ApacheSolrForTypo3\Solr\...TypoScriptConfiguration is incompatible with the type array<integer,mixed> expected by parameter $constructorArguments of TYPO3\CMS\Core\Utility\G...Utility::makeInstance(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

215
        $request = GeneralUtility::makeInstance(SearchRequest::class, [], $contextPageUid, $contextSystemLanguage, /** @scrutinizer ignore-type */ $contextConfiguration);
Loading history...
216 33
        $arguments = $request->setRawQueryString($queryString)->getAsArray();
217
218 33
        $pageUid = $this->getTargetPageUidFromRequestConfiguration($previousSearchRequest);
219 33
        return $this->buildLinkWithInMemoryCache($pageUid, $arguments);
220
    }
221
222
    /**
223
     * @param SearchRequest $previousSearchRequest
224
     * @param $sortingName
225
     * @param $sortingDirection
226
     * @return string
227
     */
228 31
    public function getSetSortingUri(SearchRequest $previousSearchRequest, $sortingName, $sortingDirection)
229
    {
230
        $persistentAndFacetArguments = $previousSearchRequest
231 31
            ->getCopyForSubRequest()->setSorting($sortingName, $sortingDirection)
232 31
            ->getAsArray();
233
234 31
        $pageUid = $this->getTargetPageUidFromRequestConfiguration($previousSearchRequest);
235 31
        return $this->buildLinkWithInMemoryCache($pageUid, $persistentAndFacetArguments);
236
    }
237
238
    /**
239
     * @param SearchRequest $previousSearchRequest
240
     * @return string
241
     */
242 30
    public function getRemoveSortingUri(SearchRequest $previousSearchRequest)
243
    {
244
        $persistentAndFacetArguments = $previousSearchRequest
245 30
            ->getCopyForSubRequest()->removeSorting()
246 30
            ->getAsArray();
247
248 30
        $pageUid = $this->getTargetPageUidFromRequestConfiguration($previousSearchRequest);
249 30
        return $this->buildLinkWithInMemoryCache($pageUid, $persistentAndFacetArguments);
250
    }
251
252
    /**
253
     * @param SearchRequest $previousSearchRequest
254
     * @return string
255
     */
256 26
    public function getCurrentSearchUri(SearchRequest $previousSearchRequest)
257
    {
258
        $persistentAndFacetArguments = $previousSearchRequest
259 26
            ->getCopyForSubRequest()
260 26
            ->getAsArray();
261
262
263 26
        $pageUid = $this->getTargetPageUidFromRequestConfiguration($previousSearchRequest);
264 26
        return $this->buildLinkWithInMemoryCache($pageUid, $persistentAndFacetArguments);
265
    }
266
267
    /**
268
     * @param SearchRequest $request
269
     * @return array
270
     */
271 33
    protected function getAdditionalArgumentsFromRequestConfiguration(SearchRequest $request)
272
    {
273 33
        if ($request->getContextTypoScriptConfiguration() == null) {
274
            return [];
275
        }
276
277 33
        $reQuestId = $request->getId();
278 33
        if (isset(self::$additionalArgumentsCache[$reQuestId])) {
279 30
            return self::$additionalArgumentsCache[$reQuestId];
280
        }
281
282 33
        self::$additionalArgumentsCache[$reQuestId] = $request->getContextTypoScriptConfiguration()
283 33
            ->getSearchFacetingFacetLinkUrlParametersAsArray();
284
285 33
        return self::$additionalArgumentsCache[$reQuestId];
286
    }
287
288
    /**
289
     * @param SearchRequest $request
290
     * @return integer|null
291
     */
292 42
    protected function getTargetPageUidFromRequestConfiguration(SearchRequest $request)
293
    {
294 42
        if ($request->getContextTypoScriptConfiguration() == null) {
295
            return null;
296
        }
297
298 42
        return $request->getContextTypoScriptConfiguration()->getSearchTargetPage();
299
    }
300
301
    /**
302
     * @param integer $pageUid
303
     * @param array $arguments
304
     * @return string
305
     */
306 42
    protected function buildLinkWithInMemoryCache($pageUid, array $arguments)
307
    {
308 42
        $values = [];
309 42
        $structure = $arguments;
310 42
        $this->getSubstitution($structure, $values);
311 42
        $hash = md5($pageUid . json_encode($structure));
312
313 42
        if (isset(self::$preCompiledLinks[$hash])) {
314 33
            self::$hitCount++;
315 33
            $template = self::$preCompiledLinks[$hash];
316
        } else {
317 41
            self::$missCount++;
318 41
            $this->uriBuilder->setTargetPageUid($pageUid);
319 41
            $template = $this->uriBuilder->setArguments($structure)->setUseCacheHash(false)->build();
320 41
            self::$preCompiledLinks[$hash] = $template;
321
        }
322
323 42
        $keys = array_map(function($value) {
324 40
            return urlencode($value);
325 42
        }, array_keys($values));
326 42
        $values = array_map(function($value) {
327 40
            return urlencode($value);
328 42
        }, $values);
329 42
        $uri = str_replace($keys, $values, $template);
330 42
        return $uri;
331
    }
332
333
    /**
334
     * This method is used to build two arrays from a nested array. The first one represents the structure.
335
     * In this structure the values are replaced with the pass to the value. At the same time the values get collected
336
     * in the $values array, with the path as key. This can be used to build a comparable hash from the arguments
337
     * in order to reduce the amount of typolink calls
338
     *
339
     *
340
     * Example input
341
     *
342
     * $data = [
343
     *  'foo' => [
344
     *      'bar' => 111
345
     *   ]
346
     * ]
347
     *
348
     * will return:
349
     *
350
     * $structure = [
351
     *  'foo' => [
352
     *      'bar' => '###foo:bar###'
353
     *   ]
354
     * ]
355
     *
356
     * $values = [
357
     *  '###foo:bar###' => 111
358
     * ]
359
     *
360
     * @param $structure
361
     * @param $values
362
     * @param array $branch
363
     */
364 42
    protected function getSubstitution(array &$structure, array  &$values, array $branch = [])
365
    {
366 42
        foreach ($structure as $key => &$value) {
367 42
            $branch[] = $key;
368 42
            if (is_array($value)) {
369 42
                $this->getSubstitution($value, $values, $branch);
370
            } else {
371 40
                $path = '###' . implode(':', $branch) . '###';
372 40
                $values[$path] = $value;
373 42
                $structure[$key] = $path;
374
            }
375
        }
376 42
    }
377
}
378