Passed
Push — master ( e722e6...567d6a )
by Rafael
37:36
created

Search::search()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 41
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 5.1158

Importance

Changes 0
Metric Value
eloc 24
dl 0
loc 41
ccs 20
cts 24
cp 0.8333
rs 9.2248
c 0
b 0
f 0
cc 5
nc 16
nop 3
crap 5.1158
1
<?php
2
namespace ApacheSolrForTypo3\Solr;
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 3 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\Domain\Search\Query\Query;
28
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration;
29
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
30
use ApacheSolrForTypo3\Solr\System\Solr\ResponseAdapter;
31
use ApacheSolrForTypo3\Solr\System\Solr\SolrCommunicationException;
32
use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection;
33
use TYPO3\CMS\Core\Utility\GeneralUtility;
34
35
/**
36
 * Class to handle solr search requests
37
 *
38
 * @author Ingo Renner <[email protected]>
39
 */
40
class Search
41
{
42
43
    /**
44
     * An instance of the Solr service
45
     *
46
     * @var SolrConnection
47
     */
48
    protected $solr = null;
49
50
    /**
51
     * The search query
52
     *
53
     * @var Query
54
     */
55
    protected $query = null;
56
57
    /**
58
     * The search response
59
     *
60
     * @var ResponseAdapter
61
     */
62
    protected $response = null;
63
64
    /**
65
     * @var TypoScriptConfiguration
66
     */
67
    protected $configuration;
68
69
    // TODO Override __clone to reset $response and $hasSearched
70
71
    /**
72
     * @var \ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager
73
     */
74
    protected $logger = null;
75
76
    /**
77
     * Constructor
78
     *
79
     * @param SolrConnection $solrConnection The Solr connection to use for searching
80
     */
81 57
    public function __construct(SolrConnection $solrConnection = null)
82
    {
83 57
        $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
84
85 57
        $this->solr = $solrConnection;
86
87 57
        if (is_null($solrConnection)) {
88
            /** @var $connectionManager ConnectionManager */
89 7
            $connectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
90 7
            $this->solr = $connectionManager->getConnectionByPageId($GLOBALS['TSFE']->id, Util::getLanguageUid());
91
        }
92
93 57
        $this->configuration = Util::getSolrConfiguration();
94 57
    }
95
96
    /**
97
     * Gets the Solr connection used by this search.
98
     *
99
     * @return SolrConnection Solr connection
100
     */
101
    public function getSolrConnection()
102
    {
103
        return $this->solr;
104
    }
105
106
    /**
107
     * Sets the Solr connection used by this search.
108
     *
109
     * Since ApacheSolrForTypo3\Solr\Search is a \TYPO3\CMS\Core\SingletonInterface, this is needed to
110
     * be able to switch between multiple cores/connections during
111
     * one request
112
     *
113
     * @param SolrConnection $solrConnection
114
     */
115
    public function setSolrConnection(SolrConnection $solrConnection)
116
    {
117
        $this->solr = $solrConnection;
118
    }
119
120
    /**
121
     * Executes a query against a Solr server.
122
     *
123
     * 1) Gets the query string
124
     * 2) Conducts the actual search
125
     * 3) Checks debug settings
126
     *
127
     * @param Query $query The query with keywords, filters, and so on.
128
     * @param int $offset Result offset for pagination.
129
     * @param int $limit Maximum number of results to return. If set to NULL, this value is taken from the query object.
130
     * @return ResponseAdapter Solr response
131
     * @throws \Exception
132
     */
133 53
    public function search(Query $query, $offset = 0, $limit = 10)
134
    {
135 53
        $this->query = $query;
136
137 53
        if (!empty($limit)) {
138 11
            $query->setRows($limit);
139
        }
140 53
        $query->setStart($offset);
141
142
        try {
143 53
            $response = $this->solr->getReadService()->search($query);
144 51
            if ($this->configuration->getLoggingQueryQueryString()) {
145
                $this->logger->log(SolrLogManager::INFO,
146
                    'Querying Solr, getting result',
147
                    [
148
                        'query string' => $query->getQuery(),
149
                        'query parameters' => $query->getRequestBuilder()->build($query)->getParams(),
150 51
                        'response' => json_decode($response->getRawResponse(), true)
151
                    ]
152
                );
153
            }
154 2
        }  catch (SolrCommunicationException $e) {
155 2
            if ($this->configuration->getLoggingExceptions()) {
156 2
                $this->logger->log(
157 2
                    SolrLogManager::ERROR,
158 2
                    'Exception while querying Solr',
159
                    [
160 2
                        'exception' => $e->__toString(),
161 2
                        'query' => (array)$query,
162 2
                        'offset' => $offset,
163 2
                        'limit' => $query->getRows()
164
                    ]
165
                );
166
            }
167
168 2
            throw $e;
169
        }
170
171 51
        $this->response = $response;
172
173 51
        return $this->response;
174
    }
175
176
    /**
177
     * Sends a ping to the solr server to see whether it is available.
178
     *
179
     * @param bool $useCache Set to true if the cache should be used.
180
     * @return bool Returns TRUE on successful ping.
181
     * @throws \Exception Throws an exception in case ping was not successful.
182
     */
183
    public function ping($useCache = true)
184
    {
185
        $solrAvailable = false;
186
187
        try {
188
            if (!$this->solr->getReadService()->ping($useCache)) {
189
                throw new \Exception('Solr Server not responding.', 1237475791);
190
            }
191
192
            $solrAvailable = true;
193
        } catch (\Exception $e) {
194
            if ($this->configuration->getLoggingExceptions()) {
195
                $this->logger->log(
196
                    SolrLogManager::ERROR,
197
                    'Exception while trying to ping the solr server',
198
                    [
199
                        $e->__toString()
200
                    ]
201
                );
202
            }
203
        }
204
205
        return $solrAvailable;
206
    }
207
208
    /**
209
     * Gets the query object.
210
     *
211
     * @return Query
212
     */
213
    public function getQuery()
214
    {
215
        return $this->query;
216
    }
217
218
    /**
219
     * Gets the Solr response
220
     *
221
     * @return ResponseAdapter
222
     */
223 28
    public function getResponse()
224
    {
225 28
        return $this->response;
226
    }
227
228
    public function getRawResponse()
229
    {
230
        return $this->response->getRawResponse();
231
    }
232
233 28
    public function getResponseHeader()
234
    {
235 28
        return $this->getResponse()->responseHeader;
236
    }
237
238 28
    public function getResponseBody()
239
    {
240
        // @extensionScannerIgnoreLine
241 28
        return $this->getResponse()->response;
242
    }
243
244
    /**
245
     * Gets the time Solr took to execute the query and return the result.
246
     *
247
     * @return int Query time in milliseconds
248
     */
249 28
    public function getQueryTime()
250
    {
251 28
        return $this->getResponseHeader()->QTime;
252
    }
253
254
    /**
255
     * Gets the number of results per page.
256
     *
257
     * @return int Number of results per page
258
     */
259
    public function getResultsPerPage()
260
    {
261
        return $this->getResponseHeader()->params->rows;
262
    }
263
264
    /**
265
     * Gets the result offset.
266
     *
267
     * @return int Result offset
268
     */
269
    public function getResultOffset()
270
    {
271
        // @extensionScannerIgnoreLine
272
        return $this->response->response->start;
273
    }
274
275 2
    public function getDebugResponse()
276
    {
277
        // @extensionScannerIgnoreLine
278 2
        return $this->response->debug;
279
    }
280
281 28
    public function getHighlightedContent()
282
    {
283 28
        $highlightedContent = false;
284
285 28
        if ($this->response->highlighting) {
286 28
            $highlightedContent = $this->response->highlighting;
287
        }
288
289 28
        return $highlightedContent;
290
    }
291
}
292