Completed
Pull Request — master (#808)
by
unknown
26:57 queued 23:22
created

SolrService::getSolrconfigName()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3.0067

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 10
cts 11
cp 0.9091
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 10
nc 3
nop 0
crap 3.0067
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 2 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\System\Configuration\TypoScriptConfiguration;
28
use ApacheSolrForTypo3\Solr\System\Solr\Service\StopWordParser;
29
use ApacheSolrForTypo3\Solr\System\Solr\Service\SynonymParser;
30
use TYPO3\CMS\Core\Utility\GeneralUtility;
31
32
/**
33
 * Solr Service Access
34
 *
35
 * @author Ingo Renner <[email protected]>
36
 */
37
class SolrService extends \Apache_Solr_Service
38
{
39
    const LUKE_SERVLET = 'admin/luke';
40
    const SYSTEM_SERVLET = 'admin/system';
41
    const PLUGINS_SERVLET = 'admin/plugins';
42
    const CORES_SERVLET = 'admin/cores';
43
    const SCHEMA_SERVLET = 'schema';
44
    const SYNONYMS_SERVLET = 'schema/analysis/synonyms/';
45
    const STOPWORDS_SERVLET = 'schema/analysis/stopwords/';
46
47
    const SCHEME_HTTP = 'http';
48
    const SCHEME_HTTPS = 'https';
49
50
    /**
51
     * Server connection scheme. http or https.
52
     *
53
     * @var string
54
     */
55
    protected $_scheme = self::SCHEME_HTTP;
56
57
    /**
58
     * Constructed servlet URL for Luke
59
     *
60
     * @var string
61
     */
62
    protected $_lukeUrl;
63
64
    /**
65
     * Constructed servlet URL for plugin information
66
     *
67
     * @var string
68
     */
69
    protected $_pluginsUrl;
70
71
    /**
72
     * @var string
73
     */
74
    protected $_coresUrl;
75
76
    /**
77
     * @var string
78
     */
79
    protected $_extractUrl;
80
81
    /**
82
     * @var string
83
     */
84
    protected $_synonymsUrl;
85
86
    /**
87
     * @var string
88
     */
89
    protected $_stopWordsUrl;
90
91
    /**
92
     * @var string
93
     */
94
    protected $_schemaUrl;
95
96
    /**
97
     * @var bool
98
     */
99
    protected $debug = false;
100
101
    /**
102
     * @var \Apache_Solr_Response
103
     */
104
    protected $responseCache = null;
105
106
    /**
107
     * @var bool
108
     */
109
    protected $hasSearched = false;
110
111
    /**
112
     * @var array
113
     */
114
    protected $lukeData = [];
115
116
    protected $systemData = null;
117
    protected $pluginsData = null;
118
119
    protected $schemaName = null;
120
    protected $solrconfigName = null;
121
122
    /**
123
     * @var TypoScriptConfiguration
124
     */
125
    protected $configuration;
126
127
    /**
128
     * @var array
129
     */
130
    protected static $pingCache = [];
131
132
    /**
133
     * @var SynonymParser
134
     */
135
    protected $synonymParser = null;
136
137
    /**
138
     * @var StopWordParser
139
     */
140
    protected $stopWordParser = null;
141
142
    /**
143
     * @var string
144
     */
145
    protected $managedLanguage = '';
146
147
    /**
148
     * Constructor
149
     *
150
     * @param string $host Solr host
151
     * @param string $port Solr port
152
     * @param string $path Solr path
153
     * @param string $scheme Scheme, defaults to http, can be https
154
     * @param TypoScriptConfiguration $typoScriptConfiguration
155
     * @param SynonymParser $synonymParser
156
     * @param StopWordParser $stopWordParser
157
     */
158 66
    public function __construct(
159
        $host = '',
160
        $port = '8983',
161
        $path = '/solr/',
162
        $scheme = 'http',
163
        TypoScriptConfiguration $typoScriptConfiguration = null,
164
        SynonymParser $synonymParser = null,
165
        StopWordParser $stopWordParser = null
166
    ) {
167 66
        $this->setScheme($scheme);
168 65
        $this->configuration = is_null($typoScriptConfiguration) ? Util::getSolrConfiguration() : $typoScriptConfiguration;
169 65
        $this->synonymParser = is_null($synonymParser) ? GeneralUtility::makeInstance(SynonymParser::class) : $synonymParser;
170 65
        $this->stopWordParser = is_null($stopWordParser) ? GeneralUtility::makeInstance(StopWordParser::class) : $stopWordParser;
171
172 65
        $this->initializeTimeoutFromConfiguration();
173
174 65
        parent::__construct($host, $port, $path);
175 65
    }
176
177
    /**
178
     * Initializes the timeout from TypoScript when configuration is present.
179
     *
180
     * @return void
181
     */
182 65
    protected function initializeTimeoutFromConfiguration()
183
    {
184 65
        $timeout = $this->configuration->getSolrTimeout();
185 65
        if ($timeout > 0) {
186 1
            $this->getHttpTransport()->setDefaultTimeout($timeout);
187 1
        }
188 65
    }
189
190
    /**
191
     * Creates a string representation of the Solr connection. Specifically
192
     * will return the Solr URL.
193
     *
194
     * @return string The Solr URL.
195
     */
196 40
    public function __toString()
197
    {
198 40
        return $this->_scheme . '://' . $this->_host . ':' . $this->_port . $this->_path;
199
    }
200
201
    /**
202
     * Returns the current time in milliseconds.
203
     *
204
     * @return double
205
     */
206 1
    protected function getMilliseconds()
207
    {
208 1
        return GeneralUtility::milliseconds();
209
    }
210
211
    /**
212
     * Performs a search.
213
     *
214
     * @param string $query query string / search term
215
     * @param int $offset result offset for pagination
216
     * @param int $limit number of results to retrieve
217
     * @param array $params additional HTTP GET parameters
218
     * @param string $method The HTTP method (Apache_Solr_Service::METHOD_GET or Apache_Solr_Service::METHOD::POST)
219
     * @return \Apache_Solr_Response Solr response
220
     * @throws \RuntimeException if Solr returns a HTTP status code other than 200
221
     */
222 26
    public function search($query, $offset = 0, $limit = 10, $params = array(), $method = self::METHOD_GET)
223
    {
224 26
        $response = parent::search($query, $offset, $limit, $params, $method);
225 26
        $this->hasSearched = true;
226
227 26
        $this->responseCache = $response;
228
229 26
        if ($response->getHttpStatus() != 200) {
230 1
            throw new \RuntimeException(
231
                'Invalid query. Solr returned an error: '
232 1
                . $response->getHttpStatus() . ' '
233 1
                . $response->getHttpStatusMessage(),
234
                1293109870
235 1
            );
236
        }
237
238 25
        return $response;
239
    }
240
241
    /**
242
     * Call the /admin/ping servlet, can be used to quickly tell if a connection to the
243
     * server is available.
244
     *
245
     * Simply overrides the SolrPhpClient implementation, changing ping from a
246
     * HEAD to a GET request, see http://forge.typo3.org/issues/44167
247
     *
248
     * Also does not report the time, see https://forge.typo3.org/issues/64551
249
     *
250
     * @param float|int $timeout maximum time to wait for ping in seconds, -1 for unlimited (default is 2)
251
     * @param boolean $useCache indicates if the ping result should be cached in the instance or not
252
     * @return bool TRUE if Solr can be reached, FALSE if not
253
     */
254 37
    public function ping($timeout = 2, $useCache = true)
255
    {
256 37
        $httpResponse = $this->performPingRequest($timeout, $useCache);
257 37
        return ($httpResponse->getStatusCode() === 200);
258
    }
259
260
    /**
261
     * Call the /admin/ping servlet, can be used to get the runtime of a ping request.
262
     *
263
     * @param float|int $timeout maximum time to wait for ping in seconds, -1 for unlimited (default is 2)
264
     * @param boolean $useCache indicates if the ping result should be cached in the instance or not
265
     * @return double runtime in milliseconds
266
     * @throws \ApacheSolrForTypo3\Solr\PingFailedException
267
     */
268 1
    public function getPingRoundTripRuntime($timeout = 2, $useCache = true)
269
    {
270 1
        $start = $this->getMilliseconds();
271 1
        $httpResponse = $this->performPingRequest($timeout, $useCache);
272 1
        $end = $this->getMilliseconds();
273
274 1
        if ($httpResponse->getStatusCode() !== 200) {
275
            $message = 'Solr ping failed with unexpected response code: ' . $httpResponse->getStatusCode();
276
            /** @var $exception \ApacheSolrForTypo3\Solr\PingFailedException */
277
            $exception = GeneralUtility::makeInstance('ApacheSolrForTypo3\Solr\PingFailedException', $message);
278
            $exception->setHttpResponse($httpResponse);
279
            throw $exception;
280
        }
281
282 1
        return $end - $start;
283
    }
284
285
    /**
286
     * Performs a ping request and returns the result.
287
     *
288
     * @param int $timeout
289
     * @param boolean $useCache indicates if the ping result should be cached in the instance or not
290
     * @return \Apache_Solr_HttpTransport_Response
291
     */
292 38
    protected function performPingRequest($timeout = 2, $useCache = true)
293
    {
294 38
        $cacheKey = (string) ($this);
295 38
        if ($useCache && isset(static::$pingCache[$cacheKey])) {
296 32
            return static::$pingCache[$cacheKey];
297
        }
298
299 38
        $pingResult = $this->getHttpTransport()->performGetRequest($this->_pingUrl, $timeout);
300
301 38
        if ($useCache) {
302 37
            static::$pingCache[$cacheKey] = $pingResult;
303 37
        }
304
305 38
        return $pingResult;
306
    }
307
308
    /**
309
     * Performs a content and meta data extraction request.
310
     *
311
     * @param ExtractingQuery $query An extraction query
312
     * @return array An array containing the extracted content [0] and meta data [1]
313
     */
314 1
    public function extractByQuery(ExtractingQuery $query)
315
    {
316
        $headers = array(
317 1
            'Content-Type' => 'multipart/form-data; boundary=' . $query->getMultiPartPostDataBoundary()
318 1
        );
319
320
        try {
321 1
            $response = $this->requestServlet(
322 1
                self::EXTRACT_SERVLET,
323 1
                $query->getQueryParameters(),
324 1
                'POST',
325 1
                $headers,
326 1
                $query->getRawPostFileData()
327 1
            );
328 1
        } catch (\Exception $e) {
329
            GeneralUtility::devLog('Extracting text and meta data through Solr Cell over HTTP POST',
330
                'solr', 3, array(
331
                    'query' => (array)$query,
332
                    'parameters' => $query->getQueryParameters(),
333
                    'file' => $query->getFile(),
334
                    'headers' => $headers,
335
                    'query url' => self::EXTRACT_SERVLET,
336
                    'exception' => $e->getMessage()
337
                ));
338
        }
339
340
        return array(
341 1
            $response->extracted,
342 1
            (array)$response->extracted_metadata
343 1
        );
344
    }
345
346
    /**
347
     * Make a request to a servlet (a path) that's not a standard path.
348
     *
349
     * @param string $servlet Path to be added to the base Solr path.
350
     * @param array $parameters Optional, additional request parameters when constructing the URL.
351
     * @param string $method HTTP method to use, defaults to GET.
352
     * @param array $requestHeaders Key value pairs of header names and values. Should include 'Content-Type' for POST and PUT.
353
     * @param string $rawPost Must be an empty string unless method is POST or PUT.
354
     * @param float|bool $timeout Read timeout in seconds, defaults to FALSE.
355
     * @return \Apache_Solr_Response Response object
356
     * @throws \Apache_Solr_HttpTransportException if returned HTTP status is other than 200
357
     */
358 1
    public function requestServlet(
359
        $servlet,
360
        $parameters = array(),
361
        $method = 'GET',
362
        $requestHeaders = array(),
363
        $rawPost = '',
364
        $timeout = false
365
    ) {
366 1
        $httpTransport = $this->getHttpTransport();
367
368 1
        if ($method == 'GET' || $method == 'HEAD') {
369
            // Make sure we are not sending a request body.
370
            $rawPost = '';
371
        }
372
373
        // Add default parameters
374 1
        $parameters['wt'] = self::SOLR_WRITER;
375 1
        $parameters['json.nl'] = $this->_namedListTreatment;
376 1
        $url = $this->_constructUrl($servlet, $parameters);
377
378 1
        if ($method == self::METHOD_GET) {
379
            $httpResponse = $httpTransport->performGetRequest($url, $timeout);
380 1
        } elseif ($method == self::METHOD_POST) {
381
            // FIXME should respect all headers, not only Content-Type
382 1
            $httpResponse = $httpTransport->performPostRequest($url, $rawPost,
383 1
                $requestHeaders['Content-Type'], $timeout);
384 1
        }
385
386 1
        if (empty($httpResponse)) {
387
            throw new \InvalidArgumentException('$method should be GET or POST');
388
        }
389
390 1
        $solrResponse = new \Apache_Solr_Response($httpResponse,
391 1
            $this->_createDocuments, $this->_collapseSingleValueArrays);
392
393 1
        if ($solrResponse->getHttpStatus() != 200) {
394
            throw new \Apache_Solr_HttpTransportException($solrResponse);
395
        }
396
397 1
        return $solrResponse;
398
    }
399
400
    /**
401
     * Return a valid http URL given this server's scheme, host, port, and path
402
     * and a provided servlet name.
403
     *
404
     * @param string $servlet Servlet name
405
     * @param array $params Additional URL parameters to attach to the end of the URL
406
     * @return string Servlet URL
407
     */
408 65
    protected function _constructUrl($servlet, $params = array())
409
    {
410 65
        $url = parent::_constructUrl($servlet, $params);
411
412 65
        if (!GeneralUtility::isFirstPartOfStr($url, $this->_scheme)) {
413 1
            $parsedUrl = parse_url($url);
414
415
            // unfortunately can't use str_replace as it replace all
416
            // occurrences of $needle and can't be limited to replace only once
417 1
            $url = $this->_scheme . substr($url, strlen($parsedUrl['scheme']));
418 1
        }
419
420 65
        return $url;
421
    }
422
423
    /**
424
     * Returns the set scheme
425
     *
426
     * @return string
427
     */
428
    public function getScheme()
429
    {
430
        return $this->_scheme;
431
    }
432
433
    /**
434
     * Set the scheme used. If empty will fallback to constants
435
     *
436
     * @param string $scheme Either http or https
437
     * @throws \UnexpectedValueException
438
     */
439 66
    public function setScheme($scheme)
440
    {
441
        // Use the provided scheme or use the default
442 66
        if (empty($scheme)) {
443 1
            throw new \UnexpectedValueException('Scheme parameter is empty',
444 1
                1380756390);
445
        } else {
446 65
            if (in_array($scheme,
447 65
                array(self::SCHEME_HTTP, self::SCHEME_HTTPS))) {
448 65
                $this->_scheme = $scheme;
449 65
            } else {
450
                throw new \UnexpectedValueException('Unsupported scheme parameter, scheme must be http or https',
451
                    1380756442);
452
            }
453
        }
454
455 65
        if ($this->_urlsInited) {
456
            $this->_initUrls();
457
        }
458 65
    }
459
460
    /**
461
     * get field meta data for the index
462
     *
463
     * @param int $numberOfTerms Number of top terms to fetch for each field
464
     * @return array
465
     */
466
    public function getFieldsMetaData($numberOfTerms = 0)
467
    {
468
        return $this->getLukeMetaData($numberOfTerms)->fields;
469
    }
470
471
    /**
472
     * Retrieves meta data about the index from the luke request handler
473
     *
474
     * @param int $numberOfTerms Number of top terms to fetch for each field
475
     * @return \Apache_Solr_Response Index meta data
476
     */
477
    public function getLukeMetaData($numberOfTerms = 0)
478
    {
479
        if (!isset($this->lukeData[$numberOfTerms])) {
480
            $lukeUrl = $this->_constructUrl(
481
                self::LUKE_SERVLET,
482
                array(
483
                    'numTerms' => $numberOfTerms,
484
                    'wt' => self::SOLR_WRITER,
485
                    'fl' => '*'
486
                )
487
            );
488
489
            $this->lukeData[$numberOfTerms] = $this->_sendRawGet($lukeUrl);
490
        }
491
492
        return $this->lukeData[$numberOfTerms];
493
    }
494
495
    /**
496
     * Central method for making a get operation against this Solr Server
497
     *
498
     * @param string $url
499
     * @param float|bool $timeout Read timeout in seconds
500
     * @return \Apache_Solr_Response
501
     */
502 32
    protected function _sendRawGet($url, $timeout = false)
503
    {
504 32
        $logSeverity = 0; // info
505
506
        try {
507 32
            $response = parent::_sendRawGet($url, $timeout);
508 32
        } catch (\Apache_Solr_HttpTransportException $e) {
0 ignored issues
show
Bug introduced by
The class Apache_Solr_HttpTransportException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
509 2
            $logSeverity = 3; // fatal error
510 2
            $response = $e->getResponse();
511
        }
512
513 32
        if ($this->configuration->getLoggingQueryRawGet() || $response->getHttpStatus() != 200) {
514
            $logData = array(
515 2
                'query url' => $url,
516
                'response' => (array)$response
517 2
            );
518
519 2
            if (!empty($e)) {
520 2
                $logData['exception'] = $e->__toString();
521 2
            } else {
522
                // trigger data parsing
523
                $response->response;
524
                $logData['response data'] = print_r($response, true);
525
            }
526
527 2
            GeneralUtility::devLog('Querying Solr using GET', 'solr',
528 2
                $logSeverity, $logData);
529 2
        }
530
531 32
        return $response;
532
    }
533
534
    /**
535
     * Returns whether a search has been executed or not.
536
     *
537
     * @return bool TRUE if a search has been executed, FALSE otherwise
538
     */
539
    public function hasSearched()
540
    {
541
        return $this->hasSearched;
542
    }
543
544
    /**
545
     * Gets the most recent response (if any)
546
     *
547
     * @return \Apache_Solr_Response Most recent response, or NULL if a search has not been executed yet.
548
     */
549 1
    public function getResponse()
550
    {
551 1
        return $this->responseCache;
552
    }
553
554
    /**
555
     * Enable/Disable debug mode
556
     *
557
     * @param bool $debug TRUE to enable debug mode, FALSE to turn off, off by default
558
     */
559
    public function setDebug($debug)
560
    {
561
        $this->debug = (boolean)$debug;
562
    }
563
564
    /**
565
     * Gets information about the plugins installed in Solr
566
     *
567
     * @return array A nested array of plugin data.
568
     */
569
    public function getPluginsInformation()
570
    {
571
        if (empty($this->pluginsData)) {
572
            $pluginsInformation = $this->_sendRawGet($this->_pluginsUrl);
573
574
            // access a random property to trigger response parsing
575
            $pluginsInformation->responseHeader;
576
            $this->pluginsData = $pluginsInformation;
577
        }
578
579
        return $this->pluginsData;
580
    }
581
582
    /**
583
     * Gets the name of the schema.xml file installed and in use on the Solr
584
     * server.
585
     *
586
     * @return string Name of the active schema.xml
587
     */
588 1
    public function getSchemaName()
589
    {
590 1
        if (is_null($this->schemaName)) {
591 1
            $systemInformation = $this->getSystemInformation();
592 1
            $this->schemaName = $systemInformation->core->schema;
593 1
        }
594
595 1
        return $this->schemaName;
596
    }
597
598
    /**
599
     * Gets information about the Solr server
600
     *
601
     * @return array A nested array of system data.
602
     */
603 4
    public function getSystemInformation()
604
    {
605 4
        if (empty($this->systemData)) {
606 4
            $systemInformation = $this->system();
607
608
            // access a random property to trigger response parsing
609 4
            $systemInformation->responseHeader;
610 4
            $this->systemData = $systemInformation;
611 4
        }
612
613 4
        return $this->systemData;
614
    }
615
616
    /**
617
     * Gets the name of the solrconfig.xml file installed and in use on the Solr
618
     * server.
619
     *
620
     * @return string Name of the active solrconfig.xml
621
     */
622 1
    public function getSolrconfigName()
623
    {
624 1
        if (is_null($this->solrconfigName)) {
625 1
            $solrconfigXmlUrl = $this->_scheme . '://'
626 1
                . $this->_host . ':' . $this->_port
627 1
                . $this->_path . 'admin/file/?file=solrconfig.xml';
628
629 1
            $solrconfigXml = simplexml_load_file($solrconfigXmlUrl);
630 1
            if ($solrconfigXml === false) {
631
                throw new \InvalidArgumentException('No valid xml response from schema file: ' . $solrconfigXmlUrl);
632
            }
633 1
            $this->solrconfigName = (string)$solrconfigXml->attributes()->name;
634 1
        }
635
636 1
        return $this->solrconfigName;
637
    }
638
639
    /**
640
     * Gets the Solr server's version number.
641
     *
642
     * @return string Solr version number
643
     */
644 2
    public function getSolrServerVersion()
645
    {
646 2
        $systemInformation = $this->getSystemInformation();
647
648
        // don't know why $systemInformation->lucene->solr-spec-version won't work
649 2
        $luceneInformation = (array)$systemInformation->lucene;
650 2
        return $luceneInformation['solr-spec-version'];
651
    }
652
653
    /**
654
     * Deletes all index documents of a certain type and does a commit
655
     * afterwards.
656
     *
657
     * @param string $type The type of documents to delete, usually a table name.
658
     * @param bool $commit Will commit immediately after deleting the documents if set, defaults to TRUE
659
     */
660
    public function deleteByType($type, $commit = true)
661
    {
662
        $this->deleteByQuery('type:' . trim($type));
663
664
        if ($commit) {
665
            $this->commit(false, false, false);
666
        }
667
    }
668
669
    /**
670
     * Raw Delete Method. Takes a raw post body and sends it to the update service. Body should be
671
     * a complete and well formed "delete" xml document
672
     *
673
     * @param string $rawPost Expected to be utf-8 encoded xml document
674
     * @param float|int $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
675
     * @return \Apache_Solr_Response
676
     */
677 5
    public function delete($rawPost, $timeout = 3600)
678
    {
679 5
        $response = $this->_sendRawPost($this->_updateUrl, $rawPost, $timeout);
680
681 5
        GeneralUtility::devLog(
682 5
            'Delete Query sent.',
683 5
            'solr',
684 5
            1,
685
            array(
686 5
                'query' => $rawPost,
687 5
                'query url' => $this->_updateUrl,
688
                'response' => (array)$response
689 5
            )
690 5
        );
691
692 5
        return $response;
693
    }
694
695
    /**
696
     * Central method for making a post operation against this Solr Server
697
     *
698
     * @param string $url
699
     * @param string $rawPost
700
     * @param float|bool $timeout Read timeout in seconds
701
     * @param string $contentType
702
     * @return \Apache_Solr_Response
703
     */
704 48
    protected function _sendRawPost(
705
        $url,
706
        $rawPost,
707
        $timeout = false,
708
        $contentType = 'text/xml; charset=UTF-8'
709
    ) {
710 48
        $logSeverity = 0; // info
711
712
        try {
713 48
            $response = parent::_sendRawPost($url, $rawPost, $timeout,
714 48
                $contentType);
715 48
        } catch (\Apache_Solr_HttpTransportException $e) {
0 ignored issues
show
Bug introduced by
The class Apache_Solr_HttpTransportException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
716
            $logSeverity = 3; // fatal error
717
            $response = $e->getResponse();
718
        }
719
720 48
        if ($this->configuration->getLoggingQueryRawPost() || $response->getHttpStatus() != 200) {
721
            $logData = array(
722
                'query url' => $url,
723
                'content' => $rawPost,
724
                'response' => (array)$response
725
            );
726
727
            if (!empty($e)) {
728
                $logData['exception'] = $e->__toString();
729
            }
730
731
            GeneralUtility::devLog('Querying Solr using POST', 'solr',
732
                $logSeverity, $logData);
733
        }
734
735 48
        return $response;
736
    }
737
738
    /**
739
     * Get currently configured synonyms
740
     *
741
     * @param string $baseWord If given a base word, retrieves the synonyms for that word only
742
     * @return array
743
     */
744 1
    public function getSynonyms($baseWord = '')
745
    {
746 1
        $this->initializeSynonymsUrl();
747 1
        $synonymsUrl = $this->_synonymsUrl;
748 1
        if (!empty($baseWord)) {
749 1
            $synonymsUrl .= '/' . $baseWord;
750 1
        }
751
752 1
        $response = $this->_sendRawGet($synonymsUrl);
753 1
        return $this->synonymParser->parseJson($baseWord, $response->getRawResponse());
754
    }
755
756
    /**
757
     * Add list of synonyms for base word to managed synonyms map
758
     *
759
     * @param string $baseWord
760
     * @param array $synonyms
761
     *
762
     * @return \Apache_Solr_Response
763
     *
764
     * @throws \Apache_Solr_InvalidArgumentException If $baseWord or $synonyms are empty
765
     */
766 1
    public function addSynonym($baseWord, array $synonyms)
767
    {
768 1
        $this->initializeSynonymsUrl();
769 1
        $json = $this->synonymParser->toJson($baseWord, $synonyms);
770 1
        return $this->_sendRawPost($this->_synonymsUrl, $json,
771 1
            $this->getHttpTransport()->getDefaultTimeout(), 'application/json');
772
    }
773
774
    /**
775
     * Remove a synonym from the synonyms map
776
     *
777
     * @param string $baseWord
778
     * @return \Apache_Solr_Response
779
     * @throws \Apache_Solr_InvalidArgumentException
780
     */
781 1
    public function deleteSynonym($baseWord)
782
    {
783 1
        $this->initializeSynonymsUrl();
784 1
        if (empty($baseWord)) {
785
            throw new \Apache_Solr_InvalidArgumentException('Must provide base word.');
786
        }
787
788 1
        return $this->_sendRawDelete($this->_synonymsUrl . '/' . $baseWord);
789
    }
790
791
    /**
792
     * Central method for making a HTTP DELETE operation against the Solr server
793
     *
794
     * @param string $url
795
     * @param bool|float $timeout Read timeout in seconds
796
     * @return \Apache_Solr_Response
797
     */
798 2
    protected function _sendRawDelete($url, $timeout = false)
799
    {
800 2
        $logSeverity = 0; // info
801
802
        try {
803 2
            $httpTransport = $this->getHttpTransport();
804
805 2
            $httpResponse = $httpTransport->performDeleteRequest($url,
806 2
                $timeout);
807 2
            $solrResponse = new \Apache_Solr_Response($httpResponse,
808 2
                $this->_createDocuments, $this->_collapseSingleValueArrays);
809
810 2
            if ($solrResponse->getHttpStatus() != 200) {
811 2
                throw new \Apache_Solr_HttpTransportException($solrResponse);
812
            }
813 2
        } catch (\Apache_Solr_HttpTransportException $e) {
0 ignored issues
show
Bug introduced by
The class Apache_Solr_HttpTransportException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
814 2
            $logSeverity = 3; // fatal error
815 2
            $solrResponse = $e->getResponse();
816
        }
817
818 2
        if ($this->configuration->getLoggingQueryRawDelete() || $solrResponse->getHttpStatus() != 200) {
819
            $logData = array(
820 2
                'query url' => $url,
821
                'response' => (array)$solrResponse
822 2
            );
823
824 2
            if (!empty($e)) {
825 2
                $logData['exception'] = $e->__toString();
826 2
            } else {
827
                // trigger data parsing
828
                $solrResponse->response;
829
                $logData['response data'] = print_r($solrResponse, true);
830
            }
831
832 2
            GeneralUtility::devLog('Querying Solr using DELETE', 'solr',
833 2
                $logSeverity, $logData);
834 2
        }
835
836 2
        return $solrResponse;
837
    }
838
839
    /**
840
     * Get currently configured stop words
841
     *
842
     * @return array
843
     */
844 1
    public function getStopWords()
845
    {
846 1
        $this->initializeStopWordsUrl();
847 1
        $response = $this->_sendRawGet($this->_stopWordsUrl);
848 1
        return $this->stopWordParser->parseJson($response->getRawResponse());
849
    }
850
851
    /**
852
     * Adds stop words to the managed stop word list
853
     *
854
     * @param array|string $stopWords string for a single word, array for multiple words
855
     * @return \Apache_Solr_Response
856
     * @throws \Apache_Solr_InvalidArgumentException If $stopWords is empty
857
     */
858 1
    public function addStopWords($stopWords)
859
    {
860 1
        $this->initializeStopWordsUrl();
861 1
        $json = $this->stopWordParser->toJson($stopWords);
862 1
        return $this->_sendRawPost($this->_stopWordsUrl, $json,
863 1
            $this->getHttpTransport()->getDefaultTimeout(), 'application/json');
864
    }
865
866
    /**
867
     * Deletes a words from the managed stop word list
868
     *
869
     * @param string $stopWord stop word to delete
870
     * @return \Apache_Solr_Response
871
     * @throws \Apache_Solr_InvalidArgumentException If $stopWords is empty
872
     */
873 1
    public function deleteStopWord($stopWord)
874
    {
875 1
        $this->initializeStopWordsUrl();
876 1
        if (empty($stopWord)) {
877
            throw new \Apache_Solr_InvalidArgumentException('Must provide stop word.');
878
        }
879
880 1
        return $this->_sendRawDelete($this->_stopWordsUrl . '/' . $stopWord);
881
    }
882
883
    /**
884
     * Reloads the current core
885
     *
886
     * @return \Apache_Solr_Response
887
     */
888
    public function reloadCore()
889
    {
890
        $coreName = array_pop(explode('/', trim($this->_path, '/')));
0 ignored issues
show
Bug introduced by
explode('/', trim($this->_path, '/')) cannot be passed to array_pop() as the parameter $array expects a reference.
Loading history...
891
        $coreAdminReloadUrl = $this->_coresUrl . '?action=reload&core=' . $coreName;
892
893
        return $this->_sendRawGet($coreAdminReloadUrl);
894
    }
895
896
    /**
897
     * initializes various URLs, including the Luke URL
898
     *
899
     * @return void
900
     */
901 65
    protected function _initUrls()
902
    {
903 65
        parent::_initUrls();
904
905 65
        $this->_lukeUrl = $this->_constructUrl(
906 65
            self::LUKE_SERVLET,
907
            array(
908 65
                'numTerms' => '0',
909
                'wt' => self::SOLR_WRITER
910 65
            )
911 65
        );
912
913 65
        $this->_pluginsUrl = $this->_constructUrl(
914 65
            self::PLUGINS_SERVLET,
915 65
            array('wt' => self::SOLR_WRITER)
916 65
        );
917
918 65
        $pathElements = explode('/', trim($this->_path, '/'));
919 65
        $this->_coresUrl =
920 65
            $this->_scheme . '://' .
921 65
            $this->_host . ':' .
922 65
            $this->_port . '/' .
923 65
            $pathElements[0] . '/' .
924 65
            self::CORES_SERVLET;
925
926 65
        $this->_schemaUrl = $this->_constructUrl(self::SCHEMA_SERVLET);
927 65
    }
928
929
    /**
930
     * @return void
931
     */
932 1
    protected function initializeSynonymsUrl()
933
    {
934 1
        if (trim($this->_synonymsUrl) !== '') {
935 1
            return;
936
        }
937 1
        $this->_synonymsUrl = $this->_constructUrl(self::SYNONYMS_SERVLET) . $this->getManagedLanguage();
938 1
    }
939
940
    /**
941
     * @return void
942
     */
943 1
    protected function initializeStopWordsUrl()
944
    {
945 1
        if (trim($this->_stopWordsUrl) !== '') {
946 1
            return;
947
        }
948
949 1
        $this->_stopWordsUrl = $this->_constructUrl(self::STOPWORDS_SERVLET) . $this->getManagedLanguage();
950 1
    }
951
952
    /**
953
     * Get the language map name for the text field.
954
     * This is necessary to select the correct synonym map.
955
     *
956
     * @return string
957
     */
958 2
    protected function getManagedLanguage()
959
    {
960 2
        if ($this->managedLanguage !== '') {
961
            return $this->managedLanguage;
962
        }
963
964 2
        $schema = $this->getSchema();
965 2
        $language = 'english';
966
967 2
        if (is_object($schema) && isset($schema->fieldTypes)) {
968 2
            foreach ($schema->fieldTypes as $fieldType) {
969 2
                if ($fieldType->name === 'text') {
970 2
                    foreach ($fieldType->queryAnalyzer->filters as $filter) {
971 2
                        if ($filter->class === 'solr.ManagedSynonymFilterFactory') {
972 2
                            $language = $filter->managed;
973 2
                        }
974 2
                    }
975 2
                }
976 2
            }
977 2
        }
978
979 2
        $this->managedLanguage = $language;
980 2
        return $language;
981
    }
982
983
    /**
984
     * Get the configured schema for the current core
985
     *
986
     * @return \stdClass
987
     */
988 2
    protected function getSchema()
989
    {
990 2
        $response = $this->_sendRawGet($this->_schemaUrl);
991 2
        return json_decode($response->getRawResponse())->schema;
992
    }
993
}
994