tx_dlf_search::addFacetsMenu()   B
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 45
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 16
nc 5
nop 0
dl 0
loc 45
rs 8.439
c 0
b 0
f 0
1
<?php
2
/**
3
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
4
 *
5
 * This file is part of the Kitodo and TYPO3 projects.
6
 *
7
 * @license GNU General Public License version 3 or later.
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
/**
13
 * Plugin 'DLF: Search' for the 'dlf' extension.
14
 *
15
 * @author	Sebastian Meyer <[email protected]>
16
 * @author	Henrik Lochmann <[email protected]>
17
 * @package	TYPO3
18
 * @subpackage	tx_dlf
19
 * @access	public
20
 */
21
class tx_dlf_search extends tx_dlf_plugin {
22
23
    public $scriptRelPath = 'plugins/search/class.tx_dlf_search.php';
24
25
    /**
26
     * Adds the JS files necessary for search suggestions
27
     *
28
     * @access	protected
29
     *
30
     * @return	void
31
     */
32
    protected function addAutocompleteJS() {
33
34
        // Check if there are any metadata to suggest.
35
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
36
            'tx_dlf_metadata.*',
37
            'tx_dlf_metadata',
38
            'tx_dlf_metadata.index_autocomplete=1 AND tx_dlf_metadata.pid='.intval($this->conf['pages']).tx_dlf_helper::whereClause('tx_dlf_metadata'),
39
            '',
40
            '',
41
            '1'
42
        );
43
44
45
        if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
46
47
            $GLOBALS['TSFE']->additionalHeaderData[$this->prefixId.'_search_suggest'] = '<script type="text/javascript" src="'.\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath($this->extKey).'plugins/search/tx_dlf_search_suggest.js"></script>';
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\Utility\ExtensionManagementUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
48
49
        } else {
50
51
            if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
52
53
                \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_search->addAutocompleteJS()] No metadata fields configured for search suggestions', $this->extKey, SYSLOG_SEVERITY_WARNING);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_WARNING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The type TYPO3\CMS\Core\Utility\GeneralUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
54
55
            }
56
57
        }
58
59
    }
60
61
    /**
62
     * Adds the current collection's UID to the search form
63
     *
64
     * @access	protected
65
     *
66
     * @return	string		HTML input fields with current document's UID and parent ID
67
     */
68
    protected function addCurrentCollection() {
69
70
        // Load current collection.
71
        $list = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tx_dlf_list');
72
73
        if (!empty($list->metadata['options']['source']) && $list->metadata['options']['source'] == 'collection') {
74
75
            // Get collection's UID.
76
            return '<input type="hidden" name="'.$this->prefixId.'[collection]" value="'.$list->metadata['options']['select'].'" />';
77
78
        } elseif (!empty($list->metadata['options']['params']['fq'])) {
79
80
            // Get collection's UID from search metadata.
81
            foreach ($list->metadata['options']['params']['fq'] as $id => $facet) {
82
83
                $facetKeyVal = explode(':', $facet, 2);
84
85
                if ($facetKeyVal[0] == 'collection_faceting' && !strpos($facetKeyVal[1], '" OR "')) {
86
87
                    $collectionId = tx_dlf_helper::getIdFromIndexName(trim($facetKeyVal[1], '(")'), 'tx_dlf_collections');
88
89
                }
90
91
            }
92
93
            return '<input type="hidden" name="'.$this->prefixId.'[collection]" value="'.$collectionId.'" />';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $collectionId does not seem to be defined for all execution paths leading up to this point.
Loading history...
94
95
        }
96
97
        return '';
98
99
    }
100
101
    /**
102
     * Adds the current document's UID or parent ID to the search form
103
     *
104
     * @access	protected
105
     *
106
     * @return	string		HTML input fields with current document's UID and parent ID
107
     */
108
    protected function addCurrentDocument() {
109
110
        // Load current list object.
111
        $list = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tx_dlf_list');
112
113
        // Load current document.
114
        if (!empty($this->piVars['id']) && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($this->piVars['id'])) {
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\Utility\MathUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
115
116
            $this->loadDocument();
117
118
            // Get document's UID or parent ID.
119
            if ($this->doc->ready) {
120
121
                return '<input type="hidden" name="'.$this->prefixId.'[id]" value="'.($this->doc->parentId > 0 ? $this->doc->parentId : $this->doc->uid).'" />';
122
123
            }
124
125
        } elseif (!empty($list->metadata['options']['params']['fq'])) {
126
127
            // Get document's UID from search metadata.
128
            foreach ($list->metadata['options']['params']['fq'] as $id => $facet) {
129
130
                $facetKeyVal = explode(':', $facet);
131
132
                if ($facetKeyVal[0] == 'uid') {
133
134
                    $documentId = (int) substr($facetKeyVal[1], 1, strpos($facetKeyVal[1], ')'));
135
136
                }
137
138
            }
139
140
            return '<input type="hidden" name="'.$this->prefixId.'[id]" value="'.$documentId.'" />';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $documentId does not seem to be defined for all execution paths leading up to this point.
Loading history...
141
142
        }
143
144
        return '';
145
146
    }
147
148
    /**
149
     * Adds the encrypted Solr core name to the search form
150
     *
151
     * @access	protected
152
     *
153
     * @return	string		HTML input fields with encrypted core name and hash
154
     */
155
    protected function addEncryptedCoreName() {
156
157
        // Get core name.
158
        $name = tx_dlf_helper::getIndexName($this->conf['solrcore'], 'tx_dlf_solrcores');
159
160
        // Encrypt core name.
161
        if (!empty($name)) {
162
163
            $name = tx_dlf_helper::encrypt($name);
164
165
        }
166
167
        // Add encrypted fields to search form.
168
        if (is_array($name)) {
169
170
            return '<input type="hidden" name="'.$this->prefixId.'[encrypted]" value="'.$name['encrypted'].'" /><input type="hidden" name="'.$this->prefixId.'[hashed]" value="'.$name['hash'].'" />';
171
172
        } else {
173
174
            return '';
175
176
        }
177
178
    }
179
180
    /**
181
     * Returns the extended search form and adds the JS files necessary for extended search.
182
     *
183
     * @access	protected
184
     *
185
     * @return	string		The extended search form or an empty string
186
     */
187
    protected function addExtendedSearch() {
188
189
        $extendedSearch = '';
190
191
        // Quit without doing anything if no fields for extended search are selected.
192
        if (empty($this->conf['extendedSlotCount']) || empty($this->conf['extendedFields'])) {
193
194
            return $extendedSearch;
195
196
        }
197
198
        // Get operator options.
199
        $operatorOptions = '';
200
201
        foreach (array ('AND', 'OR', 'NOT') as $operator) {
202
203
            $operatorOptions .= '<option class="tx-dlf-search-operator-option tx-dlf-search-operator-'.$operator.'" value="'.$operator.'">'.$this->pi_getLL($operator, '', TRUE).'</option>';
204
205
        }
206
207
        // Get field selector options.
208
        $fieldSelectorOptions = '';
209
210
        $searchFields = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->conf['extendedFields'], TRUE);
211
212
        foreach ($searchFields as $searchField) {
213
214
            $fieldSelectorOptions .= '<option class="tx-dlf-search-field-option tx-dlf-search-field-'.$searchField.'" value="'.$searchField.'">'.tx_dlf_helper::translate($searchField, 'tx_dlf_metadata', $this->conf['pages']).'</option>';
215
216
        }
217
218
        for ($i = 0; $i < $this->conf['extendedSlotCount']; $i++) {
219
220
            $markerArray = array (
221
                '###EXT_SEARCH_OPERATOR###' => '<select class="tx-dlf-search-operator tx-dlf-search-operator-'.$i.'" name="'.$this->prefixId.'[extOperator]['.$i.']">'.$operatorOptions.'</select>',
222
                '###EXT_SEARCH_FIELDSELECTOR###' => '<select class="tx-dlf-search-field tx-dlf-search-field-'.$i.'" name="'.$this->prefixId.'[extField]['.$i.']">'.$fieldSelectorOptions.'</select>',
223
                '###EXT_SEARCH_FIELDQUERY###' => '<input class="tx-dlf-search-query tx-dlf-search-query-'.$i.'" type="text" name="'.$this->prefixId.'[extQuery]['.$i.']" />'
224
            );
225
226
            $extendedSearch .= $this->cObj->substituteMarkerArray($this->cObj->getSubpart($this->template, '###EXT_SEARCH_ENTRY###'), $markerArray);
227
228
        }
229
230
        return $extendedSearch;
231
232
    }
233
234
    /**
235
     * Adds the facets menu to the search form
236
     *
237
     * @access	protected
238
     *
239
     * @return	string		HTML output of facets menu
240
     */
241
    protected function addFacetsMenu() {
242
243
        // Check for typoscript configuration to prevent fatal error.
244
        if (empty($this->conf['facetsConf.'])) {
245
246
            if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
247
248
                \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_search->addFacetsMenu()] Incomplete plugin configuration', $this->extKey, SYSLOG_SEVERITY_WARNING);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_WARNING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
249
250
            }
251
252
            return '';
253
254
        }
255
256
        // Quit without doing anything if no facets are selected.
257
        if (empty($this->conf['facets'])) {
258
259
            return '';
260
261
        }
262
263
        // Get facets from plugin configuration.
264
        $facets = array ();
265
266
        foreach (\TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->conf['facets'], TRUE) as $facet) {
267
268
            $facets[$facet.'_faceting'] = tx_dlf_helper::translate($facet, 'tx_dlf_metadata', $this->conf['pages']);
269
270
        }
271
272
        // Render facets menu.
273
        $TSconfig = array ();
274
275
        $TSconfig['special'] = 'userfunction';
276
277
        $TSconfig['special.']['userFunc'] = 'tx_dlf_search->makeFacetsMenuArray';
278
279
        $TSconfig['special.']['facets'] = $facets;
280
281
        $TSconfig['special.']['limit'] = max(intval($this->conf['limitFacets']), 1);
282
283
        $TSconfig = tx_dlf_helper::array_merge_recursive_overrule($this->conf['facetsConf.'], $TSconfig);
284
285
        return $this->cObj->HMENU($TSconfig);
286
287
    }
288
289
    /**
290
     * Adds the fulltext switch to the search form
291
     *
292
     * @access	protected
293
     *
294
     * @param int $isFulltextSearch
295
     *
296
     * @return	string		HTML output of fulltext switch
297
     */
298
    protected function addFulltextSwitch($isFulltextSearch = 0) {
299
300
        $output = '';
301
302
        // Check for plugin configuration.
303
        if (!empty($this->conf['fulltext'])) {
304
305
            $output .= ' <input class="tx-dlf-search-fulltext" id="tx-dlf-search-fulltext-no" type="radio" name="'.$this->prefixId.'[fulltext]" value="0" '.($isFulltextSearch == 0 ? 'checked="checked"' : '').' />';
306
307
            $output .= ' <label for="tx-dlf-search-fulltext-no">'.$this->pi_getLL('label.inMetadata', '').'</label>';
308
309
            $output .= ' <input class="tx-dlf-search-fulltext" id="tx-dlf-search-fulltext-yes" type="radio" name="'.$this->prefixId.'[fulltext]" value="1" '.($isFulltextSearch == 1 ? 'checked="checked"' : '').'/>';
310
311
            $output .= ' <label for="tx-dlf-search-fulltext-yes">'.$this->pi_getLL('label.inFulltext', '').'</label>';
312
313
        }
314
315
        return $output;
316
317
    }
318
319
    /**
320
     * Adds the logical page field to the search form
321
     *
322
     * @access	protected
323
     *
324
     * @return	string		HTML output of logical page field
325
     */
326
    protected function addLogicalPage() {
327
		
328
        $output = '';
329
330
        // Check for plugin configuration.
331
        if (!empty($this->conf['showLogicalPageField'])) {
332
			
333
            $output .= ' <label for="tx-dlf-search-logical-page">'.$this->pi_getLL('label.logicalPage', '').': </label>';
334
			
335
            $output .= ' <input class="tx-dlf-search-logical-page" id="tx-dlf-search-logical-page" type="text" name="'.$this->prefixId.'[logicalPage]" />';
336
			
337
        }
338
339
        return $output;
340
		
341
    }
342
343
    /**
344
     * Creates an array for a HMENU entry of a facet value.
345
     *
346
     * @param	string		$field: The facet's index_name
347
     * @param	string		$value: The facet's value
348
     * @param	integer		$count: Number of hits for this facet
349
     * @param	array		$search: The parameters of the current search query
350
     * @param	string		&$state: The state of the parent item
351
     *
352
     * @return	array		The array for the facet's menu entry
353
     */
354
    protected function getFacetsMenuEntry($field, $value, $count, $search, &$state) {
355
356
        $entryArray = array ();
357
358
        // Translate value.
359
        if ($field == 'owner_faceting') {
360
361
            // Translate name of holding library.
362
            $entryArray['title'] = htmlspecialchars(tx_dlf_helper::translate($value, 'tx_dlf_libraries', $this->conf['pages']));
363
364
        } elseif ($field == 'type_faceting') {
365
366
            // Translate document type.
367
            $entryArray['title'] = htmlspecialchars(tx_dlf_helper::translate($value, 'tx_dlf_structures', $this->conf['pages']));
368
369
        } elseif ($field == 'collection_faceting') {
370
371
            // Translate name of collection.
372
            $entryArray['title'] = htmlspecialchars(tx_dlf_helper::translate($value, 'tx_dlf_collections', $this->conf['pages']));
373
374
        } elseif ($field == 'language_faceting') {
375
376
            // Translate ISO 639 language code.
377
            $entryArray['title'] = htmlspecialchars(tx_dlf_helper::getLanguageName($value));
378
379
        } else {
380
381
            $entryArray['title'] = htmlspecialchars($value);
382
383
        }
384
385
        $entryArray['count'] = $count;
386
387
        $entryArray['doNotLinkIt'] = 0;
388
389
        // Check if facet is already selected.
390
        $index = array_search($field.':("'.tx_dlf_solr::escapeQuery($value).'")', $search['params']['fq']);
391
392
        if ($index !== FALSE) {
393
394
            // Facet is selected, thus remove it from filter.
395
            unset($search['params']['fq'][$index]);
396
397
            $search['params']['fq'] = array_values($search['params']['fq']);
398
399
            $entryArray['ITEM_STATE'] = 'CUR';
400
401
            $state = 'ACTIFSUB';
402
403
            //Reset facets
404
            if ($this->conf['resetFacets']) {
405
                //remove ($count) for selected facet in template
406
                $entryArray['count'] = FALSE;
407
                //build link to delete selected facet
408
                $entryArray['_OVERRIDE_HREF'] = $this->pi_linkTP_keepPIvars_url(array ('query' => $search['query'], 'fq' => $search['params']['fq']));
409
                $entryArray['title'] = sprintf($this->pi_getLL('resetFacet', ''), $entryArray['title']);
410
            }
411
412
        } else {
413
414
            // Facet is not selected, thus add it to filter.
415
            $search['params']['fq'][] = $field.':("'.tx_dlf_solr::escapeQuery($value).'")';
416
417
            $entryArray['ITEM_STATE'] = 'NO';
418
419
        }
420
421
        $entryArray['_OVERRIDE_HREF'] = $this->pi_linkTP_keepPIvars_url(array ('query' => $search['query'], 'fq' => $search['params']['fq']));
422
423
        return $entryArray;
424
425
    }
426
427
    /**
428
     * The main method of the PlugIn
429
     *
430
     * @access	public
431
     *
432
     * @param	string		$content: The PlugIn content
433
     * @param	array		$conf: The PlugIn configuration
434
     *
435
     * @return	string		The content that is displayed on the website
436
     */
437
    public function main($content, $conf) {
438
439
        $this->init($conf);
440
441
        // Disable caching for this plugin.
442
        $this->setCache(FALSE);
443
444
        // Quit without doing anything if required variables are not set.
445
        if (empty($this->conf['solrcore'])) {
446
447
            if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
448
449
                \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_search->main('.$content.', [data])] Incomplete plugin configuration', $this->extKey, SYSLOG_SEVERITY_WARNING, $conf);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_WARNING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
450
451
            }
452
453
            return $content;
454
455
        }
456
457
        if (!isset($this->piVars['query']) && empty($this->piVars['extQuery'])) {
458
459
            // Extract query and filter from last search.
460
            $list = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tx_dlf_list');
461
462
            if (!empty($list->metadata['searchString'])) {
463
464
                if ($list->metadata['options']['source'] == 'search') {
465
466
                    $search['query'] = $list->metadata['searchString'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$search was never initialized. Although not strictly required by PHP, it is generally a good practice to add $search = array(); before regardless.
Loading history...
467
468
                }
469
470
                $search['params'] = $list->metadata['options']['params'];
471
472
            }
473
474
            // Add javascript for search suggestions if enabled and jQuery autocompletion is available.
475
            if (!empty($this->conf['suggest'])) {
476
477
                $this->addAutocompleteJS();
478
479
            }
480
481
            // Load template file.
482
            if (!empty($this->conf['templateFile'])) {
483
484
                $this->template = $this->cObj->getSubpart($this->cObj->fileResource($this->conf['templateFile']), '###TEMPLATE###');
485
486
            } else {
487
488
                $this->template = $this->cObj->getSubpart($this->cObj->fileResource('EXT:dlf/plugins/search/template.tmpl'), '###TEMPLATE###');
489
490
            }
491
492
            // Configure @action URL for form.
493
            $linkConf = array (
494
                'parameter' => $GLOBALS['TSFE']->id,
495
                'forceAbsoluteUrl' => 1
496
            );
497
498
            // Fill markers.
499
            $markerArray = array (
500
                '###ACTION_URL###' => $this->cObj->typoLink_URL($linkConf),
501
                '###LABEL_QUERY###' => (!empty($search['query']) ? $search['query'] : $this->pi_getLL('label.query')),
502
                '###LABEL_SUBMIT###' => $this->pi_getLL('label.submit'),
503
                '###FIELD_QUERY###' => $this->prefixId.'[query]',
504
                '###QUERY###' => (!empty($search['query']) ? $search['query'] : ''),
505
                '###FULLTEXTSWITCH###' => $this->addFulltextSwitch($list->metadata['fulltextSearch']),
506
                '###FIELD_DOC###' => ($this->conf['searchIn'] == 'document' || $this->conf['searchIn'] == 'all' ? $this->addCurrentDocument() : ''),
507
                '###FIELD_COLL###' => ($this->conf['searchIn'] == 'collection' || $this->conf['searchIn'] == 'all' ? $this->addCurrentCollection() : ''),
508
                '###ADDITIONAL_INPUTS###' => $this->addEncryptedCoreName(),
509
                '###FACETS_MENU###' => $this->addFacetsMenu(),
510
                '###LOGICAL_PAGE###' => $this->addLogicalPage()
511
            );
512
513
            // Get additional fields for extended search.
514
            $extendedSearch = $this->addExtendedSearch();
515
516
            // Display search form.
517
            $content .= $this->cObj->substituteSubpart($this->cObj->substituteMarkerArray($this->template, $markerArray), '###EXT_SEARCH_ENTRY###', $extendedSearch);
518
519
            return $this->pi_wrapInBaseClass($content);
520
521
        } else {
522
523
            // Instantiate search object.
524
            $solr = tx_dlf_solr::getInstance($this->conf['solrcore']);
525
526
            if (!$solr->ready) {
527
528
                if (TYPO3_DLOG) {
529
530
                    \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_search->main('.$content.', [data])] Apache Solr not available', $this->extKey, SYSLOG_SEVERITY_ERROR, $conf);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
531
532
                }
533
534
                return $content;
535
536
            }
537
538
            // Build label for result list.
539
            $label = $this->pi_getLL('search', '', TRUE);
540
541
            if (!empty($this->piVars['query'])) {
542
543
                $label .= htmlspecialchars(sprintf($this->pi_getLL('for', ''), $this->piVars['query']));
544
545
            }
546
547
            // Prepare query parameters.
548
            $params = array ();
549
550
            $matches = array ();
551
552
            // Set search query.
553
            if ((!empty($this->conf['fulltext']) && !empty($this->piVars['fulltext'])) || preg_match('/fulltext:\((.*)\)/', $this->piVars['query'], $matches)) {
554
555
                // If the query already is a fulltext query e.g using the facets
556
                $this->piVars['query'] = empty($matches[1]) ? $this->piVars['query'] : $matches[1];
0 ignored issues
show
Bug Best Practice introduced by
The property piVars does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
557
558
                // Search in fulltext field if applicable. query must not be empty!
559
                if (!empty($this->piVars['query'])) {
560
561
                    $query = 'fulltext:('.tx_dlf_solr::escapeQuery($this->piVars['query']).')';
562
563
                }
564
565
                // Add highlighting for fulltext.
566
                $params['hl'] = 'true';
567
568
                $params['hl.fl'] = 'fulltext';
569
570
            } else {
571
                // Retain given search field if valid.
572
                $query = tx_dlf_solr::escapeQueryKeepField($this->piVars['query'], $this->conf['pages']);
573
574
            }
575
576
            // Add extended search query.
577
            if (!empty($this->piVars['extQuery']) && is_array($this->piVars['extQuery'])) {
578
579
                $allowedOperators = array ('AND', 'OR', 'NOT');
580
581
                $allowedFields = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->conf['extendedFields'], TRUE);
582
583
                for ($i = 0; $i < count($this->piVars['extQuery']); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
584
585
                    if (!empty($this->piVars['extQuery'][$i])) {
586
587
                        if (in_array($this->piVars['extOperator'][$i], $allowedOperators) && in_array($this->piVars['extField'][$i], $allowedFields)) {
588
589
                            if (!empty($query)) {
590
591
                                $query .= ' '.$this->piVars['extOperator'][$i].' ';
592
593
                            }
594
595
                            $query .= tx_dlf_indexing::getIndexFieldName($this->piVars['extField'][$i], $this->conf['pages']).':('.tx_dlf_solr::escapeQuery($this->piVars['extQuery'][$i]).')';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $query does not seem to be defined for all execution paths leading up to this point.
Loading history...
596
597
                        }
598
599
                    }
600
601
                }
602
603
            }
604
605
            // Add filter query for faceting.
606
            if (!empty($this->piVars['fq'])) {
607
608
                $params['fq'] = $this->piVars['fq'];
609
610
            }
611
612
            // Add filter query for in-document searching.
613
            if ($this->conf['searchIn'] == 'document' || $this->conf['searchIn'] == 'all') {
614
615
                if (!empty($this->piVars['id']) && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($this->piVars['id'])) {
616
617
                    $params['fq'][] = 'uid:('.$this->piVars['id'].') OR partof:('.$this->piVars['id'].')';
618
619
                    $label .= htmlspecialchars(sprintf($this->pi_getLL('in', ''), tx_dlf_document::getTitle($this->piVars['id'])));
620
621
                }
622
623
            }
624
625
            // Add filter query for in-collection searching.
626
            if ($this->conf['searchIn'] == 'collection' || $this->conf['searchIn'] == 'all') {
627
628
                if (!empty($this->piVars['collection']) && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($this->piVars['collection'])) {
629
630
                    $index_name = tx_dlf_helper::getIndexName($this->piVars['collection'], 'tx_dlf_collections', $this->conf['pages']);
631
632
                    $params['fq'][] = 'collection_faceting:("'.tx_dlf_solr::escapeQuery($index_name).'")';
633
634
                    $label .= sprintf($this->pi_getLL('in', '', TRUE), tx_dlf_helper::translate($index_name, 'tx_dlf_collections', $this->conf['pages']));
635
636
                }
637
638
            }
639
640
            // Add filter query for collection restrictions.
641
            if ($this->conf['collections']) {
642
643
                $collIds = explode(',', $this->conf['collections']);
644
645
                $collIndexNames = array ();
646
647
                foreach ($collIds as $collId) {
648
649
                    $collIndexNames[] = tx_dlf_solr::escapeQuery(tx_dlf_helper::getIndexName(intval($collId), 'tx_dlf_collections', $this->conf['pages']));
650
651
                }
652
653
                // Last value is fake and used for distinction in $this->addCurrentCollection()
654
                $params['fq'][] = 'collection_faceting:("'.implode('" OR "', $collIndexNames).'" OR "FakeValueForDistinction")';
655
656
            }
657
658
            // Set search parameters.
659
            $solr->limit = max(intval($this->conf['limit']), 1);
660
661
            $solr->cPid = $this->conf['pages'];
662
663
            $solr->params = $params;
664
665
            // Perform search.
666
            $results = $solr->search($query);
667
668
            $results->metadata = array (
669
                'label' => $label,
670
                'description' => '<p class="tx-dlf-search-numHits">'.htmlspecialchars(sprintf($this->pi_getLL('hits', ''), $solr->numberOfHits, count($results))).'</p>',
671
                'thumbnail' => '',
672
                'searchString' => $this->piVars['query'],
673
                'fulltextSearch' => (!empty($this->piVars['fulltext']) ? '1' : '0'),
674
                'options' => $results->metadata['options']
675
            );
676
677
            $results->save();
678
679
            // Clean output buffer.
680
            \TYPO3\CMS\Core\Utility\GeneralUtility::cleanOutputBuffers();
681
682
            $additionalParams = array ();
683
684
            if (!empty($this->piVars['logicalPage'])) {
685
686
                $additionalParams['logicalPage'] = $this->piVars['logicalPage'];
687
688
            }
689
690
            // Jump directly to the page view, if there is only one result and it is configured
691
            if ($results->count() == 1 && !empty($this->conf['showSingleResult'])) {
692
693
                $linkConf['parameter'] = $this->conf['targetPidPageView'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$linkConf was never initialized. Although not strictly required by PHP, it is generally a good practice to add $linkConf = array(); before regardless.
Loading history...
694
695
                $additionalParams['id'] = $results->current()['uid'];
696
                $additionalParams['highlight_word'] = preg_replace('/\s\s+/', ';', $results->metadata['searchString']);
697
                $additionalParams['page'] = count($results[0]['subparts']) == 1 ? $results[0]['subparts'][0]['page'] : 1;
698
699
            } else {
700
701
                // Keep some plugin variables.
702
                $linkConf['parameter'] = $this->conf['targetPid'];
703
704
                if (!empty($this->piVars['order'])) {
705
706
                    $additionalParams['order'] = $this->piVars['order'];
707
                    $additionalParams['asc'] = !empty($this->piVars['asc']) ? '1' : '0';
708
709
                }
710
711
            }
712
713
            $linkConf['additionalParams'] = \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl($this->prefixId, $additionalParams, '', TRUE, FALSE);
714
715
            // Send headers.
716
            header('Location: '.\TYPO3\CMS\Core\Utility\GeneralUtility::locationHeaderUrl($this->cObj->typoLink_URL($linkConf)));
717
718
            // Flush output buffer and end script processing.
719
            ob_end_flush();
720
721
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
722
723
        }
724
725
    }
726
727
    /**
728
     * This builds a menu array for HMENU
729
     *
730
     * @access	public
731
     *
732
     * @param	string		$content: The PlugIn content
733
     * @param	array		$conf: The PlugIn configuration
734
     *
735
     * @return	array		HMENU array
736
     */
737
    public function makeFacetsMenuArray($content, $conf) {
738
739
        $this->init($conf);
740
741
        $menuArray = array ();
742
743
        // Set default value for facet search.
744
        $search = array (
745
            'query' => '*',
746
            'params' => array ()
747
        );
748
749
        // Extract query and filter from last search.
750
        $list = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tx_dlf_list');
751
752
        if (!empty($list->metadata['options']['source'])) {
753
754
            if ($list->metadata['options']['source'] == 'search') {
755
756
                $search['query'] = $list->metadata['options']['select'];
757
758
            }
759
760
            $search['params'] = $list->metadata['options']['params'];
761
762
        }
763
764
        // Get applicable facets.
765
        $solr = tx_dlf_solr::getInstance($this->conf['solrcore']);
766
767
        if (!$solr->ready) {
768
769
            if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
770
771
                \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_search->makeFacetsMenuArray('.$content.', [data])] Apache Solr not available', $this->extKey, SYSLOG_SEVERITY_ERROR, $conf);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
772
773
            }
774
775
            return array ();
776
777
        }
778
779
        // Set needed parameters for facet search.
780
        if (empty($search['params']['fq'])) {
781
782
            $search['params']['fq'] = array ();
783
784
        }
785
786
        $search['params']['facet'] = 'true';
787
788
        $search['params']['facet.field'] = array_keys($this->conf['facets']);
789
790
        //override SOLR default value for facet.limit of 100
791
        $search['params']['facet.limit'] = $this->conf['limitFacets'];
792
793
        // Perform search.
794
        $results = $solr->service->search($search['query'], 0, $this->conf['limit'], $search['params']);
795
796
        // Process results.
797
        foreach ($results->facet_counts->facet_fields as $field => $values) {
798
799
            $entryArray = array ();
800
801
            $entryArray['title'] = htmlspecialchars($this->conf['facets'][$field]);
802
803
            $entryArray['count'] = 0;
804
805
            $entryArray['_OVERRIDE_HREF'] = '';
806
807
            $entryArray['doNotLinkIt'] = 1;
808
809
            $entryArray['ITEM_STATE'] = 'NO';
810
811
            // Count number of facet values.
812
            $i = 0;
813
814
            foreach ($values as $value => $count) {
815
816
                if ($count > 0) {
817
818
                    $hasValue = TRUE;
0 ignored issues
show
Unused Code introduced by
The assignment to $hasValue is dead and can be removed.
Loading history...
819
820
                    $entryArray['count']++;
821
822
                    if ($entryArray['ITEM_STATE'] == 'NO') {
823
824
                        $entryArray['ITEM_STATE'] = 'IFSUB';
825
826
                    }
827
828
                    $entryArray['_SUB_MENU'][] = $this->getFacetsMenuEntry($field, $value, $count, $search, $entryArray['ITEM_STATE']);
829
830
                    if (++$i == $this->conf['limit']) {
831
832
                        break;
833
834
                    }
835
836
                } else {
837
838
                    break;
839
840
                }
841
842
            }
843
844
            $menuArray[] = $entryArray;
845
846
        }
847
848
        return $menuArray;
849
850
851
    }
852
853
}
854