Passed
Pull Request — master (#123)
by
unknown
05:29
created

Solr   F

Complexity

Total Complexity 64

Size/Duplication

Total Lines 664
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 226
dl 0
loc 664
rs 3.28
c 1
b 0
f 0
wmc 64

22 Methods

Rating   Name   Duplication   Size   Complexity  
B createCore() 0 37 6
A searchRaw() 0 23 3
A magicGetService() 0 3 1
A magicGetLimit() 0 3 1
A __isset() 0 3 1
A getNextCoreNumber() 0 9 2
A __set() 0 10 3
A magicGetNumberOfHits() 0 3 1
A magicSetParams() 0 3 1
A __get() 0 11 3
B getInstance() 0 30 8
A magicGetReady() 0 3 1
A magicSetLimit() 0 3 1
B __construct() 0 70 9
B escapeQueryKeepField() 0 42 6
A escapeQuery() 0 6 1
A loadSolrConnectionInfo() 0 25 6
A magicSetConfigPid() 0 3 1
A magicGetCore() 0 3 1
A getFields() 0 34 2
A optimize() 0 23 4
A suggestBuild() 0 12 2

How to fix   Complexity   

Complex Class

Complex classes like Solr often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Solr, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
5
 *
6
 * This file is part of the Kitodo and TYPO3 projects.
7
 *
8
 * @license GNU General Public License version 3 or later.
9
 * For the full copyright and license information, please read the
10
 * LICENSE.txt file that was distributed with this source code.
11
 */
12
13
namespace Kitodo\Dlf\Common\Solr;
14
15
use Kitodo\Dlf\Common\Helper;
16
use Psr\Log\LoggerAwareInterface;
17
use Psr\Log\LoggerAwareTrait;
18
use Solarium\Client;
19
use Solarium\Core\Client\Adapter\Http;
20
use Solarium\QueryType\Server\CoreAdmin\Result\StatusResult;
21
use TYPO3\CMS\Core\Cache\CacheManager;
22
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
23
use TYPO3\CMS\Core\Database\ConnectionPool;
24
use TYPO3\CMS\Core\EventDispatcher\EventDispatcher;
25
use TYPO3\CMS\Core\Utility\GeneralUtility;
26
use TYPO3\CMS\Core\Utility\MathUtility;
27
28
/**
29
 * Solr class for the 'dlf' extension
30
 *
31
 * @package TYPO3
32
 * @subpackage dlf
33
 *
34
 * @access public
35
 *
36
 * @property array $config this holds the Solr configuration
37
 * @property-read string|null $core this holds the core name for the current instance
38
 * @property-write int $configPid this holds the PID for the configuration
39
 * @property int $limit this holds the max results
40
 * @property-read int $numberOfHits this holds the number of hits for last search
41
 * @property-write array $params this holds the additional query parameters
42
 * @property-read bool $ready flag if the Solr service is instantiated successfully
43
 * @property-read Client $service this holds the Solr service object
44
 */
45
class Solr implements LoggerAwareInterface
46
{
47
    use LoggerAwareTrait;
48
49
    /**
50
     * @access protected
51
     * @var array This holds the Solr configuration
52
     */
53
    protected array $config = [];
54
55
    /**
56
     * @access protected
57
     * @var string|null This holds the core name
58
     */
59
    protected ?string $core = null;
60
61
    /**
62
     * @access protected
63
     * @var int This holds the PID for the configuration
64
     */
65
    protected int $configPid = 0;
66
67
    /**
68
     * @access public
69
     * @static
70
     * @var string The extension key
71
     */
72
    public static string $extKey = 'dlf';
73
74
    /**
75
     * @access public
76
     * @static
77
     * @var array The fields for SOLR index
78
     */
79
    public static array $fields = [];
80
81
    /**
82
     * @access protected
83
     * @var int This holds the max results
84
     */
85
    protected int $limit = 50000;
86
87
    /**
88
     * @access protected
89
     * @var int This holds the number of hits for last search
90
     */
91
    protected int $numberOfHits = 0;
92
93
    /**
94
     * @access protected
95
     * @var array This holds the additional query parameters
96
     */
97
    protected array $params = [];
98
99
    /**
100
     * @access protected
101
     * @var bool Is the search instantiated successfully?
102
     */
103
    protected bool $ready = false;
104
105
    /**
106
     * @access protected
107
     * @var array(Solr) This holds the singleton search objects with their core as array key
108
     */
109
    protected static array $registry = [];
110
111
    /**
112
     * @access protected
113
     * @var Client This holds the Solr service object
114
     */
115
    protected Client $service;
116
117
    /**
118
     * Add a new core to Apache Solr
119
     *
120
     * @access public
121
     *
122
     * @param string $core The name of the new core. If empty, the next available core name is used.
123
     *
124
     * @return string The name of the new core
125
     */
126
    public static function createCore($core = ''): string
127
    {
128
        // Get next available core name if none given.
129
        if (empty($core)) {
130
            $core = 'dlfCore' . self::getNextCoreNumber();
131
        }
132
        // Get Solr service instance.
133
        $solr = self::getInstance($core);
134
        // Create new core if core with given name doesn't exist.
135
        if ($solr->ready) {
136
            // Core already exists.
137
            return $core;
138
        } else {
139
            // Core doesn't exist yet.
140
            $solrAdmin = self::getInstance();
141
            if ($solrAdmin->ready) {
142
                $query = $solrAdmin->service->createCoreAdmin();
143
                $action = $query->createCreate();
144
                $action->setConfigSet('dlf');
145
                $action->setCore($core);
146
                $action->setDataDir('data');
147
                $action->setInstanceDir($core);
148
                $query->setAction($action);
149
                try {
150
                    $response = $solrAdmin->service->coreAdmin($query);
151
                    if ($response->getWasSuccessful()) {
152
                        // Core successfully created.
153
                        return $core;
154
                    }
155
                } catch (\Exception $e) {
156
                    // Nothing to do here.
157
                }
158
            } else {
159
                Helper::log('Apache Solr not available', LOG_SEVERITY_ERROR);
160
            }
161
        }
162
        return '';
163
    }
164
165
    /**
166
     * Escape special characters in a query string
167
     *
168
     * @access public
169
     *
170
     * @param string $query The query string
171
     *
172
     * @return string The escaped query string
173
     */
174
    public static function escapeQuery(string $query): string
175
    {
176
        // Escape query by disallowing range and field operators
177
        // Permit operators: wildcard, boolean, fuzzy, proximity, boost, grouping
178
        // https://solr.apache.org/guide/solr/latest/query-guide/standard-query-parser.html
179
        return preg_replace('/(\{|}|\[|]|:|\/|\\\)/', '\\\$1', $query);
180
    }
181
182
    /**
183
     * Escape all special characters in a query string while retaining valid field queries
184
     *
185
     * @access public
186
     *
187
     * @param string $query The query string
188
     * @param int $pid The PID for the field configuration
189
     *
190
     * @return string The escaped query string
191
     */
192
    public static function escapeQueryKeepField(string $query, int $pid): string
193
    {
194
        // Is there a field query?
195
        if (preg_match('/^[[:alnum:]]+_[tu][su]i:\(?.*\)?$/', $query)) {
196
            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
197
                ->getQueryBuilderForTable('tx_dlf_metadata');
198
199
            // Get all indexed fields.
200
            $fields = [];
201
            $result = $queryBuilder
202
                ->select(
203
                    'tx_dlf_metadata.index_name AS index_name',
204
                    'tx_dlf_metadata.index_tokenized AS index_tokenized',
205
                    'tx_dlf_metadata.index_stored AS index_stored'
206
                )
207
                ->from('tx_dlf_metadata')
208
                ->where(
209
                    $queryBuilder->expr()->eq('tx_dlf_metadata.index_indexed', 1),
210
                    $queryBuilder->expr()->eq('tx_dlf_metadata.pid', (int) $pid),
211
                    $queryBuilder->expr()->orX(
212
                        $queryBuilder->expr()->in('tx_dlf_metadata.sys_language_uid', [-1, 0]),
213
                        $queryBuilder->expr()->eq('tx_dlf_metadata.l18n_parent', 0)
214
                    ),
215
                    Helper::whereExpression('tx_dlf_metadata')
216
                )
217
                ->execute();
218
219
            while ($resArray = $result->fetchAssociative()) {
220
                $fields[] = $resArray['index_name'] . '_' . ($resArray['index_tokenized'] ? 't' : 'u') . ($resArray['index_stored'] ? 's' : 'u') . 'i';
221
            }
222
223
            // Check if queried field is valid.
224
            $splitQuery = explode(':', $query, 2);
225
            if (in_array($splitQuery[0], $fields)) {
226
                $query = $splitQuery[0] . ':(' . self::escapeQuery(trim($splitQuery[1], '()')) . ')';
227
            } else {
228
                $query = self::escapeQuery($query);
229
            }
230
        } else {
231
            $query = self::escapeQuery($query);
232
        }
233
        return $query;
234
    }
235
236
    /**
237
     * Get fields for index.
238
     *
239
     * @access public
240
     *
241
     * @return array fields
242
     */
243
    public static function getFields(): array
244
    {
245
        if (empty(self::$fields)) {
246
            $conf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey, 'solr');
247
            $solrFields = $conf['fields'];
248
            self::$fields['id'] = $solrFields['id'];
249
            self::$fields['uid'] = $solrFields['uid'];
250
            self::$fields['pid'] = $solrFields['pid'];
251
            self::$fields['page'] = $solrFields['page'];
252
            self::$fields['partof'] = $solrFields['partof'];
253
            self::$fields['root'] = $solrFields['root'];
254
            self::$fields['sid'] = $solrFields['sid'];
255
            self::$fields['toplevel'] = $solrFields['toplevel'];
256
            self::$fields['type'] = $solrFields['type'];
257
            self::$fields['title'] = $solrFields['title'];
258
            self::$fields['volume'] = $solrFields['volume'];
259
            self::$fields['date'] = $solrFields['date'];
260
            self::$fields['thumbnail'] = $solrFields['thumbnail'];
261
            self::$fields['default'] = $solrFields['default'];
262
            self::$fields['timestamp'] = $solrFields['timestamp'];
263
            self::$fields['autocomplete'] = $solrFields['autocomplete'];
264
            self::$fields['fulltext'] = $solrFields['fulltext'];
265
            self::$fields['record_id'] = $solrFields['recordId'];
266
            self::$fields['purl'] = $solrFields['purl'];
267
            self::$fields['urn'] = $solrFields['urn'];
268
            self::$fields['location'] = $solrFields['location'];
269
            self::$fields['collection'] = $solrFields['collection'];
270
            self::$fields['license'] = $solrFields['license'];
271
            self::$fields['terms'] = $solrFields['terms'];
272
            self::$fields['restrictions'] = $solrFields['restrictions'];
273
            self::$fields['geom'] = $solrFields['geom'];
274
        }
275
276
        return self::$fields;
277
    }
278
279
    /**
280
     * This is a singleton class, thus instances must be created by this method
281
     *
282
     * @access public
283
     *
284
     * @param mixed $core Name or UID of the core to load or null to get core admin endpoint
285
     *
286
     * @return Solr Instance of this class
287
     */
288
    public static function getInstance($core = null): Solr
289
    {
290
        // Get core name if UID is given.
291
        if (MathUtility::canBeInterpretedAsInteger($core)) {
292
            $core = Helper::getIndexNameFromUid($core, 'tx_dlf_solrcores');
0 ignored issues
show
Bug introduced by
It seems like $core can also be of type null; however, parameter $uid of Kitodo\Dlf\Common\Helper::getIndexNameFromUid() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

292
            $core = Helper::getIndexNameFromUid(/** @scrutinizer ignore-type */ $core, 'tx_dlf_solrcores');
Loading history...
293
        }
294
        // Check if core is set or null.
295
        if (
296
            empty($core)
297
            && $core !== null
0 ignored issues
show
introduced by
The condition $core !== null is always false.
Loading history...
298
        ) {
299
            Helper::log('Invalid core UID or name given for Apache Solr', LOG_SEVERITY_ERROR);
300
        }
301
        if (!empty($core)) {
302
            // Check if there is an instance in the registry already.
303
            if (
304
                array_key_exists($core, self::$registry)
305
                && self::$registry[$core] instanceof self
306
            ) {
307
                // Return singleton instance if available.
308
                return self::$registry[$core];
309
            }
310
        }
311
        // Create new instance...
312
        $instance = new self($core);
313
        // ...and save it to registry.
314
        if (!empty($instance->core)) {
315
            self::$registry[$instance->core] = $instance;
316
        }
317
        return $instance;
318
    }
319
320
    /**
321
     * Get next unused Solr core number
322
     *
323
     * @access public
324
     *
325
     * @param int $number Number to start with
326
     *
327
     * @return int First unused core number found
328
     */
329
    public static function getNextCoreNumber(int $number = 0): int
330
    {
331
        $number = max($number, 0);
332
        // Check if core already exists.
333
        $solr = self::getInstance('dlfCore' . $number);
334
        if (!$solr->ready) {
335
            return $number;
336
        } else {
337
            return self::getNextCoreNumber($number + 1);
338
        }
339
    }
340
341
    /**
342
     * Sets the connection information for Solr
343
     *
344
     * @access protected
345
     *
346
     * @return void
347
     */
348
    protected function loadSolrConnectionInfo(): void
349
    {
350
        if (empty($this->config)) {
351
            $config = [];
352
            // Extract extension configuration.
353
            $conf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey, 'solr');
354
            // Derive Solr scheme
355
            $config['scheme'] = empty($conf['https']) ? 'http' : 'https';
356
            // Derive Solr host name.
357
            $config['host'] = ($conf['host'] ? $conf['host'] : '127.0.0.1');
358
            // Set username and password.
359
            $config['username'] = $conf['user'];
360
            $config['password'] = $conf['pass'];
361
            // Set port if not set.
362
            $config['port'] = MathUtility::forceIntegerInRange($conf['port'], 1, 65535, 8983);
363
            // Trim path of slashes and (re-)add trailing slash if path not empty.
364
            $config['path'] = trim($conf['path'], '/');
365
            if (!empty($config['path'])) {
366
                $config['path'] .= '/';
367
            }
368
369
            // Set connection timeout lower than PHP's max_execution_time.
370
            $maxExecutionTime = (int) ini_get('max_execution_time') ? : 30;
371
            $config['timeout'] = MathUtility::forceIntegerInRange($conf['timeout'], 1, $maxExecutionTime, 10);
372
            $this->config = $config;
373
        }
374
    }
375
376
    /**
377
     * Processes a search request and returns the raw Apache Solr Documents.
378
     *
379
     * @access public
380
     *
381
     * @param array $parameters Additional search parameters
382
     *
383
     * @return array The Apache Solr Documents that were fetched
384
     */
385
    public function searchRaw(array $parameters = []): array
386
    {
387
        // Set additional query parameters.
388
        $parameters['start'] = 0;
389
        $parameters['rows'] = $this->limit;
390
        // Calculate cache identifier.
391
        $cacheIdentifier = Helper::digest($this->core . print_r(array_merge($this->params, $parameters), true));
0 ignored issues
show
introduced by
The property params is declared write-only in Kitodo\Dlf\Common\Solr\Solr.
Loading history...
Bug introduced by
Are you sure print_r(array_merge($thi...ms, $parameters), true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

391
        $cacheIdentifier = Helper::digest($this->core . /** @scrutinizer ignore-type */ print_r(array_merge($this->params, $parameters), true));
Loading history...
392
        $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('tx_dlf_solr');
393
        $resultSet = [];
394
        $entry = $cache->get($cacheIdentifier);
395
        if ($entry === false) {
396
            $selectQuery = $this->service->createSelect(array_merge($this->params, $parameters));
397
            $result = $this->service->select($selectQuery);
398
            foreach ($result as $doc) {
399
                $resultSet[] = $doc;
400
            }
401
            // Save value in cache.
402
            $cache->set($cacheIdentifier, $resultSet);
403
        } else {
404
            // Return cache hit.
405
            $resultSet = $entry;
406
        }
407
        return $resultSet;
408
    }
409
410
    /**
411
     * This returns $this->core via __get()
412
     *
413
     * @access protected
414
     *
415
     * @return string|null The core name of the current query endpoint or null if core admin endpoint
416
     */
417
    protected function magicGetCore(): ?string
418
    {
419
        return $this->core;
420
    }
421
422
    /**
423
     * This returns $this->limit via __get()
424
     *
425
     * @access protected
426
     *
427
     * @return int The max number of results
428
     */
429
    protected function magicGetLimit(): int
430
    {
431
        return $this->limit;
432
    }
433
434
    /**
435
     * This returns $this->numberOfHits via __get()
436
     *
437
     * @access protected
438
     *
439
     * @return int Total number of hits for last search
440
     */
441
    protected function magicGetNumberOfHits(): int
442
    {
443
        return $this->numberOfHits;
444
    }
445
446
    /**
447
     * This returns $this->ready via __get()
448
     *
449
     * @access protected
450
     *
451
     * @return bool Is the search instantiated successfully?
452
     */
453
    protected function magicGetReady(): bool
454
    {
455
        return $this->ready;
456
    }
457
458
    /**
459
     * This returns $this->service via __get()
460
     *
461
     * @access protected
462
     *
463
     * @return Client Apache Solr service object
464
     */
465
    protected function magicGetService(): Client
466
    {
467
        return $this->service;
468
    }
469
470
    /**
471
     * This sets $this->configPid via __set()
472
     *
473
     * @access protected
474
     *
475
     * @param int $value The new PID for the metadata definitions
476
     *
477
     * @return void
478
     */
479
    protected function magicSetConfigPid(int $value): void
480
    {
481
        $this->configPid = max($value, 0);
482
    }
483
484
    /**
485
     * This sets $this->limit via __set()
486
     *
487
     * @access protected
488
     *
489
     * @param int $value The max number of results
490
     *
491
     * @return void
492
     */
493
    protected function magicSetLimit(int $value): void
494
    {
495
        $this->limit = max($value, 0);
496
    }
497
498
    /**
499
     * This sets $this->params via __set()
500
     *
501
     * @access protected
502
     *
503
     * @param array $value The query parameters
504
     *
505
     * @return void
506
     */
507
    protected function magicSetParams(array $value): void
508
    {
509
        $this->params = $value;
510
    }
511
512
    /**
513
     * This magic method is called each time an invisible property is referenced from the object
514
     *
515
     * @access public
516
     *
517
     * @param string $var Name of variable to get
518
     *
519
     * @return mixed Value of $this->$var
520
     */
521
    public function __get(string $var)
522
    {
523
        $method = 'magicGet' . ucfirst($var);
524
        if (
525
            !property_exists($this, $var)
526
            || !method_exists($this, $method)
527
        ) {
528
            $this->logger->warning('There is no getter function for property "' . $var . '"');
0 ignored issues
show
Bug introduced by
The method warning() does not exist on null. ( Ignorable by Annotation )

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

528
            $this->logger->/** @scrutinizer ignore-call */ 
529
                           warning('There is no getter function for property "' . $var . '"');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
529
            return null;
530
        } else {
531
            return $this->$method();
532
        }
533
    }
534
535
    /**
536
     * This magic method is called each time an invisible property is checked for isset() or empty()
537
     *
538
     * @access public
539
     *
540
     * @param string $var Name of variable to check
541
     *
542
     * @return bool true if variable is set and not empty, false otherwise
543
     */
544
    public function __isset(string $var): bool
545
    {
546
        return !empty($this->__get($var));
547
    }
548
549
    /**
550
     * This magic method is called each time an invisible property is referenced from the object
551
     *
552
     * @access public
553
     *
554
     * @param string $var Name of variable to set
555
     * @param mixed $value New value of variable
556
     *
557
     * @return void
558
     */
559
    public function __set(string $var, $value): void
560
    {
561
        $method = 'magicSet' . ucfirst($var);
562
        if (
563
            !property_exists($this, $var)
564
            || !method_exists($this, $method)
565
        ) {
566
            $this->logger->warning('There is no setter function for property "' . $var . '"');
567
        } else {
568
            $this->$method($value);
569
        }
570
    }
571
572
    /**
573
     * This is a singleton class, thus the constructor should be private/protected
574
     *
575
     * @access protected
576
     *
577
     * @param string|null $core The name of the core to use or null for core admin endpoint
578
     *
579
     * @return void
580
     */
581
    protected function __construct(?string $core)
582
    {
583
        // Solarium requires different code for version 5 and 6.
584
        $isSolarium5 = Client::checkExact('5');
585
        // Get Solr connection parameters from configuration.
586
        $this->loadSolrConnectionInfo();
587
        // Configure connection adapter.
588
        $adapter = GeneralUtility::makeInstance(Http::class);
589
        $adapter->setTimeout($this->config['timeout']);
590
        // Configure event dispatcher.
591
        if ($isSolarium5) {
592
            $eventDispatcher = null;
593
        } else {
594
            // When updating to TYPO3 >=10.x and Solarium >=6.x
595
            // we have to provide an PSR-14 Event Dispatcher instead of
596
            // "null".
597
            $eventDispatcher = GeneralUtility::makeInstance(EventDispatcher::class);
598
        }
599
        // Configure endpoint.
600
        $config = [
601
            'endpoint' => [
602
                'default' => [
603
                    'scheme' => $this->config['scheme'],
604
                    'host' => $this->config['host'],
605
                    'port' => $this->config['port'],
606
                    'path' => '/' . $this->config['path'],
607
                    'core' => $core,
608
                    'username' => $this->config['username'],
609
                    'password' => $this->config['password']
610
                ]
611
            ]
612
        ];
613
        // Instantiate Solarium\Client class.
614
        if ($isSolarium5) {
615
            $this->service = GeneralUtility::makeInstance(Client::class, $config);
0 ignored issues
show
Bug introduced by
The property service is declared read-only in Kitodo\Dlf\Common\Solr\Solr.
Loading history...
616
        } else {
617
            // When updating to TYPO3 >=10.x and Solarium >=6.x
618
            // $adapter and $eventDispatcher are mandatory arguments
619
            // of the \Solarium\Client constructor.
620
            $this->service = GeneralUtility::makeInstance(Client::class, $adapter, $eventDispatcher, $config);
621
        }
622
        $this->service->setAdapter($adapter);
623
        // Check if connection is established.
624
        $query = $this->service->createCoreAdmin();
625
        $action = $query->createStatus();
626
        if ($core !== null) {
627
            $action->setCore($core);
628
        }
629
        $query->setAction($action);
630
        try {
631
            $response = $this->service->coreAdmin($query);
632
            if ($response->getWasSuccessful()) {
633
                // Solr is reachable, but is the core as well?
634
                if ($core !== null) {
635
                    $result = $response->getStatusResult();
636
                    if (
637
                        $result instanceof StatusResult
638
                        && $result->getUptime() > 0
639
                    ) {
640
                        // Set core name.
641
                        $this->core = $core;
0 ignored issues
show
Bug introduced by
The property core is declared read-only in Kitodo\Dlf\Common\Solr\Solr.
Loading history...
642
                    } else {
643
                        // Core not available.
644
                        return;
645
                    }
646
                }
647
                // Instantiation successful!
648
                $this->ready = true;
0 ignored issues
show
Bug introduced by
The property ready is declared read-only in Kitodo\Dlf\Common\Solr\Solr.
Loading history...
649
            }
650
        } catch (\Exception $e) {
651
            // Nothing to do here.
652
        }
653
    }
654
655
    /**
656
     * Sends the commit and optimize command to the index.
657
     *
658
     * @access public
659
     *
660
     * @param bool $commit If true, the commit command is sent to the index
661
     * @param bool $optimize If true, the optimize command is sent to the index
662
     *
663
     * @return bool true if executing the command worked
664
     */
665
    public function optimize(bool $commit, bool $optimize): bool
666
    {
667
        // get an update query instance
668
        $update = $this->service->createUpdate();
669
670
        // commit the index
671
        if ($commit) {
672
            $update->addCommit(false);
673
        }
674
675
        // optimize the index
676
        if ($optimize) {
677
            $update->addOptimize(false);
678
        }
679
680
        // this executes the query and returns the result
681
        $result = $this->service->update($update);
682
683
        if ($result->getStatus()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result->getStatus() of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
684
            return false;
685
        }
686
687
        return true;
688
    }
689
690
    /**
691
     * Sends the suggest.build=true command to the index.
692
     *
693
     * @access public
694
     *
695
     * @return bool true if executing the command worked
696
     */
697
    public function suggestBuild(): bool
698
    {
699
        $query = $this->service->createSuggester();
700
        $query->addParam('suggest.build', 'true');
701
        $query->setCount(0);
702
        $result = $this->service->execute($query);
703
704
        if ($result->getResponse()->getStatusCode() == 400) {
705
            return false;
706
        }
707
708
        return true;
709
    }
710
}
711