Passed
Push — master ( 0ba0e3...644d9b )
by Timo
19:06
created

setObjectManager()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
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\FacetRegistry;
18
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Sorting\Sorting;
19
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Spellchecking\Suggestion;
20
use TYPO3\CMS\Core\Utility\GeneralUtility;
21
use TYPO3\CMS\Extbase\Object\ObjectManager;
22
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
23
24
/**
25
 * This processor is used to transform the solr response into a
26
 * domain object hierarchy that can be used in the application (controller and view).
27
 *
28
 * @author Frans Saris <[email protected]>
29
 * @author Timo Hund <[email protected]>
30
 * @package ApacheSolrForTypo3\Solr\Domain\Search\ResultSet
31
 */
32
class ResultSetReconstitutionProcessor implements SearchResultSetProcessor
33
{
34
    /**
35
     * @var ObjectManagerInterface
36
     */
37
    protected $objectManager;
38
39
    /**
40
     * @return ObjectManagerInterface
41
     */
42
    public function getObjectManager()
43 46
    {
44
        if ($this->objectManager === null) {
45 46
            $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
46 22
        }
47
        return $this->objectManager;
48 46
    }
49
50
    /**
51
     * @param ObjectManagerInterface $objectManager
52
     */
53
    public function setObjectManager($objectManager)
54 24
    {
55
        $this->objectManager = $objectManager;
56 24
    }
57 24
58
59
    /**
60
     * @return FacetRegistry
61
     */
62
    protected function getFacetRegistry()
63 46
    {
64
        return $this->getObjectManager()->get(FacetRegistry::class);
65 46
    }
66
67
    /**
68
     * The implementation can be used to influence a SearchResultSet that is
69
     * created and processed in the SearchResultSetService.
70
     *
71
     * @param SearchResultSet $resultSet
72
     * @return SearchResultSet
73
     */
74
    public function process(SearchResultSet $resultSet)
75 58
    {
76
        if (!$resultSet instanceof SearchResultSet) {
77 58
            return $resultSet;
78
        }
79
80
        $resultSet = $this->parseResultCount($resultSet);
81 58
        $resultSet = $this->parseSpellCheckingResponseIntoObjects($resultSet);
82 58
        $resultSet = $this->parseSortingIntoObjects($resultSet);
83 58
84
        // here we can reconstitute other domain objects from the solr response
85
        $resultSet = $this->parseFacetsIntoObjects($resultSet);
86 58
87
        return $resultSet;
88 58
    }
89
90 58
    /**
91
     * @param SearchResultSet $resultSet
92
     * @return SearchResultSet
93
     */
94
    protected function parseResultCount(SearchResultSet $resultSet)
95
    {
96
        $response = $resultSet->getResponse();
97 58
        if (!isset($response->response->numFound)) {
0 ignored issues
show
Bug introduced by
The property response does not seem to exist. Did you mean _response?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
98
            return $resultSet;
99 58
        }
100 58
101 6
        $resultSet->setAllResultCount($response->response->numFound);
0 ignored issues
show
Bug introduced by
The property response does not seem to exist. Did you mean _response?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
102
        return $resultSet;
103
    }
104 52
105 52
    /**
106
     * @param SearchResultSet $resultSet
107
     * @return SearchResultSet
108
     */
109
    protected function parseSortingIntoObjects(SearchResultSet $resultSet)
110
    {
111
        $configuration = $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration();
112 58
        $hasSorting = $resultSet->getUsedSearchRequest()->getHasSorting();
113
        $activeSortingName = $resultSet->getUsedSearchRequest()->getSortingName();
114 58
        $activeSortingDirection = $resultSet->getUsedSearchRequest()->getSortingDirection();
115 58
116 58
        // no configuration available
117 58
        if (!isset($configuration)) {
118
            return $resultSet;
119
        }
120 58
121 8
        // no sorting enabled
122
        if (!$configuration->getSearchSorting()) {
123
            return $resultSet;
124
        }
125 50
        foreach ($configuration->getSearchSortingOptionsConfiguration() as $sortingKeyName => $sortingOptions) {
126 26
            $sortingName = rtrim($sortingKeyName, '.');
127
            $selected = false;
128 24
            $direction = $configuration->getSearchSortingDefaultOrderBySortOptionName($sortingName);
129 24
130 24
            // when we have an active sorting in the request we compare the sortingName and mark is as active and
131 24
            // use the direction from the request
132
            if ($hasSorting && $activeSortingName == $sortingName) {
133
                $selected = true;
134
                $direction = $activeSortingDirection;
135 24
            }
136 1
137 1
            $field = $sortingOptions['field'];
138
            $label = $sortingOptions['label'];
139
140 24
            $isResetOption = $field === 'relevance';
141 24
            // @todo allow stdWrap on label
142
            $sorting = new Sorting($resultSet, $sortingName, $field, $direction, $label, $selected, $isResetOption);
143 24
            $resultSet->addSorting($sorting);
144
        }
145 24
146 24
        return $resultSet;
147
    }
148
149 24
    /**
150
     * @param SearchResultSet $resultSet
151
     * @return SearchResultSet
152
     */
153
    private function parseSpellCheckingResponseIntoObjects(SearchResultSet $resultSet)
154
    {
155
        //read the response
156 58
        $response = $resultSet->getResponse();
157
        if (!is_object($response->spellcheck->suggestions)) {
158
            return $resultSet;
159 58
        }
160 58
161 51
        foreach ($response->spellcheck->suggestions as $key => $suggestionData) {
162
            if (!isset($suggestionData->suggestion) && !is_array($suggestionData->suggestion)) {
163
                continue;
164 7
            }
165 4
166 1
            // the key contains the misspelled word expect the internal key "collation"
167
            if ($key == 'collation') {
168
                continue;
169
            }
170 4
            //create the spellchecking object structure
171
            $misspelledTerm = $key;
172
            foreach ($suggestionData->suggestion as $suggestedTerm) {
173
                $suggestion = $this->createSuggestionFromResponseFragment($suggestionData, $suggestedTerm, $misspelledTerm);
174 4
175 4
                //add it to the resultSet
176 4
                $resultSet->addSpellCheckingSuggestion($suggestion);
177
            }
178
        }
179 4
180
        return $resultSet;
181
    }
182
183 7
    /**
184
     * @param \stdClass $suggestionData
185
     * @param string $suggestedTerm
186
     * @param string $misspelledTerm
187
     * @return Suggestion
188
     */
189
    private function createSuggestionFromResponseFragment($suggestionData, $suggestedTerm, $misspelledTerm)
190
    {
191
        $numFound = isset($suggestionData->numFound) ? $suggestionData->numFound : 0;
192 4
        $startOffset = isset($suggestionData->startOffset) ? $suggestionData->startOffset : 0;
193
        $endOffset = isset($suggestionData->endOffset) ? $suggestionData->endOffset : 0;
194 4
195 4
        // by now we avoid to use GeneralUtility::makeInstance, since we only create a value object
196 4
        // and the usage might be a overhead.
197
        $suggestion = new Suggestion($suggestedTerm, $misspelledTerm, $numFound, $startOffset, $endOffset);
198
        return $suggestion;
199
    }
200 4
201 4
    /**
202
     * Parse available facets into objects
203
     *
204
     * @param SearchResultSet $resultSet
205
     * @return SearchResultSet
206
     */
207
    private function parseFacetsIntoObjects(SearchResultSet $resultSet)
208
    {
209
        // Make sure we can access the facet configuration
210 58
        if (!$resultSet->getUsedSearchRequest() || !$resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()) {
211
            return $resultSet;
212
        }
213 58
214 8
        // Read the response
215
        $response = $resultSet->getResponse();
216
        if (!is_object($response->facet_counts)) {
217
            return $resultSet;
218 50
        }
219 50
220 4
        /** @var FacetRegistry $facetRegistry */
221
        $facetRegistry = $this->getFacetRegistry();
222
        $facetsConfiguration = $resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()->getSearchFacetingFacets();
223
224 46
        foreach ($facetsConfiguration as $name => $options) {
225 46
            if (!is_array($options)) {
226
                continue;
227 46
            }
228 44
            $facetName = rtrim($name, '.');
229
            $type = !empty($options['type']) ? $options['type'] : '';
230
231 44
            $parser = $facetRegistry->getPackage($type)->getParser();
232 44
            $facet = $parser->parse($resultSet, $facetName, $options);
233
            if ($facet !== null) {
234 44
                $resultSet->addFacet($facet);
235 44
            }
236 44
        }
237 44
238
        return $resultSet;
239
    }
240
}
241