Passed
Pull Request — master (#123)
by
unknown
03:55
created

SearchController   F

Complexity

Total Complexity 85

Size/Duplication

Total Lines 537
Duplicated Lines 0 %

Importance

Changes 8
Bugs 2 Features 1
Metric Value
eloc 227
c 8
b 2
f 1
dl 0
loc 537
rs 2
wmc 85

11 Methods

Rating   Name   Duplication   Size   Complexity  
F mainAction() 0 105 21
A getFacetsMenuEntry() 0 28 3
A injectMetadataRepository() 0 3 1
A injectCollectionRepository() 0 3 1
F makeFacetsMenuArray() 0 126 24
A translateValue() 0 17 5
B addCollectionsQuery() 0 40 11
A addExtendedSearch() 0 22 4
B processResults() 0 37 10
A searchAction() 0 7 1
A addFacetsMenu() 0 14 4

How to fix   Complexity   

Complex Class

Complex classes like SearchController 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 SearchController, 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\Controller;
14
15
use Kitodo\Dlf\Common\Helper;
16
use Kitodo\Dlf\Common\Indexer;
17
use Kitodo\Dlf\Common\SolrPaginator;
18
use Kitodo\Dlf\Common\Solr\Solr;
19
use Kitodo\Dlf\Domain\Model\Collection;
20
use Kitodo\Dlf\Domain\Repository\CollectionRepository;
21
use Kitodo\Dlf\Domain\Repository\MetadataRepository;
22
use Solarium\Component\Result\FacetSet;
23
use TYPO3\CMS\Core\Core\Environment;
24
use TYPO3\CMS\Core\Information\Typo3Version;
25
use TYPO3\CMS\Core\Pagination\SimplePagination;
26
use TYPO3\CMS\Core\Utility\GeneralUtility;
27
28
/**
29
 * Controller class for the plugin 'Search'.
30
 *
31
 * @package TYPO3
32
 * @subpackage dlf
33
 *
34
 * @access public
35
 */
36
class SearchController extends AbstractController
37
{
38
    /**
39
     * @access protected
40
     * @var CollectionRepository
41
     */
42
    protected CollectionRepository $collectionRepository;
43
44
    /**
45
     * @access public
46
     *
47
     * @param CollectionRepository $collectionRepository
48
     *
49
     * @return void
50
     */
51
    public function injectCollectionRepository(CollectionRepository $collectionRepository): void
52
    {
53
        $this->collectionRepository = $collectionRepository;
54
    }
55
56
    /**
57
     * @access protected
58
     * @var MetadataRepository
59
     */
60
    protected MetadataRepository $metadataRepository;
61
62
    /**
63
     * @access public
64
     *
65
     * @param MetadataRepository $metadataRepository
66
     *
67
     * @return void
68
     */
69
    public function injectMetadataRepository(MetadataRepository $metadataRepository): void
70
    {
71
        $this->metadataRepository = $metadataRepository;
72
    }
73
74
    /**
75
     * @access protected
76
     * @var array The current search parameter
77
     */
78
    protected ?array $searchParams;
79
80
    /**
81
     * Search Action
82
     *
83
     * @access public
84
     *
85
     * @return void
86
     */
87
    public function searchAction(): void
88
    {
89
        // if search was triggered, get search parameters from POST variables
90
        $this->searchParams = $this->getParametersSafely('searchParameter');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getParametersSafely('searchParameter') can also be of type string. However, the property $searchParams is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
91
92
        // output is done by main action
93
        $this->forward('main', null, null, ['searchParameter' => $this->searchParams]);
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Mvc\Co...onController::forward() has been deprecated: since TYPO3 11.0, will be removed in 12.0 ( Ignorable by Annotation )

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

93
        /** @scrutinizer ignore-deprecated */ $this->forward('main', null, null, ['searchParameter' => $this->searchParams]);

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

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

Loading history...
94
    }
95
96
    /**
97
     * Main action
98
     *
99
     * This shows the search form and optional the facets and extended search form.
100
     *
101
     * @access public
102
     *
103
     * @return void
104
     */
105
    public function mainAction(): void
106
    {
107
        $listViewSearch = false;
108
        // Quit without doing anything if required variables are not set.
109
        if (empty($this->settings['solrcore'])) {
110
            $this->logger->warning('Incomplete plugin configuration');
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

110
            $this->logger->/** @scrutinizer ignore-call */ 
111
                           warning('Incomplete plugin configuration');

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...
111
            return;
112
        }
113
114
        // if search was triggered, get search parameters from POST variables
115
        $this->searchParams = $this->getParametersSafely('searchParameter');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getParametersSafely('searchParameter') can also be of type string. However, the property $searchParams is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
116
        // if search was triggered by the ListView plugin, get the parameters from GET variables
117
        $listRequestData = GeneralUtility::_GPmerged('tx_dlf_listview');
118
119
        if (isset($listRequestData['searchParameter']) && is_array($listRequestData['searchParameter'])) {
120
            $this->searchParams = array_merge($this->searchParams ?: [], $listRequestData['searchParameter']);
121
            $listViewSearch = true;
122
            $GLOBALS['TSFE']->fe_user->setKey('ses', 'search', $this->searchParams);
123
        }
124
125
        // sanitize date search input
126
        if (empty($this->searchParams['dateFrom']) && !empty($this->searchParams['dateTo'])) {
127
            $this->searchParams['dateFrom'] = '*';
128
        }
129
        if (empty($this->searchParams['dateTo']) && !empty($this->searchParams['dateFrom'])) {
130
            $this->searchParams['dateTo'] = 'NOW';
131
        }
132
        if ($this->searchParams['dateFrom'] > $this->searchParams['dateTo']) {
133
            $tmpDate = $this->searchParams['dateFrom'];
134
            $this->searchParams['dateFrom'] = $this->searchParams['dateTo'];
135
            $this->searchParams['dateTo'] = $tmpDate;
136
        }
137
138
        // Pagination of Results: Pass the currentPage to the fluid template to calculate current index of search result.
139
        $currentPage = $this->getParametersSafely('page');
140
        if (empty($currentPage)) {
141
            $currentPage = 1;
142
        }
143
144
        // If a targetPid is given, the results will be shown by ListView on the target page.
145
        if (!empty($this->settings['targetPid']) && !empty($this->searchParams) && !$listViewSearch) {
146
            $this->redirect(
147
                'main',
148
                'ListView',
149
                null,
150
                [
151
                    'searchParameter' => $this->searchParams,
152
                    'page' => $currentPage
153
                ], $this->settings['targetPid']
154
            );
155
        }
156
157
        // If no search has been executed, no variables have to be prepared.
158
        // An empty form will be shown.
159
        if (is_array($this->searchParams) && !empty($this->searchParams)) {
160
            // get all sortable metadata records
161
            $sortableMetadata = $this->metadataRepository->findByIsSortable(true);
0 ignored issues
show
Bug introduced by
The method findByIsSortable() does not exist on Kitodo\Dlf\Domain\Repository\MetadataRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

161
            /** @scrutinizer ignore-call */ 
162
            $sortableMetadata = $this->metadataRepository->findByIsSortable(true);
Loading history...
162
163
            // get all metadata records to be shown in results
164
            $listedMetadata = $this->metadataRepository->findByIsListed(true);
0 ignored issues
show
Bug introduced by
The method findByIsListed() does not exist on Kitodo\Dlf\Domain\Repository\MetadataRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

164
            /** @scrutinizer ignore-call */ 
165
            $listedMetadata = $this->metadataRepository->findByIsListed(true);
Loading history...
165
166
            $solrResults = null;
167
            $numResults = 0;
168
            // Do not execute the Solr search if used together with ListView plugin.
169
            if (!$listViewSearch) {
170
                $solrResults = $this->documentRepository->findSolrWithoutCollection($this->settings, $this->searchParams, $listedMetadata);
171
                $numResults = $solrResults->getNumFound();
172
173
                $itemsPerPage = $this->settings['list']['paginate']['itemsPerPage'];
174
                if (empty($itemsPerPage)) {
175
                    $itemsPerPage = 25;
176
                }
177
                $solrPaginator = new SolrPaginator($solrResults, $currentPage, $itemsPerPage);
178
                $simplePagination = new SimplePagination($solrPaginator);
179
180
                $pagination = $this->buildSimplePagination($simplePagination, $solrPaginator);
181
                $this->view->assignMultiple([ 'pagination' => $pagination, 'paginator' => $solrPaginator ]);
182
            }
183
184
            $this->view->assign('documents', !empty($solrResults) ? $solrResults : []);
185
            $this->view->assign('numResults', $numResults);
186
            $this->view->assign('page', $currentPage);
187
            $this->view->assign('lastSearch', $this->searchParams);
188
            $this->view->assign('listedMetadata', $listedMetadata);
189
            $this->view->assign('sortableMetadata', $sortableMetadata);
190
191
            // Add the facets menu
192
            $this->addFacetsMenu();
193
        }
194
195
        // Get additional fields for extended search.
196
        $this->addExtendedSearch();
197
198
        // Add the current document if present to fluid. This way, we can limit further searches to this document.
199
        if (isset($this->requestData['id'])) {
200
            $currentDocument = $this->documentRepository->findByUid($this->requestData['id']);
201
            $this->view->assign('currentDocument', $currentDocument);
202
        }
203
204
        // Add uHash parameter to suggest parameter to make a basic protection of this form.
205
        if ($this->settings['suggest']) {
206
            $this->view->assign('uHash', GeneralUtility::hmac((string) (new Typo3Version()) . Environment::getExtensionsPath(), 'SearchSuggest'));
207
        }
208
209
        $this->view->assign('viewData', $this->viewData);
210
    }
211
212
    /**
213
     * Adds the facets menu to the search form
214
     *
215
     * @access protected
216
     */
217
    protected function addFacetsMenu(): void
218
    {
219
        // Quit without doing anything if no facets are configured.
220
        if (empty($this->settings['facets']) && empty($this->settings['facetCollections'])) {
221
            return;
222
        }
223
224
        // Get facets from plugin configuration.
225
        $facets = [];
226
        foreach (GeneralUtility::trimExplode(',', $this->settings['facets'], true) as $facet) {
227
            $facets[$facet . '_faceting'] = Helper::translate($facet, 'tx_dlf_metadata', $this->settings['storagePid']);
228
        }
229
230
        $this->view->assign('facetsMenu', $this->makeFacetsMenuArray($facets));
231
    }
232
233
    /**
234
     * This builds a menu array for HMENU
235
     *
236
     * @access public
237
     *
238
     * @param array $facets
239
     *
240
     * @return array HMENU array
241
     */
242
    public function makeFacetsMenuArray(array $facets): array
243
    {
244
        // Set default value for facet search.
245
        $search = [
246
            'query' => '*:*',
247
            'params' => [
248
                'component' => [
249
                    'facetset' => [
250
                        'facet' => []
251
                    ]
252
                ],
253
                'filterquery' => []
254
            ]
255
        ];
256
257
        $fields = Solr::getFields();
258
259
        // Set search query.
260
        $searchParams = $this->searchParams;
261
        if (
262
            (!empty($searchParams['fulltext']))
263
            || preg_match('/' . $fields['fulltext'] . ':\((.*)\)/', trim($searchParams['query']), $matches)
264
        ) {
265
            // If the query already is a fulltext query e.g using the facets
266
            $searchParams['query'] = empty($matches[1]) ? $searchParams['query'] : $matches[1];
267
            // Search in fulltext field if applicable. Query must not be empty!
268
            if (!empty($searchParams['query'])) {
269
                $search['query'] = $fields['fulltext'] . ':(' . Solr::escapeQuery(trim($searchParams['query'])) . ')';
270
            }
271
        } else {
272
            // Retain given search field if valid.
273
            if (!empty($searchParams['query'])) {
274
                $search['query'] = Solr::escapeQueryKeepField(trim($searchParams['query']), $this->settings['storagePid']);
275
            }
276
        }
277
278
        $collectionsQuery = $this->addCollectionsQuery($search['query']);
279
        if (!empty($collectionsQuery)) {
280
            $search['params']['filterquery'][]['query'] = $collectionsQuery;
281
        }
282
283
        // add filter query for date search
284
        if (!empty($this->searchParams['dateFrom']) && !empty($this->searchParams['dateTo'])) {
285
            // combine dateFrom and dateTo into filterquery as range search
286
            $search['params']['filterquery'][]['query'] = '{!join from=' . $fields['uid'] . ' to=' . $fields['uid'] . '}' . $fields['date'] . ':[' . $this->searchParams['dateFrom'] . ' TO ' . $this->searchParams['dateTo'] . ']';
287
        }
288
289
        // Add extended search query.
290
        if (
291
            !empty($searchParams['extQuery'])
292
            && is_array($searchParams['extQuery'])
293
        ) {
294
            // If the search query is already set by the simple search field, we have to reset it.
295
            $search['query'] = '';
296
            $allowedOperators = ['AND', 'OR', 'NOT'];
297
            $numberOfExtQueries = count($searchParams['extQuery']);
298
            for ($i = 0; $i < $numberOfExtQueries; $i++) {
299
                if (!empty($searchParams['extQuery'][$i])) {
300
                    if (
301
                        in_array($searchParams['extOperator'][$i], $allowedOperators)
302
                    ) {
303
                        if (!empty($search['query'])) {
304
                            $search['query'] .= ' ' . $searchParams['extOperator'][$i] . ' ';
305
                        }
306
                        $search['query'] .= Indexer::getIndexFieldName($searchParams['extField'][$i], $this->settings['storagePid']) . ':(' . Solr::escapeQuery($searchParams['extQuery'][$i]) . ')';
307
                    }
308
                }
309
            }
310
        }
311
312
        if (isset($this->searchParams['fq']) && is_array($this->searchParams['fq'])) {
313
            foreach ($this->searchParams['fq'] as $fq) {
314
                $search['params']['filterquery'][]['query'] = $fq;
315
            }
316
        }
317
318
        // Get applicable facets.
319
        $solr = Solr::getInstance($this->settings['solrcore']);
320
        if (!$solr->ready) {
321
            $this->logger->error('Apache Solr not available');
322
            return [];
323
        }
324
325
        foreach (array_keys($facets) as $field) {
326
            $search['params']['component']['facetset']['facet'][] = [
327
                'type' => 'field',
328
                'mincount' => '1',
329
                'key' => $field,
330
                'field' => $field,
331
                'limit' => $this->settings['limitFacets'],
332
                'sort' => isset($this->settings['sortingFacets']) ? $this->settings['sortingFacets'] : 'count'
333
            ];
334
        }
335
336
        // Set additional query parameters.
337
        $search['params']['start'] = 0;
338
        $search['params']['rows'] = 0;
339
        // Set query.
340
        $search['params']['query'] = $search['query'];
341
        // Perform search.
342
        $selectQuery = $solr->service->createSelect($search['params']);
343
        // check for solr response
344
        $solrRequest = $solr->service->createRequest($selectQuery);
345
        $response = $solr->service->executeRequest($solrRequest);
346
        // return empty facet on solr error
347
        if ($response->getStatusCode() == 400) {
348
            return [];
349
        }
350
        $results = $solr->service->select($selectQuery);
351
        $facet = $results->getFacetSet();
352
353
        $facetCollectionArray = [];
354
355
        // replace everything expect numbers and comma
356
        $facetCollections = preg_replace('/[^\d,]/', '', $this->settings['facetCollections']);
357
358
        if (!empty($facetCollections)) {
359
            $collections = $this->collectionRepository->findCollectionsBySettings(['collections' => $facetCollections]);
360
361
            /** @var Collection $collection */
362
            foreach ($collections as $collection) {
363
                $facetCollectionArray[] = $collection->getIndexName();
364
            }
365
        }
366
367
        return $this->processResults($facet, $facetCollectionArray, $search);
368
    }
369
370
    /**
371
     * Add the collection query string, if the collections are given.
372
     *
373
     * @access private
374
     *
375
     * @param string $query The current query
376
     *
377
     * @return string The collection query string
378
     */
379
    private function addCollectionsQuery(string $query): string
380
    {
381
        // if collections are given, we prepare the collections query string
382
        // extract collections from collection parameter
383
        $collections = null;
384
        if ($this->searchParams['collection']) {
385
            foreach (explode(',', $this->searchParams['collection']) as $collectionEntry) {
386
                $collections[] = $this->collectionRepository->findByUid((int) $collectionEntry);
387
            }
388
        }
389
        if ($collections) {
0 ignored issues
show
introduced by
$collections is of type null, thus it always evaluated to false.
Loading history...
390
            $collectionsQueryString = '';
391
            $virtualCollectionsQueryString = '';
392
            foreach ($collections as $collectionEntry) {
393
                // check for virtual collections query string
394
                if ($collectionEntry->getIndexSearch()) {
395
                    $virtualCollectionsQueryString .= empty($virtualCollectionsQueryString) ? '(' . $collectionEntry->getIndexSearch() . ')' : ' OR (' . $collectionEntry->getIndexSearch() . ')';
396
                } else {
397
                    $collectionsQueryString .= empty($collectionsQueryString) ? '"' . $collectionEntry->getIndexName() . '"' : ' OR "' . $collectionEntry->getIndexName() . '"';
398
                }
399
            }
400
401
            // distinguish between simple collection browsing and actual searching within the collection(s)
402
            if (!empty($collectionsQueryString)) {
403
                if (empty($query)) {
404
                    $collectionsQueryString = '(collection_faceting:(' . $collectionsQueryString . ') AND toplevel:true AND partof:0)';
405
                } else {
406
                    $collectionsQueryString = '(collection_faceting:(' . $collectionsQueryString . '))';
407
                }
408
            }
409
410
            // virtual collections might query documents that are neither toplevel:true nor partof:0 and need to be searched separately
411
            if (!empty($virtualCollectionsQueryString)) {
412
                $virtualCollectionsQueryString = '(' . $virtualCollectionsQueryString . ')';
413
            }
414
415
            // combine both querystrings into a single filterquery via OR if both are given, otherwise pass either of those
416
            return implode(" OR ", array_filter([$collectionsQueryString, $virtualCollectionsQueryString]));
417
        }
418
        return "";
419
    }
420
421
    /**
422
     * Creates an array for a HMENU entry of a facet value.
423
     *
424
     * @access private
425
     *
426
     * @param string $field The facet's index_name
427
     * @param string $value The facet's value
428
     * @param int $count Number of hits for this facet
429
     * @param array $search The parameters of the current search query
430
     * @param string &$state The state of the parent item
431
     *
432
     * @return array The array for the facet's menu entry
433
     */
434
    private function getFacetsMenuEntry(string $field, string $value, int $count, array $search, string &$state): array
435
    {
436
        $entryArray = [];
437
        $entryArray['title'] = $this->translateValue($field, $value);
438
        $entryArray['count'] = $count;
439
        $entryArray['doNotLinkIt'] = 0;
440
        // Check if facet is already selected.
441
        $queryColumn = array_column($search['params']['filterquery'], 'query');
442
        $index = array_search($field . ':("' . Solr::escapeQuery($value) . '")', $queryColumn);
443
        if ($index !== false) {
444
            // Facet is selected, thus remove it from filter.
445
            unset($queryColumn[$index]);
446
            $queryColumn = array_values($queryColumn);
447
            $entryArray['ITEM_STATE'] = 'CUR';
448
            $state = 'ACTIFSUB';
449
            // Reset facets
450
            if ($this->settings['resetFacets']) {
451
                $entryArray['resetFacet'] = true;
452
                $entryArray['queryColumn'] = $queryColumn;
453
            }
454
        } else {
455
            // Facet is not selected, thus add it to filter.
456
            $queryColumn[] = $field . ':("' . Solr::escapeQuery($value) . '")';
457
            $entryArray['ITEM_STATE'] = 'NO';
458
        }
459
        $entryArray['queryColumn'] = $queryColumn;
460
461
        return $entryArray;
462
    }
463
464
    /**
465
     * Process results.
466
     *
467
     * @access private
468
     *
469
     * @param FacetSet|null $facet
470
     * @param array $facetCollectionArray
471
     * @param array $search
472
     *
473
     * @return array menu array
474
     */
475
    private function processResults($facet, array $facetCollectionArray, array $search): array
476
    {
477
        $menuArray = [];
478
479
        if ($facet) {
480
            foreach ($facet as $field => $values) {
481
                $entryArray = [];
482
                $entryArray['field'] = substr($field, 0, strpos($field, '_faceting'));
483
                $entryArray['count'] = 0;
484
                $entryArray['_OVERRIDE_HREF'] = '';
485
                $entryArray['ITEM_STATE'] = 'NO';
486
                // Count number of facet values.
487
                $i = 0;
488
                foreach ($values as $value => $count) {
489
                    if ($count > 0) {
490
                        // check if facet collection configuration exists
491
                        if (!empty($this->settings['facetCollections'])) {
492
                            if ($field == "collection_faceting" && !in_array($value, $facetCollectionArray)) {
493
                                continue;
494
                            }
495
                        }
496
                        $entryArray['count']++;
497
                        if ($entryArray['ITEM_STATE'] == 'NO') {
498
                            $entryArray['ITEM_STATE'] = 'IFSUB';
499
                        }
500
                        $entryArray['_SUB_MENU'][] = $this->getFacetsMenuEntry($field, $value, $count, $search, $entryArray['ITEM_STATE']);
501
                        if (++$i == $this->settings['limit']) {
502
                            break;
503
                        }
504
                    } else {
505
                        break;
506
                    }
507
                }
508
                $menuArray[] = $entryArray;
509
            }
510
        }
511
        return $menuArray;
512
    }
513
514
    /**
515
     * Translates value depending on the index name.
516
     *
517
     * @access private
518
     *
519
     * @param string $field The facet's index_name
520
     * @param string $value The facet's value
521
     *
522
     * @return string
523
     */
524
    private function translateValue(string $field, string $value): string
525
    {
526
        switch ($field) {
527
            case 'owner_faceting':
528
                // Translate name of holding library.
529
                return htmlspecialchars(Helper::translate($value, 'tx_dlf_libraries', $this->settings['storagePid']));
530
            case 'type_faceting':
531
                // Translate document type.
532
                return htmlspecialchars(Helper::translate($value, 'tx_dlf_structures', $this->settings['storagePid']));
533
            case 'collection_faceting':
534
                // Translate name of collection.
535
                return htmlspecialchars(Helper::translate($value, 'tx_dlf_collections', $this->settings['storagePid']));
536
            case 'language_faceting':
537
                // Translate ISO 639 language code.
538
                return htmlspecialchars(Helper::getLanguageName($value));
539
            default:
540
                return htmlspecialchars($value);
541
        }
542
    }
543
544
    /**
545
     * Returns the extended search form and adds the JS files necessary for extended search.
546
     *
547
     * @access private
548
     *
549
     * @return void
550
     */
551
    private function addExtendedSearch(): void
552
    {
553
        // Quit without doing anything if no fields for extended search are selected.
554
        if (
555
            empty($this->settings['extendedSlotCount'])
556
            || empty($this->settings['extendedFields'])
557
        ) {
558
            return;
559
        }
560
561
        // Get field selector options.
562
        $searchFields = GeneralUtility::trimExplode(',', $this->settings['extendedFields'], true);
563
564
        $slotCountArray = [];
565
        for ($i = 0; $i < $this->settings['extendedSlotCount']; $i++) {
566
            $slotCountArray[] = $i;
567
        }
568
569
        $this->view->assign('extendedSlotCount', $slotCountArray);
570
        $this->view->assign('extendedFields', $this->settings['extendedFields']);
571
        $this->view->assign('operators', ['AND', 'OR', 'NOT']);
572
        $this->view->assign('searchFields', $searchFields);
573
    }
574
}
575