Passed
Pull Request — master (#1228)
by Timo
18:39
created

Query::setFacetFields()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
crap 2
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\Domain\Site\SiteHashService;
28
use ApacheSolrForTypo3\Solr\FieldProcessor\PageUidToHierarchy;
29
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration;
30
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
31
use TYPO3\CMS\Core\Utility\GeneralUtility;
32
33
/**
34
 * A Solr search query
35
 *
36
 * @author Ingo Renner <[email protected]>
37
 */
38
class Query
39
{
40
41
    // FIXME extract link building from the query, it's not the query's domain
42
43
    const SORT_ASC = 'ASC';
44
    const SORT_DESC = 'DESC';
45
46
    const OPERATOR_AND = 'AND';
47
    const OPERATOR_OR = 'OR';
48
49
    /**
50
     * Used to identify the queries.
51
     *
52
     * @var int
53
     */
54
    protected static $idCount = 0;
55
56
    /**
57
     * @var int
58
     */
59
    protected $id;
60
61
    /**
62
     * @var TypoScriptConfiguration
63
     */
64
    protected $solrConfiguration;
65
66
    /**
67
     * @var string
68
     */
69
    protected $keywords;
70
71
    /**
72
     * @var string
73
     */
74
    protected $keywordsRaw;
75
76
    /**
77
     * @var array
78
     */
79
    protected $filters = [];
80
81
    /**
82
     * @var string
83
     */
84
    protected $sorting;
85
86
    // TODO check usage of these two variants, especially the check for $rawQueryString in getQueryString()
87
    /**
88
     * @var
89
     */
90
    protected $queryString;
91
92
    /**
93
     * @var array
94
     */
95
    protected $queryParameters = [];
96
97
    /**
98
     * @var int
99
     */
100
    protected $resultsPerPage;
101
102
    /**
103
     * @var int
104
     */
105
    protected $page;
106
107
    /**
108
     * @var int
109
     */
110
    protected $linkTargetPageId;
111
112
    /**
113
     * Holds the query fields with their associated boosts. The key represents
114
     * the field name, value represents the field's boost. These are the fields
115
     * that will actually be searched.
116
     *
117
     * Used in Solr's qf parameter
118
     *
119
     * @var array
120
     * @see http://wiki.apache.org/solr/DisMaxQParserPlugin#qf_.28Query_Fields.29
121
     */
122
    protected $queryFields = [];
123
124
    /**
125
     * List of fields that will be returned in the result documents.
126
     *
127
     * used in Solr's fl parameter
128
     *
129
     * @var array
130
     * @see http://wiki.apache.org/solr/CommonQueryParameters#fl
131
     */
132
    protected $fieldList = [];
133
134
    /**
135
     * @var array
136
     */
137
    protected $filterFields;
138
139
    /**
140
     * @var array
141
     * @deprecated since 6.1 will be removed in 7.0
142
     */
143
    protected $sortingFields = [];
144
145
    /**
146
     * @var bool
147
     */
148
    private $rawQueryString = false;
149
150
    /**
151
     * The field by which the result will be collapsed
152
     * @var string
153
     */
154
    protected $variantField = 'variantId';
155
156
    /**
157
     * @var SiteHashService
158
     */
159
    protected $siteHashService = null;
160
161
    /**
162
     * @var \ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager
163
     */
164
    protected $logger = null;
165
166
    /**
167
     * Query constructor.
168
     * @param string $keywords
169
     * @param TypoScriptConfiguration $solrConfiguration
170
     * @param SiteHashService|null $siteHashService
171
     */
172 132
    public function __construct($keywords, $solrConfiguration = null, SiteHashService $siteHashService = null)
173
    {
174 132
        $keywords = (string)$keywords;
175
176 132
        $this->logger = GeneralUtility::makeInstance(SolrLogManager::class, __CLASS__);
177 132
        $this->solrConfiguration = is_null($solrConfiguration) ? Util::getSolrConfiguration() : $solrConfiguration;
178 132
        $this->siteHashService = is_null($siteHashService) ? GeneralUtility::makeInstance(SiteHashService::class) : $siteHashService;
179
180 132
        $this->setKeywords($keywords);
181 132
        $this->sorting = '';
182
183
        // What fields to search
184 132
        $queryFields = $this->solrConfiguration->getSearchQueryQueryFields();
185 132
        if ($queryFields != '') {
186 27
            $this->setQueryFieldsFromString($queryFields);
187 27
        }
188
189
        // What fields to return from Solr
190 132
        $this->fieldList = $this->solrConfiguration->getSearchQueryReturnFieldsAsArray(['*', 'score']);
191 132
        $this->linkTargetPageId = $this->solrConfiguration->getSearchTargetPage();
192
193 132
        $this->initializeQuery();
194
195 132
        $this->id = ++self::$idCount;
196 132
    }
197
198
    /**
199
     * @return void
200
     */
201 131
    protected function initializeQuery()
202
    {
203 131
        $this->initializeCollapsingFromConfiguration();
204 131
    }
205
206
    /**
207
     * Takes a string of comma separated query fields and _overwrites_ the
208
     * currently set query fields. Boost can also be specified in through the
209
     * given string.
210
     *
211
     * Example: "title^5, subtitle^2, content, author^0.5"
212
     * This sets the query fields to title with  a boost of 5.0, subtitle with
213
     * a boost of 2.0, content with a default boost of 1.0 and the author field
214
     * with a boost of 0.5
215
     *
216
     * @param string $queryFields A string defining which fields to query and their associated boosts
217
     * @return void
218
     */
219 28
    public function setQueryFieldsFromString($queryFields)
220
    {
221 28
        $fields = GeneralUtility::trimExplode(',', $queryFields, true);
222
223 28
        foreach ($fields as $field) {
224 28
            $fieldNameAndBoost = explode('^', $field);
225
226 28
            $boost = 1.0;
227 28
            if (isset($fieldNameAndBoost[1])) {
228 28
                $boost = floatval($fieldNameAndBoost[1]);
229 28
            }
230
231 28
            $this->setQueryField($fieldNameAndBoost[0], $boost);
232 28
        }
233 28
    }
234
235
    /**
236
     * Sets a query field and its boost. If the field does not exist yet, it
237
     * gets added. Boost is optional, if left out a default boost of 1.0 is
238
     * applied.
239
     *
240
     * @param string $fieldName The field's name
241
     * @param float $boost Optional field boost, defaults to 1.0
242
     * @return void
243
     */
244 28
    public function setQueryField($fieldName, $boost = 1.0)
245
    {
246 28
        $this->queryFields[$fieldName] = (float)$boost;
247 28
    }
248
249
    /**
250
     * magic implementation for clone(), makes sure that the id counter is
251
     * incremented
252
     *
253
     * @return void
254
     */
255 5
    public function __clone()
256
    {
257 5
        $this->id = ++self::$idCount;
258 5
    }
259
260
    /**
261
     * returns a string representation of the query
262
     *
263
     * @return string the string representation of the query
264
     */
265 8
    public function __toString()
266
    {
267 8
        return $this->getQueryString();
268
    }
269
270
    /**
271
     * Builds the query string which is then used for Solr's q parameters
272
     *
273
     * @return string Solr query string
274
     */
275 38
    public function getQueryString()
276
    {
277 38
        if (!$this->rawQueryString) {
278 35
            $this->buildQueryString();
279 35
        }
280
281 38
        return $this->queryString;
282
    }
283
284
    /**
285
     * Sets the query string without any escaping.
286
     *
287
     * Be cautious with this function!
288
     * TODO remove this method as it basically just sets the q parameter / keywords
289
     *
290
     * @param string $queryString The raw query string.
291
     */
292 4
    public function setQueryString($queryString)
293
    {
294 4
        $this->queryString = $queryString;
295 4
    }
296
297
    /**
298
     * Creates the string that is later used as the q parameter in the solr query
299
     *
300
     * @return void
301
     */
302 35
    protected function buildQueryString()
303
    {
304
        // very simple for now
305 35
        $this->queryString = $this->keywords;
306 35
    }
307
308
    /**
309
     * Sets whether a raw query sting should be used, that is, whether the query
310
     * string should be escaped or not.
311
     *
312
     * @param bool $useRawQueryString TRUE to use raw queries (like Lucene Query Language) or FALSE for regular, escaped queries
313
     */
314 4
    public function useRawQueryString($useRawQueryString)
315
    {
316 4
        $this->rawQueryString = (boolean)$useRawQueryString;
317 4
    }
318
319
    /**
320
     * Returns the query's ID.
321
     *
322
     * @return int The query's ID.
323
     */
324
    public function getId()
325
    {
326
        return $this->id;
327
    }
328
329
    /**
330
     * Quote and escape search strings
331
     *
332
     * @param string $string String to escape
333
     * @return string The escaped/quoted string
334
     */
335 132
    public function escape($string)
336
    {
337
        // when we have a numeric string only, nothing needs to be done
338 132
        if (is_numeric($string)) {
339 1
            return $string;
340
        }
341
342
        // when no whitespaces are in the query we can also just escape the special characters
343 132
        if (preg_match('/\W/', $string) != 1) {
344 111
            return $this->escapeSpecialCharacters($string);
345
        }
346
347
        // when there are no quotes inside the query string we can also just escape the whole string
348 37
        $hasQuotes = strrpos($string, '"') !== false;
349 37
        if (!$hasQuotes) {
350 30
            return $this->escapeSpecialCharacters($string);
351
        }
352
353 7
        $result = $this->tokenizeByQuotesAndEscapeDependingOnContext($string);
354
355 7
        return $result;
356
    }
357
358
    /**
359
     * This method is used to escape the content in the query string surrounded by quotes
360
     * different then when it is not in a quoted context.
361
     *
362
     * @param string $string
363
     * @return string
364
     */
365 7
    protected function tokenizeByQuotesAndEscapeDependingOnContext($string)
366
    {
367 7
        $result = '';
368 7
        $quotesCount = substr_count($string, '"');
369 7
        $isEvenAmountOfQuotes = $quotesCount % 2 === 0;
370
371
        // go over all quote segments and apply escapePhrase inside a quoted
372
        // context and escapeSpecialCharacters outside the quoted context.
373 7
        $segments = explode('"', $string);
374 7
        $segmentsIndex = 0;
375 7
        foreach ($segments as $segment) {
376 7
            $isInQuote = $segmentsIndex % 2 !== 0;
377 7
            $isLastQuote = $segmentsIndex === $quotesCount;
378
379 7
            if ($isLastQuote && !$isEvenAmountOfQuotes) {
380 1
                $result .= '\"';
381 1
            }
382
383 7
            if ($isInQuote && !$isLastQuote) {
384 6
                $result .= $this->escapePhrase($segment);
385 6
            } else {
386 7
                $result .= $this->escapeSpecialCharacters($segment);
387
            }
388
389 7
            $segmentsIndex++;
390 7
        }
391
392 7
        return $result;
393
    }
394
395
    // pagination
396
397
    /**
398
     * Escapes a value meant to be contained in a phrase with characters with
399
     * special meanings in Lucene query syntax.
400
     *
401
     * @param string $value Unescaped - "dirty" - string
402
     * @return string Escaped - "clean" - string
403
     */
404 6
    protected function escapePhrase($value)
405
    {
406 6
        $pattern = '/("|\\\)/';
407 6
        $replace = '\\\$1';
408
409 6
        return '"' . preg_replace($pattern, $replace, $value) . '"';
410
    }
411
412
    /**
413
     * Escapes characters with special meanings in Lucene query syntax.
414
     *
415
     * @param string $value Unescaped - "dirty" - string
416
     * @return string Escaped - "clean" - string
417
     */
418 132
    protected function escapeSpecialCharacters($value)
419
    {
420
        // list taken from http://lucene.apache.org/core/4_4_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description
421
        // which mentions: + - && || ! ( ) { } [ ] ^ " ~ * ? : \ /
422
        // of which we escape: ( ) { } [ ] ^ " ~ : \ /
423
        // and explicitly don't escape: + - && || ! * ?
424 132
        $pattern = '/(\\(|\\)|\\{|\\}|\\[|\\]|\\^|"|~|\:|\\\\|\\/)/';
425 132
        $replace = '\\\$1';
426
427 132
        return preg_replace($pattern, $replace, $value);
428
    }
429
430
    /**
431
     * Gets the currently showing page's number
432
     *
433
     * @return int page number currently showing
434
     */
435 1
    public function getPage()
436
    {
437 1
        return $this->page;
438
    }
439
440
    /**
441
     * Sets the page that should be shown
442
     *
443
     * @param int $page page number to show
444
     * @return void
445
     */
446 1
    public function setPage($page)
447
    {
448 1
        $this->page = max(intval($page), 0);
449 1
    }
450
451
    /**
452
     * Gets the index of the first result document we're showing
453
     *
454
     * @return int index of the currently first document showing
455
     */
456
    public function getStartIndex()
457
    {
458
        return ($this->page - 1) * $this->resultsPerPage;
459
    }
460
461
    /**
462
     * Gets the index of the last result document we're showing
463
     *
464
     * @return int index of the currently last document showing
465
     */
466
    public function getEndIndex()
467
    {
468
        return $this->page * $this->resultsPerPage;
469
    }
470
471
    // query elevation
472
473
    /**
474
     * Activates and deactivates query elevation for the current query.
475
     *
476
     * @param bool $elevation True to enable query elevation (default), FALSE to disable query elevation.
477
     * @param bool $forceElevation Optionally force elevation so that the elevated documents are always on top regardless of sorting, default to TRUE.
478
     * @param bool $markElevatedResults Mark elevated results
479
     * @return void
480
     */
481 26
    public function setQueryElevation(
482
        $elevation = true,
483
        $forceElevation = true,
484
        $markElevatedResults = true
485
    ) {
486 26
        if ($elevation) {
487 22
            $this->queryParameters['enableElevation'] = 'true';
488 22
            $this->setForceElevation($forceElevation);
489 22
            if ($markElevatedResults) {
490 22
                $this->addReturnField('isElevated:[elevated]');
491 22
            }
492 22
        } else {
493 5
            $this->queryParameters['enableElevation'] = 'false';
494 5
            unset($this->queryParameters['forceElevation']);
495 5
            $this->removeReturnField('isElevated:[elevated]');
496 5
            $this->removeReturnField('[elevated]'); // fallback
497
        }
498 26
    }
499
500
    /**
501
     * Enables or disables the forceElevation query parameter.
502
     *
503
     * @param bool $forceElevation
504
     */
505 22
    protected function setForceElevation($forceElevation)
506
    {
507 22
        if ($forceElevation) {
508 21
            $this->queryParameters['forceElevation'] = 'true';
509 21
        } else {
510 1
            $this->queryParameters['forceElevation'] = 'false';
511
        }
512 22
    }
513
514
    // collapsing
515
516
    /**
517
     * Check whether collapsing is active
518
     *
519
     * @return bool
520
     */
521 3
    public function getIsCollapsing()
522
    {
523 3
        return array_key_exists('collapsing', $this->filters);
524
    }
525
526
    /**
527
     * @param string $fieldName
528
     */
529 3
    public function setVariantField($fieldName)
530
    {
531 3
        $this->variantField = $fieldName;
532 3
    }
533
534
    /**
535
     * @return string
536
     */
537 1
    public function getVariantField()
538
    {
539 1
        return $this->variantField;
540
    }
541
542
    /**
543
     * @param bool $collapsing
544
     */
545 4
    public function setCollapsing($collapsing = true)
546
    {
547 4
        if ($collapsing) {
548 4
            $this->filters['collapsing'] = '{!collapse field=' . $this->variantField . '}';
549 4
            if ($this->solrConfiguration->getSearchVariantsExpand()) {
550 2
                $this->queryParameters['expand'] = 'true';
551 2
                $this->queryParameters['expand.rows'] = $this->solrConfiguration->getSearchVariantsLimit();
552 2
            }
553 4
        } else {
554 1
            unset($this->filters['collapsing']);
555 1
            unset($this->queryParameters['expand']);
556 1
            unset($this->queryParameters['expand.rows']);
557
        }
558 4
    }
559
560
    // grouping
561
562
    /**
563
     * Adds a field to the list of fields to return. Also checks whether * is
564
     * set for the fields, if so it's removed from the field list.
565
     *
566
     * @param string $fieldName Name of a field to return in the result documents
567
     */
568 23
    public function addReturnField($fieldName)
569
    {
570 23
        if (strpos($fieldName, '[') === false
571 23
            && strpos($fieldName, ']') === false
572 23
            && in_array('*', $this->fieldList)
573 23
        ) {
574 1
            $this->fieldList = array_diff($this->fieldList, ['*']);
575 1
        }
576
577 23
        $this->fieldList[] = $fieldName;
578 23
    }
579
580
    /**
581
     * Removes a field from the list of fields to return (fl parameter).
582
     *
583
     * @param string $fieldName Field to remove from the list of fields to return
584
     */
585 6
    public function removeReturnField($fieldName)
586
    {
587 6
        $key = array_search($fieldName, $this->fieldList);
588
589 6
        if ($key !== false) {
590 2
            unset($this->fieldList[$key]);
591 2
        }
592 6
    }
593
594
    /**
595
     * Activates and deactivates grouping for the current query.
596
     *
597
     * @param bool $grouping TRUE to enable grouping, FALSE to disable grouping
598
     * @return void
599
     */
600 2
    public function setGrouping($grouping = true)
601
    {
602 2
        if ($grouping) {
603 1
            $this->queryParameters['group'] = 'true';
604 1
            $this->queryParameters['group.format'] = 'grouped';
605 1
            $this->queryParameters['group.ngroups'] = 'true';
606 1
        } else {
607 1
            foreach ($this->queryParameters as $key => $value) {
608
                // remove all group.* settings
609 1
                if (GeneralUtility::isFirstPartOfStr($key, 'group')) {
610 1
                    unset($this->queryParameters[$key]);
611 1
                }
612 1
            }
613
        }
614 2
    }
615
616
    /**
617
     * Sets the number of groups to return per group field or group query
618
     *
619
     * Internally uses the rows parameter.
620
     *
621
     * @param int $numberOfGroups Number of groups per group.field or group.query
622
     */
623 1
    public function setNumberOfGroups($numberOfGroups)
624
    {
625 1
        $this->setResultsPerPage($numberOfGroups);
626 1
    }
627
628
    /**
629
     * Gets the number of groups to return per group field or group query
630
     *
631
     * Internally uses the rows parameter.
632
     *
633
     * @return int Number of groups per group.field or group.query
634
     */
635 1
    public function getNumberOfGroups()
636
    {
637 1
        return $this->getResultsPerPage();
638
    }
639
640
    /**
641
     * Returns the number of results that should be shown per page
642
     *
643
     * @return int number of results to show per page
644
     */
645 25
    public function getResultsPerPage()
646
    {
647 25
        return $this->resultsPerPage;
648
    }
649
650
    /**
651
     * Sets the number of results that should be shown per page
652
     *
653
     * @param int $resultsPerPage Number of results to show per page
654
     * @return void
655
     */
656 32
    public function setResultsPerPage($resultsPerPage)
657
    {
658 32
        $this->resultsPerPage = max(intval($resultsPerPage), 0);
659 32
    }
660
661
    /**
662
     * Adds a field that should be used for grouping.
663
     *
664
     * @param string $fieldName Name of a field for grouping
665
     */
666 1
    public function addGroupField($fieldName)
667
    {
668 1
        if (!isset($this->queryParameters['group.field'])) {
669 1
            $this->queryParameters['group.field'] = [];
670 1
        }
671
672 1
        $this->queryParameters['group.field'][] = $fieldName;
673 1
    }
674
675
    /**
676
     * Gets the fields set for grouping.
677
     *
678
     * @return array An array of fields set for grouping.
679
     */
680 1
    public function getGroupFields()
681
    {
682 1
        return (array)$this->getQueryParameter('group.field', []);
683
    }
684
685
    /**
686
     * Adds sorting configuration for grouping.
687
     *
688
     * @param string $sorting value of sorting configuration
689
     */
690 1
    public function addGroupSorting($sorting)
691
    {
692 1
        if (!isset($this->queryParameters['group.sort'])) {
693 1
            $this->queryParameters['group.sort'] = [];
694 1
        }
695 1
        $this->queryParameters['group.sort'][] = $sorting;
696 1
    }
697
698
    /**
699
     * Gets the sorting set for grouping.
700
     *
701
     * @return array An array of sorting configurations for grouping.
702
     */
703 1
    public function getGroupSortings()
704
    {
705 1
        return (array)$this->getQueryParameter('group.sort', []);
706
    }
707
708
    // faceting
709
710
    /**
711
     * Adds a query that should be used for grouping.
712
     *
713
     * @param string $query Lucene query for grouping
714
     */
715 1
    public function addGroupQuery($query)
716
    {
717 1
        if (!isset($this->queryParameters['group.query'])) {
718 1
            $this->queryParameters['group.query'] = [];
719 1
        }
720
721 1
        $this->queryParameters['group.query'][] = $query;
722 1
    }
723
724
    /**
725
     * Gets the queries set for grouping.
726
     *
727
     * @return array An array of queries set for grouping.
728
     */
729 1
    public function getGroupQueries()
730
    {
731 1
        return (array)$this->getQueryParameter('group.query', []);
732
    }
733
734
    /**
735
     * Sets the maximum number of results to be returned per group.
736
     *
737
     * @param int $numberOfResults Maximum number of results per group to return
738
     */
739 1
    public function setNumberOfResultsPerGroup($numberOfResults)
740
    {
741 1
        $numberOfResults = max(intval($numberOfResults), 0);
742
743 1
        $this->queryParameters['group.limit'] = $numberOfResults;
744 1
    }
745
746
    // filter
747
748
    /**
749
     * Gets the maximum number of results to be returned per group.
750
     *
751
     * @return int Maximum number of results per group to return
752
     */
753 1
    public function getNumberOfResultsPerGroup()
754
    {
755
        // default if nothing else set is 1, @see http://wiki.apache.org/solr/FieldCollapsing
756 1
        $numberOfResultsPerGroup = 1;
757
758 1
        if (!empty($this->queryParameters['group.limit'])) {
759 1
            $numberOfResultsPerGroup = $this->queryParameters['group.limit'];
760 1
        }
761
762 1
        return $numberOfResultsPerGroup;
763
    }
764
765
    /**
766
     * Activates and deactivates faceting for the current query.
767
     *
768
     * @param bool $faceting TRUE to enable faceting, FALSE to disable faceting
769
     * @return void
770
     */
771 31
    public function setFaceting($faceting = true)
772
    {
773 31
        if ($faceting) {
774 31
            $this->queryParameters['facet'] = 'true';
775 31
            $this->queryParameters['facet.mincount'] = $this->solrConfiguration->getSearchFacetingMinimumCount();
776 31
            $this->queryParameters['facet.limit'] = $this->solrConfiguration->getSearchFacetingFacetLimit();
777
778 31
            $this->applyConfiguredFacetSorting();
779 31
        } else {
780 1
            $this->removeFacetingParametersFromQuery();
781
        }
782 31
    }
783
784
    /**
785
     * Removes all facet.* or f.*.facet.* parameters from the query.
786
     *
787
     * @return void
788
     */
789 1
    protected function removeFacetingParametersFromQuery()
790
    {
791 1
        foreach ($this->queryParameters as $key => $value) {
792
            // remove all facet.* settings
793 1
            if (GeneralUtility::isFirstPartOfStr($key, 'facet')) {
794 1
                unset($this->queryParameters[$key]);
795 1
            }
796
797
            // remove all f.*.facet.* settings (overrides for individual fields)
798 1
            if (GeneralUtility::isFirstPartOfStr($key, 'f.') && strpos($key, '.facet.') !== false) {
799 1
                unset($this->queryParameters[$key]);
800 1
            }
801 1
        }
802 1
    }
803
804
    /**
805
     * Reads the facet sorting configuration and applies it to the queryParameters.
806
     *
807
     * @return void
808
     */
809 31
    protected function applyConfiguredFacetSorting()
810
    {
811 31
        $sorting = $this->solrConfiguration->getSearchFacetingSortBy();
812 31
        if (!GeneralUtility::inList('count,index,alpha,lex,1,0,true,false', $sorting)) {
813
            // when the sorting is not in the list of valid values we do not apply it.
814 10
            return;
815
        }
816
817
        // alpha and lex alias for index
818 21
        if ($sorting == 'alpha' || $sorting == 'lex') {
819 1
            $sorting = 'index';
820 1
        }
821
822 21
        $this->queryParameters['facet.sort'] = $sorting;
823 21
    }
824
825
    /**
826
     * Sets facet fields for a query.
827
     *
828
     * @param array $facetFields Array of field names
829
     */
830 1
    public function setFacetFields(array $facetFields)
831
    {
832 1
        $this->queryParameters['facet.field'] = [];
833
834 1
        foreach ($facetFields as $facetField) {
835 1
            $this->addFacetField($facetField);
836 1
        }
837 1
    }
838
839
    /**
840
     * Adds a single facet field.
841
     *
842
     * @param string $facetField field name
843
     */
844 2
    public function addFacetField($facetField)
845
    {
846 2
        $this->queryParameters['facet.field'][] = $facetField;
847 2
    }
848
849
    /**
850
     * Removes a filter on a field
851
     *
852
     * @param string $filterFieldName The field name the filter should be removed for
853
     * @return void
854
     */
855 1
    public function removeFilter($filterFieldName)
856
    {
857 1
        foreach ($this->filters as $key => $filterString) {
858 1
            if (GeneralUtility::isFirstPartOfStr($filterString,
859 1
                $filterFieldName . ':')
860 1
            ) {
861 1
                unset($this->filters[$key]);
862 1
            }
863 1
        }
864 1
    }
865
866
    /**
867
     * Removes a filter based on key of filter array
868
     *
869
     * @param string $key array key
870
     */
871 1
    public function removeFilterByKey($key)
872
    {
873 1
        unset($this->filters[$key]);
874 1
    }
875
876
    /**
877
     * Removes a filter by the filter value. The value has the following format:
878
     *
879
     * "fieldname:value"
880
     *
881
     * @param string $filterString The filter to remove, in the form of field:value
882
     */
883 1
    public function removeFilterByValue($filterString)
884
    {
885 1
        $key = array_search($filterString, $this->filters);
886 1
        if ($key === false) {
887
            // value not found, nothing to do
888
            return;
889
        }
890 1
        unset($this->filters[$key]);
891 1
    }
892
893
    /**
894
     * Gets all currently applied filters.
895
     *
896
     * @return array Array of filters
897
     */
898 30
    public function getFilters()
899
    {
900 30
        return $this->filters;
901
    }
902
903
    // sorting
904
905
    /**
906
     * Sets access restrictions for a frontend user.
907
     *
908
     * @param array $groups Array of groups a user has been assigned to
909
     */
910 29
    public function setUserAccessGroups(array $groups)
911
    {
912 29
        $groups = array_map('intval', $groups);
913 29
        $groups[] = 0; // always grant access to public documents
914 29
        $groups = array_unique($groups);
915 29
        sort($groups, SORT_NUMERIC);
916
917 29
        $accessFilter = '{!typo3access}' . implode(',', $groups);
918
919 29
        foreach ($this->filters as $key => $filter) {
920 25
            if (GeneralUtility::isFirstPartOfStr($filter, '{!typo3access}')) {
921 1
                unset($this->filters[$key]);
922 1
            }
923 29
        }
924
925 29
        $this->addFilter($accessFilter);
926 29
    }
927
928
    /**
929
     * Adds a filter parameter.
930
     *
931
     * @param string $filterString The filter to add, in the form of field:value
932
     * @return void
933
     */
934 37
    public function addFilter($filterString)
935
    {
936
        // TODO refactor to split filter field and filter value, @see Drupal
937 37
        if ($this->solrConfiguration->getLoggingQueryFilters()) {
938
            $this->logger->log(
939
                SolrLogManager::INFO,
940
                'Adding filter',
941
                [
942
                    $filterString
943
                ]
944
            );
945
        }
946
947 37
        $this->filters[] = $filterString;
948 37
    }
949
950
951
    // query parameters
952
953
    /**
954
     * Limits the query to certain sites
955
     *
956
     * @param string $allowedSites Comma-separated list of domains
957
     */
958 26
    public function setSiteHashFilter($allowedSites)
959
    {
960 26
        if (trim($allowedSites) === '*') {
961 1
            return;
962
        }
963
964 25
        $allowedSites = GeneralUtility::trimExplode(',', $allowedSites);
965 25
        $filters = [];
966
967 25
        foreach ($allowedSites as $site) {
968 25
            $siteHash = $this->siteHashService->getSiteHashForDomain($site);
969 25
            $filters[] = 'siteHash:"' . $siteHash . '"';
970 25
        }
971
972 25
        $this->addFilter(implode(' OR ', $filters));
973 25
    }
974
975
    /**
976
     * Limits the query to certain page tree branches
977
     *
978
     * @param string $pageIds Comma-separated list of page IDs
979
     */
980
    public function setRootlineFilter($pageIds)
981
    {
982
        $pageIds = GeneralUtility::trimExplode(',', $pageIds);
983
        $filters = [];
984
985
            /** @var $processor PageUidToHierarchy */
986
        $processor = GeneralUtility::makeInstance(PageUidToHierarchy::class);
987
        $hierarchies = $processor->process($pageIds);
988
989
        foreach ($hierarchies as $hierarchy) {
990
            $lastLevel = array_pop($hierarchy);
991
            $filters[] = 'rootline:"' . $lastLevel . '"';
992
        }
993
994
        $this->addFilter(implode(' OR ', $filters));
995
    }
996
997
    /**
998
     * Adds a sort field and the sorting direction for that field
999
     *
1000
     * @param string $fieldName The field name to sort by
1001
     * @param string $direction Either ApacheSolrForTypo3\Solr\Query::SORT_ASC to sort the field ascending or ApacheSolrForTypo3\Solr\Query::SORT_DESC to sort descending
1002
     * @return void
1003
     * @throws \InvalidArgumentException if the $direction parameter given is neither ApacheSolrForTypo3\Solr\Query::SORT_ASC nor ApacheSolrForTypo3\Solr\Query::SORT_DESC
1004
     * @deprecated since 6.1 will be removed in 7.0
1005
     */
1006 1
    public function addSortField($fieldName, $direction)
1007
    {
1008 1
        GeneralUtility::logDeprecatedFunction();
1009
1010 1
        $isValidSorting = $direction === self::SORT_DESC || $direction === self::SORT_ASC;
1011 1
        if (!$isValidSorting) {
1012 1
            throw new \InvalidArgumentException('Invalid sort direction "' . $direction . '"', 1235051723);
1013
        }
1014
1015 1
        $this->sortingFields[$fieldName] = $direction;
0 ignored issues
show
Deprecated Code introduced by
The property ApacheSolrForTypo3\Solr\Query::$sortingFields has been deprecated with message: since 6.1 will be removed in 7.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1016 1
    }
1017
1018
    /**
1019
     * Gets the currently set sorting fields and their sorting directions
1020
     *
1021
     * @return array An associative array with the field names as key and their sorting direction as value
1022
     * @deprecated since 6.1 will be removed in 7.0
1023
     */
1024 1
    public function getSortingFields()
1025
    {
1026 1
        GeneralUtility::logDeprecatedFunction();
1027
1028 1
        return $this->sortingFields;
0 ignored issues
show
Deprecated Code introduced by
The property ApacheSolrForTypo3\Solr\Query::$sortingFields has been deprecated with message: since 6.1 will be removed in 7.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1029
    }
1030
1031
    /**
1032
     * Gets the list of fields a query will return.
1033
     *
1034
     * @return array Array of field names the query will return
1035
     */
1036 6
    public function getFieldList()
1037
    {
1038 6
        return $this->fieldList;
1039
    }
1040
1041
    /**
1042
     * Sets the fields to return by a query.
1043
     *
1044
     * @param array|string $fieldList an array or comma-separated list of field names
1045
     * @throws \UnexpectedValueException on parameters other than comma-separated lists and arrays
1046
     */
1047 3
    public function setFieldList($fieldList = ['*', 'score'])
1048
    {
1049 3
        if (is_string($fieldList)) {
1050 2
            $fieldList = GeneralUtility::trimExplode(',', $fieldList);
1051 2
        }
1052
1053 3
        if (!is_array($fieldList) || empty($fieldList)) {
1054 1
            throw new \UnexpectedValueException(
1055 1
                'Field list must be a comma-separated list or array and must not be empty.',
1056
                1310740308
1057 1
            );
1058
        }
1059
1060 3
        $this->fieldList = $fieldList;
1061 3
    }
1062
1063
    /**
1064
     * Gets the query type, Solr's qt parameter.
1065
     *
1066
     * @return string Query type, qt parameter.
1067
     */
1068 1
    public function getQueryType()
1069
    {
1070 1
        return $this->queryParameters['qt'];
1071
    }
1072
1073
    /**
1074
     * Sets the query type, Solr's qt parameter.
1075
     *
1076
     * @param string|bool $queryType String query type or boolean FALSE to disable / reset the qt parameter.
1077
     * @see http://wiki.apache.org/solr/CoreQueryParameters#qt
1078
     */
1079 2
    public function setQueryType($queryType)
1080
    {
1081 2
        if ($queryType) {
1082 2
            $this->queryParameters['qt'] = $queryType;
1083 2
        } else {
1084 1
            unset($this->queryParameters['qt']);
1085
        }
1086 2
    }
1087
1088
    /**
1089
     * Sets the query operator to AND or OR. Unsets the query operator (actually
1090
     * sets it back to default) for FALSE.
1091
     *
1092
     * @param string|bool $operator AND or OR, FALSE to unset
1093
     */
1094 1
    public function setOperator($operator)
1095
    {
1096 1
        if (in_array($operator, [self::OPERATOR_AND, self::OPERATOR_OR])) {
1097 1
            $this->queryParameters['q.op'] = $operator;
1098 1
        }
1099
1100 1
        if ($operator === false) {
1101 1
            unset($this->queryParameters['q.op']);
1102 1
        }
1103 1
    }
1104
1105
    /**
1106
     * Gets the alternative query, Solr's q.alt parameter.
1107
     *
1108
     * @return string Alternative query, q.alt parameter.
1109
     */
1110 1
    public function getAlternativeQuery()
1111
    {
1112 1
        return $this->queryParameters['q.alt'];
1113
    }
1114
1115
    /**
1116
     * Sets an alternative query, Solr's q.alt parameter.
1117
     *
1118
     * This query supports the complete Lucene Query Language.
1119
     *
1120
     * @param mixed $alternativeQuery String alternative query or boolean FALSE to disable / reset the q.alt parameter.
1121
     * @see http://wiki.apache.org/solr/DisMaxQParserPlugin#q.alt
1122
     */
1123 26
    public function setAlternativeQuery($alternativeQuery)
1124
    {
1125 26
        if ($alternativeQuery) {
1126 26
            $this->queryParameters['q.alt'] = $alternativeQuery;
1127 26
        } else {
1128 1
            unset($this->queryParameters['q.alt']);
1129
        }
1130 26
    }
1131
1132
    // keywords
1133
1134
    /**
1135
     * Set the query to omit the response header
1136
     *
1137
     * @param bool $omitHeader TRUE (default) to omit response headers, FALSE to re-enable
1138
     */
1139 1
    public function setOmitHeader($omitHeader = true)
1140
    {
1141 1
        if ($omitHeader) {
1142 1
            $this->queryParameters['omitHeader'] = 'true';
1143 1
        } else {
1144 1
            unset($this->queryParameters['omitHeader']);
1145
        }
1146 1
    }
1147
1148
    /**
1149
     * Get the query keywords, keywords are escaped.
1150
     *
1151
     * @return string query keywords
1152
     */
1153 20
    public function getKeywords()
1154
    {
1155 20
        return $this->keywords;
1156
    }
1157
1158
    /**
1159
     * Sets the query keywords, escapes them as needed for Solr/Lucene.
1160
     *
1161
     * @param string $keywords user search terms/keywords
1162
     */
1163 132
    public function setKeywords($keywords)
1164
    {
1165 132
        $this->keywords = $this->escape($keywords);
1166 132
        $this->keywordsRaw = $keywords;
1167 132
    }
1168
1169
    /**
1170
     * Gets the cleaned keywords so that it can be used in templates f.e.
1171
     *
1172
     * @return string The cleaned keywords.
1173
     */
1174 18
    public function getKeywordsCleaned()
1175
    {
1176 18
        return $this->cleanKeywords($this->keywordsRaw);
1177
    }
1178
1179
    /**
1180
     * Helper method to escape/encode keywords for use in HTML
1181
     *
1182
     * @param string $keywords Keywords to prepare for use in HTML
1183
     * @return string Encoded keywords
1184
     */
1185 22
    public static function cleanKeywords($keywords)
1186
    {
1187 22
        $keywords = trim($keywords);
1188 22
        $keywords = GeneralUtility::removeXSS($keywords);
1189 22
        $keywords = htmlentities($keywords, ENT_QUOTES,
1190 22
            $GLOBALS['TSFE']->metaCharset);
1191
1192
        // escape triple hashes as they are used in the template engine
1193
        // TODO remove after switching to fluid templates
1194 22
        $keywords = Template::escapeMarkers($keywords);
1195
1196 22
        return $keywords;
1197
    }
1198
1199
    // relevance, matching
1200
1201
    /**
1202
     * Gets the raw, unescaped, unencoded keywords.
1203
     *
1204
     * USE WITH CAUTION!
1205
     *
1206
     * @return string raw keywords
1207
     */
1208 19
    public function getKeywordsRaw()
1209
    {
1210 19
        return $this->keywordsRaw;
1211
    }
1212
1213
    /**
1214
     * Sets the minimum match (mm) parameter
1215
     *
1216
     * @param mixed $minimumMatch Minimum match parameter as string or boolean FALSE to disable / reset the mm parameter
1217
     * @see http://wiki.apache.org/solr/DisMaxRequestHandler#mm_.28Minimum_.27Should.27_Match.29
1218
     */
1219 1
    public function setMinimumMatch($minimumMatch)
1220
    {
1221 1
        if (is_string($minimumMatch) && !empty($minimumMatch)) {
1222 1
            $this->queryParameters['mm'] = $minimumMatch;
1223 1
        } else {
1224 1
            unset($this->queryParameters['mm']);
1225
        }
1226 1
    }
1227
1228
    /**
1229
     * Sets the boost function (bf) parameter
1230
     *
1231
     * @param mixed $boostFunction boost function parameter as string or boolean FALSE to disable / reset the bf parameter
1232
     * @see http://wiki.apache.org/solr/DisMaxRequestHandler#bf_.28Boost_Functions.29
1233
     */
1234 1
    public function setBoostFunction($boostFunction)
1235
    {
1236 1
        if (is_string($boostFunction) && !empty($boostFunction)) {
1237 1
            $this->queryParameters['bf'] = $boostFunction;
1238 1
        } else {
1239 1
            unset($this->queryParameters['bf']);
1240
        }
1241 1
    }
1242
1243
    // query fields
1244
    // TODO move up to field list methods
1245
1246
    /**
1247
     * Sets the boost query (bq) parameter
1248
     *
1249
     * @param mixed $boostQuery boost query parameter as string or array to set a boost query or boolean FALSE to disable / reset the bq parameter
1250
     * @see http://wiki.apache.org/solr/DisMaxQParserPlugin#bq_.28Boost_Query.29
1251
     */
1252 1
    public function setBoostQuery($boostQuery)
1253
    {
1254 1
        if ((is_string($boostQuery) || is_array($boostQuery)) && !empty($boostQuery)) {
1255 1
            $this->queryParameters['bq'] = $boostQuery;
1256 1
        } else {
1257 1
            unset($this->queryParameters['bq']);
1258
        }
1259 1
    }
1260
1261
    /**
1262
     * Gets a specific query parameter by its name.
1263
     *
1264
     * @param string $parameterName The parameter to return
1265
     * @param mixed $defaultIfEmpty
1266
     * @return mixed The parameter's value or $defaultIfEmpty if not set
1267
     */
1268 10
    public function getQueryParameter($parameterName, $defaultIfEmpty = null)
1269
    {
1270 10
        $parameters = $this->getQueryParameters();
1271 10
        return isset($parameters[$parameterName]) ? $parameters[$parameterName] : $defaultIfEmpty;
1272
    }
1273
1274
    /**
1275
     * Builds an array of query parameters to use for the search query.
1276
     *
1277
     * @return array An array ready to use with query parameters
1278
     */
1279 64
    public function getQueryParameters()
1280
    {
1281 64
        $queryParameters = array_merge(
1282
            [
1283 64
                'fl' => implode(',', $this->fieldList),
1284 64
                'fq' => array_values($this->filters)
1285 64
            ],
1286 64
            $this->queryParameters
1287 64
        );
1288
1289 64
        $queryFieldString = $this->getQueryFieldsAsString();
1290 64
        if (!empty($queryFieldString)) {
1291 27
            $queryParameters['qf'] = $queryFieldString;
1292 27
        }
1293
1294 64
        return $queryParameters;
1295
    }
1296
1297
    // general query parameters
1298
1299
    /**
1300
     * Compiles the query fields into a string to be used in Solr's qf parameter.
1301
     *
1302
     * @return string A string of query fields with their associated boosts
1303
     */
1304 66
    public function getQueryFieldsAsString()
1305
    {
1306 66
        $queryFieldString = '';
1307
1308 66
        foreach ($this->queryFields as $fieldName => $fieldBoost) {
1309 28
            $queryFieldString .= $fieldName;
1310
1311 28
            if ($fieldBoost != 1.0) {
1312 28
                $queryFieldString .= '^' . number_format($fieldBoost, 1, '.', '');
1313 28
            }
1314
1315 28
            $queryFieldString .= ' ';
1316 66
        }
1317
1318 66
        return trim($queryFieldString);
1319
    }
1320
1321
    /**
1322
     * Enables or disables highlighting of search terms in result teasers.
1323
     *
1324
     * @param bool $highlighting Enables highlighting when set to TRUE, deactivates highlighting when set to FALSE, defaults to TRUE.
1325
     * @param int $fragmentSize Size, in characters, of fragments to consider for highlighting.
1326
     * @see http://wiki.apache.org/solr/HighlightingParameters
1327
     * @return void
1328
     */
1329 31
    public function setHighlighting($highlighting = true, $fragmentSize = 200)
1330
    {
1331 31
        if ($highlighting) {
1332 31
            $this->queryParameters['hl'] = 'true';
1333 31
            $this->queryParameters['hl.fragsize'] = (int)$fragmentSize;
1334
1335 31
            $highlightingFields = $this->solrConfiguration->getSearchResultsHighlightingFields();
1336 31
            if ($highlightingFields != '') {
1337 25
                $this->queryParameters['hl.fl'] = $highlightingFields;
1338 25
            }
1339
1340
            // the fast vector highlighter can only be used, when the fragmentSize is
1341
            // higher then 17 otherwise solr throws an exception
1342 31
            $useFastVectorHighlighter = ($fragmentSize >= 18);
1343 31
            $wrap = explode('|', $this->solrConfiguration->getSearchResultsHighlightingWrap());
1344
1345 31
            if ($useFastVectorHighlighter) {
1346 29
                $this->queryParameters['hl.useFastVectorHighlighter'] = 'true';
1347 29
                $this->queryParameters['hl.tag.pre'] = $wrap[0];
1348 29
                $this->queryParameters['hl.tag.post'] = $wrap[1];
1349 29
            }
1350
1351 31
            if (isset($wrap[0]) && isset($wrap[1])) {
1352 26
                $this->queryParameters['hl.simple.pre'] = $wrap[0];
1353 26
                $this->queryParameters['hl.simple.post'] = $wrap[1];
1354 26
            }
1355 31
        } else {
1356
            // remove all hl.* settings
1357 1
            foreach ($this->queryParameters as $key => $value) {
1358 1
                if (GeneralUtility::isFirstPartOfStr($key, 'hl')) {
1359 1
                    unset($this->queryParameters[$key]);
1360 1
                }
1361 1
            }
1362
        }
1363 31
    }
1364
1365
    // misc
1366
1367
    /**
1368
     * Enables or disables spellchecking for the query.
1369
     *
1370
     * @param bool $spellchecking Enables spellchecking when set to TRUE, deactivates spellchecking when set to FALSE, defaults to TRUE.
1371
     */
1372 22
    public function setSpellchecking($spellchecking = true)
1373
    {
1374 22
        if ($spellchecking) {
1375 22
            $this->queryParameters['spellcheck'] = 'true';
1376 22
            $this->queryParameters['spellcheck.collate'] = 'true';
1377 22
            $maxCollationTries = $this->solrConfiguration->getSearchSpellcheckingNumberOfSuggestionsToTry();
1378 22
            $this->addQueryParameter('spellcheck.maxCollationTries', $maxCollationTries);
1379 22
        } else {
1380 1
            unset($this->queryParameters['spellcheck']);
1381 1
            unset($this->queryParameters['spellcheck.collate']);
1382 1
            unset($this->queryParameters['spellcheck.maxCollationTries']);
1383
        }
1384 22
    }
1385
1386
    /**
1387
     * Adds any generic query parameter.
1388
     *
1389
     * @param string $parameterName Query parameter name
1390
     * @param string $parameterValue Parameter value
1391
     */
1392 30
    public function addQueryParameter($parameterName, $parameterValue)
1393
    {
1394 30
        $this->queryParameters[$parameterName] = $parameterValue;
1395 30
    }
1396
1397
    /**
1398
     * Sets the sort parameter.
1399
     *
1400
     * $sorting must include a field name (or the pseudo-field score),
1401
     * followed by a space,
1402
     * followed by a sort direction (asc or desc).
1403
     *
1404
     * Multiple fallback sortings can be separated by comma,
1405
     * ie: <field name> <direction>[,<field name> <direction>]...
1406
     *
1407
     * @param string|bool $sorting Either a comma-separated list of sort fields and directions or FALSE to reset sorting to the default behavior (sort by score / relevance)
1408
     * @see http://wiki.apache.org/solr/CommonQueryParameters#sort
1409
     */
1410 3
    public function setSorting($sorting)
1411
    {
1412 3
        if ($sorting) {
1413 3
            if (!is_string($sorting)) {
1414
                throw new \InvalidArgumentException('Sorting needs to be a string!');
1415
            }
1416 3
            $sortParameter = $this->removeRelevanceSortField($sorting);
1417 3
            $this->queryParameters['sort'] = $sortParameter;
1418 3
        } else {
1419 1
            unset($this->queryParameters['sort']);
1420
        }
1421 3
    }
1422
1423
    /**
1424
     * Removes the relevance sort field if present in the sorting field definition.
1425
     *
1426
     * @param string $sorting
1427
     * @return string
1428
     */
1429 3
    protected function removeRelevanceSortField($sorting)
1430
    {
1431 3
        $sortParameter = $sorting;
1432 3
        list($sortField) = explode(' ', $sorting);
1433 3
        if ($sortField == 'relevance') {
1434 1
            $sortParameter = '';
1435 1
            return $sortParameter;
1436
        }
1437
1438 3
        return $sortParameter;
1439
    }
1440
1441
    /**
1442
     * Enables or disables the debug parameter for the query.
1443
     *
1444
     * @param bool $debugMode Enables debugging when set to TRUE, deactivates debugging when set to FALSE, defaults to TRUE.
1445
     */
1446
    public function setDebugMode($debugMode = true)
1447
    {
1448
        if ($debugMode) {
1449
            $this->queryParameters['debugQuery'] = 'true';
1450
            $this->queryParameters['echoParams'] = 'all';
1451
        } else {
1452
            unset($this->queryParameters['debugQuery']);
1453
            unset($this->queryParameters['echoParams']);
1454
        }
1455
    }
1456
1457
    /**
1458
     * Returns the link target page id.
1459
     *
1460
     * @return int
1461
     */
1462 2
    public function getLinkTargetPageId()
1463
    {
1464 2
        return $this->linkTargetPageId;
1465
    }
1466
1467
    /**
1468
     * Activates the collapsing on the configured field, if collapsing was enabled.
1469
     *
1470
     * @return bool
1471
     */
1472 131
    protected function initializeCollapsingFromConfiguration()
1473
    {
1474
        // check collapsing
1475 131
        if ($this->solrConfiguration->getSearchVariants()) {
1476 3
            $collapseField = $this->solrConfiguration->getSearchVariantsField();
1477 3
            $this->setVariantField($collapseField);
1478 3
            $this->setCollapsing(true);
1479
1480 3
            return true;
1481
        }
1482
1483 128
        return false;
1484
    }
1485
}
1486