Completed
Pull Request — master (#840)
by Timo
13:12
created

SolrService::getSolrconfigName()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3.0067

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 10
cts 11
cp 0.9091
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 11
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\Schema\Schema;
29
use ApacheSolrForTypo3\Solr\System\Solr\Parser\SchemaParser;
30
use ApacheSolrForTypo3\Solr\System\Solr\Parser\StopWordParser;
31
use ApacheSolrForTypo3\Solr\System\Solr\Parser\SynonymParser;
32
use TYPO3\CMS\Core\Utility\GeneralUtility;
33
34
/**
35
 * Solr Service Access
36
 *
37
 * @author Ingo Renner <[email protected]>
38
 */
39
class SolrService extends \Apache_Solr_Service
40
{
41
    const LUKE_SERVLET = 'admin/luke';
42
    const SYSTEM_SERVLET = 'admin/system';
43
    const PLUGINS_SERVLET = 'admin/plugins';
44
    const CORES_SERVLET = 'admin/cores';
45
    const SCHEMA_SERVLET = 'schema';
46
    const SYNONYMS_SERVLET = 'schema/analysis/synonyms/';
47
    const STOPWORDS_SERVLET = 'schema/analysis/stopwords/';
48
49
    const SCHEME_HTTP = 'http';
50
    const SCHEME_HTTPS = 'https';
51
52
    /**
53
     * Server connection scheme. http or https.
54
     *
55
     * @var string
56
     */
57
    protected $_scheme = self::SCHEME_HTTP;
58
59
    /**
60
     * Constructed servlet URL for Luke
61
     *
62
     * @var string
63
     */
64
    protected $_lukeUrl;
65
66
    /**
67
     * Constructed servlet URL for plugin information
68
     *
69
     * @var string
70
     */
71
    protected $_pluginsUrl;
72
73
    /**
74
     * @var string
75
     */
76
    protected $_coresUrl;
77
78
    /**
79
     * @var string
80
     */
81
    protected $_extractUrl;
82
83
    /**
84
     * @var string
85
     */
86
    protected $_synonymsUrl;
87
88
    /**
89
     * @var string
90
     */
91
    protected $_stopWordsUrl;
92
93
    /**
94
     * @var string
95
     */
96
    protected $_schemaUrl;
97
98
    /**
99
     * @var bool
100
     */
101
    protected $debug = false;
102
103
    /**
104
     * @var \Apache_Solr_Response
105
     */
106
    protected $responseCache = null;
107
108
    /**
109
     * @var bool
110
     */
111
    protected $hasSearched = false;
112
113
    /**
114
     * @var array
115
     */
116
    protected $lukeData = [];
117
118
    protected $systemData = null;
119
    protected $pluginsData = null;
120
121
    protected $solrconfigName = null;
122
123
    /**
124
     * @var TypoScriptConfiguration
125
     */
126
    protected $configuration;
127
128
    /**
129
     * @var array
130
     */
131
    protected static $pingCache = [];
132
133
    /**
134
     * @var SynonymParser
135
     */
136
    protected $synonymParser = null;
137
138
    /**
139
     * @var StopWordParser
140
     */
141
    protected $stopWordParser = null;
142
143
    /**
144
     * @var SchemaParser
145
     */
146
    protected $schemaParser = null;
147
148
    /**
149
     * @var Schema
150
     */
151
    protected $schema;
152
153
    /**
154
     * Constructor
155
     *
156
     * @param string $host Solr host
157
     * @param string $port Solr port
158
     * @param string $path Solr path
159
     * @param string $scheme Scheme, defaults to http, can be https
160
     * @param TypoScriptConfiguration $typoScriptConfiguration
161
     * @param SynonymParser $synonymParser
162
     * @param StopWordParser $stopWordParser
163
     * @param SchemaParser $schemaParser
164
     */
165 69
    public function __construct(
166
        $host = '',
167
        $port = '8983',
168
        $path = '/solr/',
169
        $scheme = 'http',
170
        TypoScriptConfiguration $typoScriptConfiguration = null,
171
        SynonymParser $synonymParser = null,
172
        StopWordParser $stopWordParser = null,
173
        SchemaParser $schemaParser = null
174
    ) {
175 69
        $this->setScheme($scheme);
176 68
        $this->configuration = is_null($typoScriptConfiguration) ? Util::getSolrConfiguration() : $typoScriptConfiguration;
177 68
        $this->synonymParser = is_null($synonymParser) ? GeneralUtility::makeInstance(SynonymParser::class) : $synonymParser;
178 68
        $this->stopWordParser = is_null($stopWordParser) ? GeneralUtility::makeInstance(StopWordParser::class) : $stopWordParser;
179 68
        $this->schemaParser = is_null($schemaParser) ? GeneralUtility::makeInstance(SchemaParser::class) : $schemaParser;
180
181 68
        $this->initializeTimeoutFromConfiguration();
182
183 68
        parent::__construct($host, $port, $path);
184 68
    }
185
186
    /**
187
     * Initializes the timeout from TypoScript when configuration is present.
188
     *
189
     * @return void
190
     */
191 68
    protected function initializeTimeoutFromConfiguration()
192
    {
193 68
        $timeout = $this->configuration->getSolrTimeout();
194 68
        if ($timeout > 0) {
195 1
            $this->getHttpTransport()->setDefaultTimeout($timeout);
196
        }
197 68
    }
198
199
    /**
200
     * Creates a string representation of the Solr connection. Specifically
201
     * will return the Solr URL.
202
     *
203
     * @return string The Solr URL.
204
     */
205 40
    public function __toString()
206
    {
207 40
        return $this->_scheme . '://' . $this->_host . ':' . $this->_port . $this->_path;
208
    }
209
210
    /**
211
     * Returns the current time in milliseconds.
212
     *
213
     * @return double
214
     */
215 1
    protected function getMilliseconds()
216
    {
217 1
        return GeneralUtility::milliseconds();
218
    }
219
220
    /**
221
     * Performs a search.
222
     *
223
     * @param string $query query string / search term
224
     * @param int $offset result offset for pagination
225
     * @param int $limit number of results to retrieve
226
     * @param array $params additional HTTP GET parameters
227
     * @param string $method The HTTP method (Apache_Solr_Service::METHOD_GET or Apache_Solr_Service::METHOD::POST)
228
     * @return \Apache_Solr_Response Solr response
229
     * @throws \RuntimeException if Solr returns a HTTP status code other than 200
230
     */
231 26
    public function search($query, $offset = 0, $limit = 10, $params = array(), $method = self::METHOD_GET)
232
    {
233 26
        $response = parent::search($query, $offset, $limit, $params, $method);
234 26
        $this->hasSearched = true;
235
236 26
        $this->responseCache = $response;
237
238 26
        if ($response->getHttpStatus() != 200) {
239 1
            throw new \RuntimeException(
240
                'Invalid query. Solr returned an error: '
241 1
                . $response->getHttpStatus() . ' '
242 1
                . $response->getHttpStatusMessage(),
243 1
                1293109870
244
            );
245
        }
246
247 25
        return $response;
248
    }
249
250
    /**
251
     * Call the /admin/ping servlet, can be used to quickly tell if a connection to the
252
     * server is available.
253
     *
254
     * Simply overrides the SolrPhpClient implementation, changing ping from a
255
     * HEAD to a GET request, see http://forge.typo3.org/issues/44167
256
     *
257
     * Also does not report the time, see https://forge.typo3.org/issues/64551
258
     *
259
     * @param float|int $timeout maximum time to wait for ping in seconds, -1 for unlimited (default is 2)
260
     * @param boolean $useCache indicates if the ping result should be cached in the instance or not
261
     * @return bool TRUE if Solr can be reached, FALSE if not
262
     */
263 37
    public function ping($timeout = 2, $useCache = true)
264
    {
265 37
        $httpResponse = $this->performPingRequest($timeout, $useCache);
266 37
        return ($httpResponse->getStatusCode() === 200);
267
    }
268
269
    /**
270
     * Call the /admin/ping servlet, can be used to get the runtime of a ping request.
271
     *
272
     * @param float|int $timeout maximum time to wait for ping in seconds, -1 for unlimited (default is 2)
273
     * @param boolean $useCache indicates if the ping result should be cached in the instance or not
274
     * @return double runtime in milliseconds
275
     * @throws \ApacheSolrForTypo3\Solr\PingFailedException
276
     */
277 1
    public function getPingRoundTripRuntime($timeout = 2, $useCache = true)
278
    {
279 1
        $start = $this->getMilliseconds();
280 1
        $httpResponse = $this->performPingRequest($timeout, $useCache);
281 1
        $end = $this->getMilliseconds();
282
283 1
        if ($httpResponse->getStatusCode() !== 200) {
284
            $message = 'Solr ping failed with unexpected response code: ' . $httpResponse->getStatusCode();
285
            /** @var $exception \ApacheSolrForTypo3\Solr\PingFailedException */
286
            $exception = GeneralUtility::makeInstance('ApacheSolrForTypo3\Solr\PingFailedException', $message);
287
            $exception->setHttpResponse($httpResponse);
288
            throw $exception;
289
        }
290
291 1
        return $end - $start;
292
    }
293
294
    /**
295
     * Performs a ping request and returns the result.
296
     *
297
     * @param int $timeout
298
     * @param boolean $useCache indicates if the ping result should be cached in the instance or not
299
     * @return \Apache_Solr_HttpTransport_Response
300
     */
301 38
    protected function performPingRequest($timeout = 2, $useCache = true)
302
    {
303 38
        $cacheKey = (string) ($this);
304 38
        if ($useCache && isset(static::$pingCache[$cacheKey])) {
305 32
            return static::$pingCache[$cacheKey];
306
        }
307
308 38
        $pingResult = $this->getHttpTransport()->performGetRequest($this->_pingUrl, $timeout);
309
310 38
        if ($useCache) {
311 37
            static::$pingCache[$cacheKey] = $pingResult;
312
        }
313
314 38
        return $pingResult;
315
    }
316
317
    /**
318
     * Performs a content and meta data extraction request.
319
     *
320
     * @param ExtractingQuery $query An extraction query
321
     * @return array An array containing the extracted content [0] and meta data [1]
322
     */
323 1
    public function extractByQuery(ExtractingQuery $query)
324
    {
325
        $headers = array(
326 1
            'Content-Type' => 'multipart/form-data; boundary=' . $query->getMultiPartPostDataBoundary()
327
        );
328
329
        try {
330 1
            $response = $this->requestServlet(
331 1
                self::EXTRACT_SERVLET,
332 1
                $query->getQueryParameters(),
333 1
                'POST',
334
                $headers,
335 1
                $query->getRawPostFileData()
336
            );
337
        } catch (\Exception $e) {
338
            GeneralUtility::devLog('Extracting text and meta data through Solr Cell over HTTP POST',
339
                'solr', 3, array(
340
                    'query' => (array)$query,
341
                    'parameters' => $query->getQueryParameters(),
342
                    'file' => $query->getFile(),
343
                    'headers' => $headers,
344
                    'query url' => self::EXTRACT_SERVLET,
345
                    'exception' => $e->getMessage()
346
                ));
347
        }
348
349
        return array(
350 1
            $response->extracted,
351 1
            (array)$response->extracted_metadata
352
        );
353
    }
354
355
    /**
356
     * Make a request to a servlet (a path) that's not a standard path.
357
     *
358
     * @param string $servlet Path to be added to the base Solr path.
359
     * @param array $parameters Optional, additional request parameters when constructing the URL.
360
     * @param string $method HTTP method to use, defaults to GET.
361
     * @param array $requestHeaders Key value pairs of header names and values. Should include 'Content-Type' for POST and PUT.
362
     * @param string $rawPost Must be an empty string unless method is POST or PUT.
363
     * @param float|bool $timeout Read timeout in seconds, defaults to FALSE.
364
     * @return \Apache_Solr_Response Response object
365
     * @throws \Apache_Solr_HttpTransportException if returned HTTP status is other than 200
366
     */
367 1
    public function requestServlet(
368
        $servlet,
369
        $parameters = array(),
370
        $method = 'GET',
371
        $requestHeaders = array(),
372
        $rawPost = '',
373
        $timeout = false
374
    ) {
375 1
        $httpTransport = $this->getHttpTransport();
376
377 1
        if ($method == 'GET' || $method == 'HEAD') {
378
            // Make sure we are not sending a request body.
379
            $rawPost = '';
380
        }
381
382
        // Add default parameters
383 1
        $parameters['wt'] = self::SOLR_WRITER;
384 1
        $parameters['json.nl'] = $this->_namedListTreatment;
385 1
        $url = $this->_constructUrl($servlet, $parameters);
386
387 1
        if ($method == self::METHOD_GET) {
388
            $httpResponse = $httpTransport->performGetRequest($url, $timeout);
389 1
        } elseif ($method == self::METHOD_POST) {
390
            // FIXME should respect all headers, not only Content-Type
391 1
            $httpResponse = $httpTransport->performPostRequest($url, $rawPost,
392 1
                $requestHeaders['Content-Type'], $timeout);
393
        }
394
395 1
        if (empty($httpResponse)) {
396
            throw new \InvalidArgumentException('$method should be GET or POST');
397
        }
398
399 1
        $solrResponse = new \Apache_Solr_Response($httpResponse,
400 1
            $this->_createDocuments, $this->_collapseSingleValueArrays);
401
402 1
        if ($solrResponse->getHttpStatus() != 200) {
403
            throw new \Apache_Solr_HttpTransportException($solrResponse);
404
        }
405
406 1
        return $solrResponse;
407
    }
408
409
    /**
410
     * Return a valid http URL given this server's scheme, host, port, and path
411
     * and a provided servlet name.
412
     *
413
     * @param string $servlet Servlet name
414
     * @param array $params Additional URL parameters to attach to the end of the URL
415
     * @return string Servlet URL
416
     */
417 68
    protected function _constructUrl($servlet, $params = array())
418
    {
419 68
        $url = parent::_constructUrl($servlet, $params);
420
421 68
        if (!GeneralUtility::isFirstPartOfStr($url, $this->_scheme)) {
422 2
            $parsedUrl = parse_url($url);
423
424
            // unfortunately can't use str_replace as it replace all
425
            // occurrences of $needle and can't be limited to replace only once
426 2
            $url = $this->_scheme . substr($url, strlen($parsedUrl['scheme']));
427
        }
428
429 68
        return $url;
430
    }
431
432
    /**
433
     * Returns the set scheme
434
     *
435
     * @return string
436
     */
437 1
    public function getScheme()
438
    {
439 1
        return $this->_scheme;
440
    }
441
442
    /**
443
     * Set the scheme used. If empty will fallback to constants
444
     *
445
     * @param string $scheme Either http or https
446
     * @throws \UnexpectedValueException
447
     */
448 69
    public function setScheme($scheme)
449
    {
450
        // Use the provided scheme or use the default
451 69
        if (empty($scheme)) {
452 2
            throw new \UnexpectedValueException('Scheme parameter is empty', 1380756390);
453
        }
454
455 68
        $isHttpOrHttps = in_array($scheme, array(self::SCHEME_HTTP, self::SCHEME_HTTPS));
456 68
        if (!$isHttpOrHttps) {
457 1
            throw new \UnexpectedValueException('Unsupported scheme parameter, scheme must be http or https', 1380756442);
458
        }
459
460
        // we have a valid scheme
461 68
        $this->_scheme = $scheme;
462
463 68
        if ($this->_urlsInited) {
464 1
            $this->_initUrls();
465
        }
466 68
    }
467
468
    /**
469
     * get field meta data for the index
470
     *
471
     * @param int $numberOfTerms Number of top terms to fetch for each field
472
     * @return array
473
     */
474
    public function getFieldsMetaData($numberOfTerms = 0)
475
    {
476
        return $this->getLukeMetaData($numberOfTerms)->fields;
477
    }
478
479
    /**
480
     * Retrieves meta data about the index from the luke request handler
481
     *
482
     * @param int $numberOfTerms Number of top terms to fetch for each field
483
     * @return \Apache_Solr_Response Index meta data
484
     */
485
    public function getLukeMetaData($numberOfTerms = 0)
486
    {
487
        if (!isset($this->lukeData[$numberOfTerms])) {
488
            $lukeUrl = $this->_constructUrl(
489
                self::LUKE_SERVLET,
490
                array(
491
                    'numTerms' => $numberOfTerms,
492
                    'wt' => self::SOLR_WRITER,
493
                    'fl' => '*'
494
                )
495
            );
496
497
            $this->lukeData[$numberOfTerms] = $this->_sendRawGet($lukeUrl);
498
        }
499
500
        return $this->lukeData[$numberOfTerms];
501
    }
502
503
    /**
504
     * Central method for making a get operation against this Solr Server
505
     *
506
     * @param string $url
507
     * @param float|bool $timeout Read timeout in seconds
508
     * @return \Apache_Solr_Response
509
     */
510 33
    protected function _sendRawGet($url, $timeout = false)
511
    {
512 33
        $logSeverity = 0; // info
513
514
        try {
515 33
            $response = parent::_sendRawGet($url, $timeout);
516 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...
517 2
            $logSeverity = 3; // fatal error
518 2
            $response = $e->getResponse();
519
        }
520
521 33
        if ($this->configuration->getLoggingQueryRawGet() || $response->getHttpStatus() != 200) {
522
            $logData = array(
523 2
                'query url' => $url,
524 2
                'response' => (array)$response
525
            );
526
527 2
            if (!empty($e)) {
528 2
                $logData['exception'] = $e->__toString();
529
            } else {
530
                // trigger data parsing
531
                $response->response;
532
                $logData['response data'] = print_r($response, true);
533
            }
534
535 2
            GeneralUtility::devLog('Querying Solr using GET', 'solr',
536
                $logSeverity, $logData);
537
        }
538
539 33
        return $response;
540
    }
541
542
    /**
543
     * Returns whether a search has been executed or not.
544
     *
545
     * @return bool TRUE if a search has been executed, FALSE otherwise
546
     */
547
    public function hasSearched()
548
    {
549
        return $this->hasSearched;
550
    }
551
552
    /**
553
     * Gets the most recent response (if any)
554
     *
555
     * @return \Apache_Solr_Response Most recent response, or NULL if a search has not been executed yet.
556
     */
557 1
    public function getResponse()
558
    {
559 1
        return $this->responseCache;
560
    }
561
562
    /**
563
     * Enable/Disable debug mode
564
     *
565
     * @param bool $debug TRUE to enable debug mode, FALSE to turn off, off by default
566
     */
567
    public function setDebug($debug)
568
    {
569
        $this->debug = (boolean)$debug;
570
    }
571
572
    /**
573
     * Gets information about the plugins installed in Solr
574
     *
575
     * @return array A nested array of plugin data.
576
     */
577
    public function getPluginsInformation()
578
    {
579
        if (empty($this->pluginsData)) {
580
            $pluginsInformation = $this->_sendRawGet($this->_pluginsUrl);
581
582
            // access a random property to trigger response parsing
583
            $pluginsInformation->responseHeader;
584
            $this->pluginsData = $pluginsInformation;
585
        }
586
587
        return $this->pluginsData;
588
    }
589
590
    /**
591
     * Gets the name of the schema.xml file installed and in use on the Solr
592
     * server.
593
     *
594
     * @deprecated use getSchema()->getName() instead will be removed in 7.0
595
     * @return string Name of the active schema.xml
596
     */
597
    public function getSchemaName()
598
    {
599
        GeneralUtility::logDeprecatedFunction();
600
        return $this->getSchema()->getName();
601
    }
602
603
    /**
604
     * Gets information about the Solr server
605
     *
606
     * @return array A nested array of system data.
607
     */
608 3
    public function getSystemInformation()
609
    {
610 3
        if (empty($this->systemData)) {
611 3
            $systemInformation = $this->system();
612
613
            // access a random property to trigger response parsing
614 3
            $systemInformation->responseHeader;
615 3
            $this->systemData = $systemInformation;
616
        }
617
618 3
        return $this->systemData;
619
    }
620
621
    /**
622
     * Gets the name of the solrconfig.xml file installed and in use on the Solr
623
     * server.
624
     *
625
     * @return string Name of the active solrconfig.xml
626
     */
627 1
    public function getSolrconfigName()
628
    {
629 1
        if (is_null($this->solrconfigName)) {
630 1
            $solrconfigXmlUrl = $this->_scheme . '://'
631 1
                . $this->_host . ':' . $this->_port
632 1
                . $this->_path . 'admin/file/?file=solrconfig.xml';
633 1
            $response= $this->_sendRawGet($solrconfigXmlUrl);
634
635 1
            $solrconfigXml = simplexml_load_string($response->getRawResponse());
636 1
            if ($solrconfigXml === false) {
637
                throw new \InvalidArgumentException('No valid xml response from schema file: ' . $solrconfigXmlUrl);
638
            }
639 1
            $this->solrconfigName = (string)$solrconfigXml->attributes()->name;
640
        }
641
642 1
        return $this->solrconfigName;
643
    }
644
645
    /**
646
     * Gets the Solr server's version number.
647
     *
648
     * @return string Solr version number
649
     */
650 2
    public function getSolrServerVersion()
651
    {
652 2
        $systemInformation = $this->getSystemInformation();
653
654
        // don't know why $systemInformation->lucene->solr-spec-version won't work
655 2
        $luceneInformation = (array)$systemInformation->lucene;
656 2
        return $luceneInformation['solr-spec-version'];
657
    }
658
659
    /**
660
     * Deletes all index documents of a certain type and does a commit
661
     * afterwards.
662
     *
663
     * @param string $type The type of documents to delete, usually a table name.
664
     * @param bool $commit Will commit immediately after deleting the documents if set, defaults to TRUE
665
     */
666
    public function deleteByType($type, $commit = true)
667
    {
668
        $this->deleteByQuery('type:' . trim($type));
669
670
        if ($commit) {
671
            $this->commit(false, false, false);
672
        }
673
    }
674
675
    /**
676
     * Raw Delete Method. Takes a raw post body and sends it to the update service. Body should be
677
     * a complete and well formed "delete" xml document
678
     *
679
     * @param string $rawPost Expected to be utf-8 encoded xml document
680
     * @param float|int $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
681
     * @return \Apache_Solr_Response
682
     */
683 5
    public function delete($rawPost, $timeout = 3600)
684
    {
685 5
        $response = $this->_sendRawPost($this->_updateUrl, $rawPost, $timeout);
686
687 5
        GeneralUtility::devLog(
688 5
            'Delete Query sent.',
689 5
            'solr',
690 5
            1,
691
            array(
692 5
                'query' => $rawPost,
693 5
                'query url' => $this->_updateUrl,
694 5
                'response' => (array)$response
695
            )
696
        );
697
698 5
        return $response;
699
    }
700
701
    /**
702
     * Central method for making a post operation against this Solr Server
703
     *
704
     * @param string $url
705
     * @param string $rawPost
706
     * @param float|bool $timeout Read timeout in seconds
707
     * @param string $contentType
708
     * @return \Apache_Solr_Response
709
     */
710 48
    protected function _sendRawPost(
711
        $url,
712
        $rawPost,
713
        $timeout = false,
714
        $contentType = 'text/xml; charset=UTF-8'
715
    ) {
716 48
        $logSeverity = 0; // info
717
718
        try {
719 48
            $response = parent::_sendRawPost($url, $rawPost, $timeout,
720
                $contentType);
721
        } 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...
722
            $logSeverity = 3; // fatal error
723
            $response = $e->getResponse();
724
        }
725
726 48
        if ($this->configuration->getLoggingQueryRawPost() || $response->getHttpStatus() != 200) {
727
            $logData = array(
728
                'query url' => $url,
729
                'content' => $rawPost,
730
                'response' => (array)$response
731
            );
732
733
            if (!empty($e)) {
734
                $logData['exception'] = $e->__toString();
735
            }
736
737
            GeneralUtility::devLog('Querying Solr using POST', 'solr',
738
                $logSeverity, $logData);
739
        }
740
741 48
        return $response;
742
    }
743
744
    /**
745
     * Get currently configured synonyms
746
     *
747
     * @param string $baseWord If given a base word, retrieves the synonyms for that word only
748
     * @return array
749
     */
750 1
    public function getSynonyms($baseWord = '')
751
    {
752 1
        $this->initializeSynonymsUrl();
753 1
        $synonymsUrl = $this->_synonymsUrl;
754 1
        if (!empty($baseWord)) {
755 1
            $synonymsUrl .= '/' . $baseWord;
756
        }
757
758 1
        $response = $this->_sendRawGet($synonymsUrl);
759 1
        return $this->synonymParser->parseJson($baseWord, $response->getRawResponse());
760
    }
761
762
    /**
763
     * Add list of synonyms for base word to managed synonyms map
764
     *
765
     * @param string $baseWord
766
     * @param array $synonyms
767
     *
768
     * @return \Apache_Solr_Response
769
     *
770
     * @throws \Apache_Solr_InvalidArgumentException If $baseWord or $synonyms are empty
771
     */
772 1
    public function addSynonym($baseWord, array $synonyms)
773
    {
774 1
        $this->initializeSynonymsUrl();
775 1
        $json = $this->synonymParser->toJson($baseWord, $synonyms);
776 1
        return $this->_sendRawPost($this->_synonymsUrl, $json,
777 1
            $this->getHttpTransport()->getDefaultTimeout(), 'application/json');
778
    }
779
780
    /**
781
     * Remove a synonym from the synonyms map
782
     *
783
     * @param string $baseWord
784
     * @return \Apache_Solr_Response
785
     * @throws \Apache_Solr_InvalidArgumentException
786
     */
787 1
    public function deleteSynonym($baseWord)
788
    {
789 1
        $this->initializeSynonymsUrl();
790 1
        if (empty($baseWord)) {
791
            throw new \Apache_Solr_InvalidArgumentException('Must provide base word.');
792
        }
793
794 1
        return $this->_sendRawDelete($this->_synonymsUrl . '/' . $baseWord);
795
    }
796
797
    /**
798
     * Central method for making a HTTP DELETE operation against the Solr server
799
     *
800
     * @param string $url
801
     * @param bool|float $timeout Read timeout in seconds
802
     * @return \Apache_Solr_Response
803
     */
804 2
    protected function _sendRawDelete($url, $timeout = false)
805
    {
806 2
        $logSeverity = 0; // info
807
808
        try {
809 2
            $httpTransport = $this->getHttpTransport();
810
811 2
            $httpResponse = $httpTransport->performDeleteRequest($url,
812
                $timeout);
813 2
            $solrResponse = new \Apache_Solr_Response($httpResponse,
814 2
                $this->_createDocuments, $this->_collapseSingleValueArrays);
815
816 2
            if ($solrResponse->getHttpStatus() != 200) {
817 2
                throw new \Apache_Solr_HttpTransportException($solrResponse);
818
            }
819 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...
820 2
            $logSeverity = 3; // fatal error
821 2
            $solrResponse = $e->getResponse();
822
        }
823
824 2
        if ($this->configuration->getLoggingQueryRawDelete() || $solrResponse->getHttpStatus() != 200) {
825
            $logData = array(
826 2
                'query url' => $url,
827 2
                'response' => (array)$solrResponse
828
            );
829
830 2
            if (!empty($e)) {
831 2
                $logData['exception'] = $e->__toString();
832
            } else {
833
                // trigger data parsing
834
                $solrResponse->response;
835
                $logData['response data'] = print_r($solrResponse, true);
836
            }
837
838 2
            GeneralUtility::devLog('Querying Solr using DELETE', 'solr',
839
                $logSeverity, $logData);
840
        }
841
842 2
        return $solrResponse;
843
    }
844
845
    /**
846
     * Get currently configured stop words
847
     *
848
     * @return array
849
     */
850 1
    public function getStopWords()
851
    {
852 1
        $this->initializeStopWordsUrl();
853 1
        $response = $this->_sendRawGet($this->_stopWordsUrl);
854 1
        return $this->stopWordParser->parseJson($response->getRawResponse());
855
    }
856
857
    /**
858
     * Adds stop words to the managed stop word list
859
     *
860
     * @param array|string $stopWords string for a single word, array for multiple words
861
     * @return \Apache_Solr_Response
862
     * @throws \Apache_Solr_InvalidArgumentException If $stopWords is empty
863
     */
864 1
    public function addStopWords($stopWords)
865
    {
866 1
        $this->initializeStopWordsUrl();
867 1
        $json = $this->stopWordParser->toJson($stopWords);
868 1
        return $this->_sendRawPost($this->_stopWordsUrl, $json,
869 1
            $this->getHttpTransport()->getDefaultTimeout(), 'application/json');
870
    }
871
872
    /**
873
     * Deletes a words from the managed stop word list
874
     *
875
     * @param string $stopWord stop word to delete
876
     * @return \Apache_Solr_Response
877
     * @throws \Apache_Solr_InvalidArgumentException If $stopWords is empty
878
     */
879 1
    public function deleteStopWord($stopWord)
880
    {
881 1
        $this->initializeStopWordsUrl();
882 1
        if (empty($stopWord)) {
883
            throw new \Apache_Solr_InvalidArgumentException('Must provide stop word.');
884
        }
885
886 1
        return $this->_sendRawDelete($this->_stopWordsUrl . '/' . $stopWord);
887
    }
888
889
    /**
890
     * Reloads the current core
891
     *
892
     * @return \Apache_Solr_Response
893
     */
894
    public function reloadCore()
895
    {
896
        $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...
897
        $coreAdminReloadUrl = $this->_coresUrl . '?action=reload&core=' . $coreName;
898
899
        return $this->_sendRawGet($coreAdminReloadUrl);
900
    }
901
902
    /**
903
     * initializes various URLs, including the Luke URL
904
     *
905
     * @return void
906
     */
907 68
    protected function _initUrls()
908
    {
909 68
        parent::_initUrls();
910
911 68
        $this->_lukeUrl = $this->_constructUrl(
912 68
            self::LUKE_SERVLET,
913
            array(
914 68
                'numTerms' => '0',
915 68
                'wt' => self::SOLR_WRITER
916
            )
917
        );
918
919 68
        $this->_pluginsUrl = $this->_constructUrl(
920 68
            self::PLUGINS_SERVLET,
921 68
            array('wt' => self::SOLR_WRITER)
922
        );
923
924 68
        $pathElements = explode('/', trim($this->_path, '/'));
925 68
        $this->_coresUrl =
926 68
            $this->_scheme . '://' .
927 68
            $this->_host . ':' .
928 68
            $this->_port . '/' .
929 68
            $pathElements[0] . '/' .
930 68
            self::CORES_SERVLET;
931
932 68
        $this->_schemaUrl = $this->_constructUrl(self::SCHEMA_SERVLET);
933 68
    }
934
935
    /**
936
     * @return void
937
     */
938 1
    protected function initializeSynonymsUrl()
939
    {
940 1
        if (trim($this->_synonymsUrl) !== '') {
941 1
            return;
942
        }
943 1
        $this->_synonymsUrl = $this->_constructUrl(self::SYNONYMS_SERVLET) . $this->getSchema()->getLanguage();
944 1
    }
945
946
    /**
947
     * @return void
948
     */
949 1
    protected function initializeStopWordsUrl()
950
    {
951 1
        if (trim($this->_stopWordsUrl) !== '') {
952 1
            return;
953
        }
954
955 1
        $this->_stopWordsUrl = $this->_constructUrl(self::STOPWORDS_SERVLET) . $this->getSchema()->getLanguage();
956 1
    }
957
958
    /**
959
     * Get the configured schema for the current core.
960
     *
961
     * @return Schema
962
     */
963 3
    public function getSchema()
964
    {
965 3
        if ($this->schema !== null) {
966
            return $this->schema;
967
        }
968 3
        $response = $this->_sendRawGet($this->_schemaUrl);
969 3
        $this->schema = $this->schemaParser->parseJson($response->getRawResponse());
970 3
        return $this->schema;
971
    }
972
}
973