parseFacetsIntoObjects()   B
last analyzed

Complexity

Conditions 9
Paths 8

Size

Total Lines 34
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 9.0239

Importance

Changes 0
Metric Value
eloc 18
dl 0
loc 34
ccs 14
cts 15
cp 0.9333
rs 8.0555
c 0
b 0
f 0
cc 9
nc 8
nop 1
crap 9.0239
1
<?php
2
namespace ApacheSolrForTypo3\Solr\Domain\Search\ResultSet;
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\Facets\AbstractFacet;
18
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Facets\FacetRegistry;
19
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Facets\RequirementsService;
20
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Sorting\Sorting;
21
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Spellchecking\Suggestion;
22
use TYPO3\CMS\Core\Utility\GeneralUtility;
23
use TYPO3\CMS\Extbase\Object\ObjectManager;
24
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
25
26
/**
27
 * This processor is used to transform the solr response into a
28
 * domain object hierarchy that can be used in the application (controller and view).
29
 *
30
 * @author Frans Saris <[email protected]>
31
 * @author Timo Hund <[email protected]>
32
 */
33
class ResultSetReconstitutionProcessor implements SearchResultSetProcessor
34
{
35
    /**
36
     * @var ObjectManagerInterface
37
     */
38
    protected $objectManager;
39
40
    /**
41
     * @return ObjectManagerInterface
42
     */
43
    public function getObjectManager()
44 61
    {
45
        if ($this->objectManager === null) {
46 61
            $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
47 32
        }
48
        return $this->objectManager;
49 61
    }
50
51
    /**
52
     * @param ObjectManagerInterface $objectManager
53
     */
54
    public function setObjectManager($objectManager)
55 29
    {
56
        $this->objectManager = $objectManager;
57 29
    }
58 29
59
60
    /**
61
     * @return FacetRegistry
62
     */
63
    protected function getFacetRegistry()
64 61
    {
65
        // @extensionScannerIgnoreLine
66 61
        return $this->getObjectManager()->get(FacetRegistry::class);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated: since TYPO3 10.4, will be removed in version 12.0 ( Ignorable by Annotation )

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

66
        return /** @scrutinizer ignore-deprecated */ $this->getObjectManager()->get(FacetRegistry::class);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
67
    }
68
69
    /**
70
     * The implementation can be used to influence a SearchResultSet that is
71
     * created and processed in the SearchResultSetService.
72
     *
73
     * @param SearchResultSet $resultSet
74
     * @return SearchResultSet
75
     */
76 72
    public function process(SearchResultSet $resultSet)
77
    {
78 72
        if (!$resultSet instanceof SearchResultSet) {
0 ignored issues
show
introduced by
$resultSet is always a sub-type of ApacheSolrForTypo3\Solr\...sultSet\SearchResultSet.
Loading history...
79
            return $resultSet;
80
        }
81
82 72
        $resultSet = $this->parseSpellCheckingResponseIntoObjects($resultSet);
83 72
        $resultSet = $this->parseSortingIntoObjects($resultSet);
84 72
85
        // here we can reconstitute other domain objects from the solr response
86
        $resultSet = $this->parseFacetsIntoObjects($resultSet);
87 72
88
        return $resultSet;
89 72
    }
90
91
    /**
92
     * @param SearchResultSet $resultSet
93
     * @return SearchResultSet
94
     */
95
    protected function parseSortingIntoObjects(SearchResultSet $resultSet)
96 72
    {
97
        $configuration = $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration();
98 72
        $hasSorting = $resultSet->getUsedSearchRequest()->getHasSorting();
99 72
        $activeSortingName = $resultSet->getUsedSearchRequest()->getSortingName();
100 72
        $activeSortingDirection = $resultSet->getUsedSearchRequest()->getSortingDirection();
101 4
102
        // no configuration available
103 68
        if (!isset($configuration)) {
104 68
            return $resultSet;
105
        }
106
107
        // no sorting enabled
108
        if (!$configuration->getSearchSorting()) {
109
            return $resultSet;
110
        }
111 72
        foreach ($configuration->getSearchSortingOptionsConfiguration() as $sortingKeyName => $sortingOptions) {
112
            $sortingName = rtrim($sortingKeyName, '.');
113 72
            $selected = false;
114 72
            $direction = $configuration->getSearchSortingDefaultOrderBySortOptionName($sortingName);
115 72
116 72
            // when we have an active sorting in the request we compare the sortingName and mark is as active and
117
            // use the direction from the request
118
            if ($hasSorting && $activeSortingName == $sortingName) {
119 72
                $selected = true;
120 7
                $direction = $activeSortingDirection;
121
            }
122
123
            $field = $sortingOptions['field'];
124 65
            $label = $sortingOptions['label'];
125 32
126
            $isResetOption = $field === 'relevance';
127 33
            // @todo allow stdWrap on label
128 33
            $sorting = $this->getObjectManager()->get(Sorting::class, $resultSet, $sortingName, $field, $direction, $label, $selected, $isResetOption);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated: since TYPO3 10.4, will be removed in version 12.0 ( Ignorable by Annotation )

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

128
            $sorting = /** @scrutinizer ignore-deprecated */ $this->getObjectManager()->get(Sorting::class, $resultSet, $sortingName, $field, $direction, $label, $selected, $isResetOption);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
129 33
            $resultSet->addSorting($sorting);
130 33
        }
131
132
        return $resultSet;
133
    }
134 33
135 1
    /**
136 1
     * @param SearchResultSet $resultSet
137
     * @return SearchResultSet
138
     */
139 33
    private function parseSpellCheckingResponseIntoObjects(SearchResultSet $resultSet)
140 33
    {
141
        //read the response
142 33
        $response = $resultSet->getResponse();
143
144 33
        if (!is_array($response->spellcheck->suggestions)) {
145 33
            return $resultSet;
146
        }
147
148 33
        $misspelledTerm = '';
149
        foreach ($response->spellcheck->suggestions as $key => $suggestionData) {
150
            if (is_string($suggestionData)) {
151
                $misspelledTerm = $key;
152
                continue;
153
            }
154
155 72
            if ($misspelledTerm === '') {
156
                throw new \UnexpectedValueException('No missspelled term before suggestion');
157
            }
158 72
159 72
            if (!is_object($suggestionData) && !is_array($suggestionData->suggestion)) {
160 64
                continue;
161
            }
162
163 8
            foreach ($suggestionData->suggestion as $suggestedTerm) {
164 5
                $suggestion = $this->createSuggestionFromResponseFragment($suggestionData, $suggestedTerm, $misspelledTerm);
165 1
                //add it to the resultSet
166
                $resultSet->addSpellCheckingSuggestion($suggestion);
167
            }
168
169 5
        }
170
171
        return $resultSet;
172
    }
173 5
174 5
    /**
175 5
     * @param \stdClass $suggestionData
176
     * @param string $suggestedTerm
177
     * @param string $misspelledTerm
178 5
     * @return Suggestion
179
     */
180
    private function createSuggestionFromResponseFragment($suggestionData, $suggestedTerm, $misspelledTerm)
181
    {
182 8
        $numFound = isset($suggestionData->numFound) ? $suggestionData->numFound : 0;
183
        $startOffset = isset($suggestionData->startOffset) ? $suggestionData->startOffset : 0;
184
        $endOffset = isset($suggestionData->endOffset) ? $suggestionData->endOffset : 0;
185
186
        // by now we avoid to use GeneralUtility::makeInstance, since we only create a value object
187
        // and the usage might be a overhead.
188
        $suggestion = new Suggestion($suggestedTerm, $misspelledTerm, $numFound, $startOffset, $endOffset);
189
        return $suggestion;
190
    }
191 5
192
    /**
193 5
     * Parse available facets into objects
194 5
     *
195 5
     * @param SearchResultSet $resultSet
196
     * @return SearchResultSet
197
     */
198
    private function parseFacetsIntoObjects(SearchResultSet $resultSet)
199 5
    {
200 5
        // Make sure we can access the facet configuration
201
        if (!$resultSet->getUsedSearchRequest() || !$resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()) {
202
            return $resultSet;
203
        }
204
205
        // Read the response
206
        $response = $resultSet->getResponse();
207
        if (!is_object($response->facet_counts) && !is_object($response->facets)) {
208
            return $resultSet;
209 72
        }
210
211
        /** @var FacetRegistry $facetRegistry */
212 72
        $facetRegistry = $this->getFacetRegistry();
213 7
        $facetsConfiguration = $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()->getSearchFacetingFacets();
214
215
        foreach ($facetsConfiguration as $name => $options) {
216
            if (!is_array($options)) {
217 65
                continue;
218 65
            }
219 4
            $facetName = rtrim($name, '.');
220
            $type = !empty($options['type']) ? $options['type'] : '';
221
222
            $parser = $facetRegistry->getPackage($type)->getParser();
223 61
            $facet = $parser->parse($resultSet, $facetName, $options);
224 61
            if ($facet !== null) {
225
                $resultSet->addFacet($facet);
226 61
            }
227 58
        }
228
229
        $this->applyRequirements($resultSet);
230 58
231 58
        return $resultSet;
232
    }
233 58
234 58
    /**
235 58
     * @param SearchResultSet $resultSet
236 58
     */
237
    protected function applyRequirements(SearchResultSet $resultSet)
238
    {
239
        $requirementsService = $this->getRequirementsService();
240 61
        $facets = $resultSet->getFacets();
241
        foreach ($facets as $facet) {
242 61
            /** @var $facet AbstractFacet */
243
            $requirementsMet = $requirementsService->getAllRequirementsMet($facet);
244
            $facet->setAllRequirementsMet($requirementsMet);
245
        }
246
    }
247
248 61
    /**
249
     * @return RequirementsService
250 61
     */
251 61
    protected function getRequirementsService()
252 61
    {
253
        // @extensionScannerIgnoreLine
254 56
        return $this->getObjectManager()->get(RequirementsService::class);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Object...ManagerInterface::get() has been deprecated: since TYPO3 10.4, will be removed in version 12.0 ( Ignorable by Annotation )

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

254
        return /** @scrutinizer ignore-deprecated */ $this->getObjectManager()->get(RequirementsService::class);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
255 56
    }
256
}
257