‪TYPO3CMS  10.4
SearchController.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
42 
51 {
57  protected ‪$sword = '';
58 
62  protected ‪$searchWords = [];
63 
67  protected ‪$searchData;
68 
78  protected ‪$searchRootPageIdList = 0;
79 
83  protected ‪$defaultResultNumber = 10;
84 
89 
95  protected ‪$searchRepository;
96 
102  protected ‪$lexerObj;
103 
108  protected ‪$externalParsers = [];
109 
115  protected ‪$firstRow = [];
116 
122  protected ‪$domainRecords = [];
123 
130 
136  protected ‪$resultSections = [];
137 
143  protected ‪$pathCache = [];
144 
150  protected ‪$iconFileNameCache = [];
151 
157  protected ‪$indexerConfig = [];
158 
164  protected ‪$enableMetaphoneSearch = false;
165 
169  protected ‪$typoScriptService;
170 
175  {
176  $this->typoScriptService = ‪$typoScriptService;
177  }
178 
185  public function ‪initialize(‪$searchData = [])
186  {
187  if (!is_array(‪$searchData)) {
188  ‪$searchData = [];
189  }
190 
191  // check if TypoScript is loaded
192  if (!isset($this->settings['results'])) {
193  $this->‪redirect('noTypoScript');
194  }
195 
196  // Sets availableResultsNumbers - has to be called before request settings are read to avoid DoS attack
197  $this->availableResultsNumbers = array_filter(‪GeneralUtility::intExplode(',', $this->settings['blind']['numberOfResults']));
198 
199  // Sets default result number if at least one availableResultsNumbers exists
200  if (isset($this->availableResultsNumbers[0])) {
201  $this->defaultResultNumber = $this->availableResultsNumbers[0];
202  }
203 
204  $this->‪loadSettings();
205 
206  // setting default values
207  if (is_array($this->settings['defaultOptions'])) {
208  ‪$searchData = array_merge($this->settings['defaultOptions'], ‪$searchData);
209  }
210  // if "languageUid" was set to "current", take the current site language
211  if ((‪$searchData['languageUid'] ?? '') === 'current') {
212  ‪$searchData['languageUid'] = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'id', 0);
213  }
214 
215  // Indexer configuration from Extension Manager interface:
216  $this->indexerConfig = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('indexed_search');
217  $this->enableMetaphoneSearch = (bool)$this->indexerConfig['enableMetaphoneSearch'];
219  // If "_sections" is set, this value overrides any existing value.
220  if (‪$searchData['_sections']) {
221  ‪$searchData['sections'] = ‪$searchData['_sections'];
222  }
223  // If "_sections" is set, this value overrides any existing value.
224  if (‪$searchData['_freeIndexUid'] !== '' && ‪$searchData['_freeIndexUid'] !== '_') {
225  ‪$searchData['freeIndexUid'] = ‪$searchData['_freeIndexUid'];
226  }
227  ‪$searchData['numberOfResults'] = $this->‪getNumberOfResults(‪$searchData['numberOfResults']);
228  // This gets the search-words into the $searchWordArray
229  $this->‪setSword(‪$searchData['sword']);
230  // Add previous search words to current
231  if (‪$searchData['sword_prev_include'] && ‪$searchData['sword_prev']) {
232  $this->‪setSword(trim(‪$searchData['sword_prev']) . ' ' . $this->‪getSword());
233  }
234  // This is the id of the site root.
235  // This value may be a commalist of integer (prepared for this)
236  $this->searchRootPageIdList = (int)‪$GLOBALS['TSFE']->config['rootLine'][0]['uid'];
237  // Setting the list of root PIDs for the search. Notice, these page IDs MUST
238  // have a TypoScript template with root flag on them! Basically this list is used
239  // to select on the "rl0" field and page ids are registered as "rl0" only if
240  // a TypoScript template record with root flag is there.
241  // This happens AFTER the use of $this->searchRootPageIdList above because
242  // the above will then fetch the menu for the CURRENT site - regardless
243  // of this kind of searching here. Thus a general search will lookup in
244  // the WHOLE database while a specific section search will take the current sections.
245  if ($this->settings['rootPidList']) {
246  $this->searchRootPageIdList = implode(',', ‪GeneralUtility::intExplode(',', $this->settings['rootPidList']));
247  }
248  $this->searchRepository = GeneralUtility::makeInstance(IndexSearchRepository::class);
249  $this->searchRepository->initialize($this->settings, ‪$searchData, $this->externalParsers, $this->searchRootPageIdList);
250  $this->searchData = ‪$searchData;
251  // $this->searchData is used in $this->getSearchWords
252  $this->searchWords = $this->‪getSearchWords(‪$searchData['defaultOperand']);
253  // Calling hook for modification of initialized content
254  if ($hookObj = $this->‪hookRequest('initialize_postProc')) {
255  $hookObj->initialize_postProc();
256  }
257  return ‪$searchData;
258  }
259 
266  public function ‪searchAction($search = [])
267  {
268  ‪$searchData = $this->‪initialize($search);
269  // Find free index uid:
270  $freeIndexUid = ‪$searchData['freeIndexUid'];
271  if ($freeIndexUid == -2) {
272  $freeIndexUid = $this->settings['defaultFreeIndexUidList'];
273  } elseif (!isset(‪$searchData['freeIndexUid'])) {
274  // index configuration is disabled
275  $freeIndexUid = -1;
276  }
277 
278  if (!empty(‪$searchData['extendedSearch'])) {
279  $this->view->assignMultiple($this->‪processExtendedSearchParameters());
280  }
281 
282  $indexCfgs = ‪GeneralUtility::intExplode(',', $freeIndexUid);
283  $resultsets = [];
284  foreach ($indexCfgs as $freeIndexUid) {
285  // Get result rows
287  if ($hookObj = $this->‪hookRequest('getResultRows')) {
288  $resultData = $hookObj->getResultRows($this->searchWords, $freeIndexUid);
289  } else {
290  $resultData = $this->searchRepository->doSearch($this->searchWords, $freeIndexUid);
291  }
292  // Display search results
294  if ($hookObj = $this->‪hookRequest('getDisplayResults')) {
295  $resultsets[$freeIndexUid] = $hookObj->getDisplayResults($this->searchWords, $resultData, $freeIndexUid);
296  } else {
297  $resultsets[$freeIndexUid] = $this->‪getDisplayResults($this->searchWords, $resultData, $freeIndexUid);
298  }
300  // Create header if we are searching more than one indexing configuration
301  if (count($indexCfgs) > 1) {
302  if ($freeIndexUid > 0) {
303  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
304  ->getQueryBuilderForTable('index_config');
305  $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
306  $indexCfgRec = $queryBuilder
307  ->select('title')
308  ->from('index_config')
309  ->where(
310  $queryBuilder->expr()->eq(
311  'uid',
312  $queryBuilder->createNamedParameter($freeIndexUid, \PDO::PARAM_INT)
313  )
314  )
315  ->execute()
316  ->fetch();
317  $categoryTitle = ‪LocalizationUtility::translate('indexingConfigurationHeader.' . $freeIndexUid, 'IndexedSearch');
318  $categoryTitle = $categoryTitle ?: $indexCfgRec['title'];
319  } else {
320  $categoryTitle = ‪LocalizationUtility::translate('indexingConfigurationHeader.' . $freeIndexUid, 'IndexedSearch');
321  }
322  $resultsets[$freeIndexUid]['categoryTitle'] = $categoryTitle;
323  }
324  // Write search statistics
325  $this->‪writeSearchStat(‪$searchData, $this->searchWords, $resultData['count'], [$tstamp1, $tstamp2, $tstamp3]);
326  }
327  $this->view->assign('resultsets', $resultsets);
328  $this->view->assign('searchParams', ‪$searchData);
329  $this->view->assign('searchWords', $this->searchWords);
330  }
331 
332  /****************************************
333  * functions to make the result rows and result sets
334  * ready for the output
335  ***************************************/
344  protected function ‪getDisplayResults(‪$searchWords, $resultData, $freeIndexUid = -1)
345  {
346  $result = [
347  'count' => $resultData['count'],
348  'searchWords' => ‪$searchWords
349  ];
350  // Perform display of result rows array
351  if ($resultData) {
352  // Set first selected row (for calculation of ranking later)
353  $this->firstRow = $resultData['firstRow'];
354  // Result display here
355  $result['rows'] = $this->‪compileResultRows($resultData['resultRows'], $freeIndexUid);
356  $result['affectedSections'] = ‪$this->resultSections;
357  // Browsing box
358  if ($resultData['count']) {
359  // could we get this in the view?
360  if ($this->searchData['group'] === 'sections' && $freeIndexUid <= 0) {
361  $resultSectionsCount = count($this->resultSections);
362  $result['sectionText'] = sprintf(‪LocalizationUtility::translate('result.' . ($resultSectionsCount > 1 ? 'inNsections' : 'inNsection'), 'IndexedSearch') ?? '', $resultSectionsCount);
363  }
364  }
365  }
366  // Print a message telling which words in which sections we searched for
367  if (strpos($this->searchData['sections'], 'rl') === 0) {
368  $result['searchedInSectionInfo'] = (‪LocalizationUtility::translate('result.inSection', 'IndexedSearch') ?? '') . ' "' . $this->‪getPathFromPageId((int)substr($this->searchData['sections'], 4)) . '"';
369  }
370 
371  if ($hookObj = $this->‪hookRequest('getDisplayResults_postProc')) {
372  $result = $hookObj->getDisplayResults_postProc($result);
373  }
374 
375  return $result;
376  }
377 
386  protected function ‪compileResultRows($resultRows, $freeIndexUid = -1)
387  {
388  $finalResultRows = [];
389  // Transfer result rows to new variable,
390  // performing some mapping of sub-results etc.
391  $newResultRows = [];
392  foreach ($resultRows as $row) {
393  $id = md5($row['phash_grouping']);
394  if (is_array($newResultRows[$id])) {
395  // swapping:
396  if (!$newResultRows[$id]['show_resume'] && $row['show_resume']) {
397  // Remove old
398  $subrows = $newResultRows[$id]['_sub'];
399  unset($newResultRows[$id]['_sub']);
400  $subrows[] = $newResultRows[$id];
401  // Insert new:
402  $newResultRows[$id] = $row;
403  $newResultRows[$id]['_sub'] = $subrows;
404  } else {
405  $newResultRows[$id]['_sub'][] = $row;
406  }
407  } else {
408  $newResultRows[$id] = $row;
409  }
410  }
411  $resultRows = $newResultRows;
412  $this->resultSections = [];
413  if ($freeIndexUid <= 0 && $this->searchData['group'] === 'sections') {
414  $rl2flag = strpos($this->searchData['sections'], 'rl') === 0;
415  $sections = [];
416  foreach ($resultRows as $row) {
417  $id = $row['rl0'] . '-' . $row['rl1'] . ($rl2flag ? '-' . $row['rl2'] : '');
418  $sections[$id][] = $row;
419  }
420  $this->resultSections = [];
421  foreach ($sections as $id => $resultRows) {
422  $rlParts = explode('-', $id);
423  if ($rlParts[2]) {
424  $theId = $rlParts[2];
425  $theRLid = 'rl2_' . $rlParts[2];
426  } elseif ($rlParts[1]) {
427  $theId = $rlParts[1];
428  $theRLid = 'rl1_' . $rlParts[1];
429  } else {
430  $theId = $rlParts[0];
431  $theRLid = '0';
432  }
433  $sectionName = $this->‪getPathFromPageId((int)$theId);
434  $sectionName = ltrim($sectionName, '/');
435  if (!trim($sectionName)) {
436  $sectionTitleLinked = ‪LocalizationUtility::translate('result.unnamedSection', 'IndexedSearch') . ':';
437  } else {
438  $onclick = 'document.forms[\'tx_indexedsearch\'][\'tx_indexedsearch_pi2[search][_sections]\'].value=' . GeneralUtility::quoteJSvalue($theRLid) . ';document.forms[\'tx_indexedsearch\'].submit();return false;';
439  $sectionTitleLinked = '<a href="#" onclick="' . htmlspecialchars($onclick) . '">' . $sectionName . ':</a>';
440  }
441  $resultRowsCount = count($resultRows);
442  $this->resultSections[$id] = [$sectionName, $resultRowsCount];
443  // Add section header
444  $finalResultRows[] = [
445  'isSectionHeader' => true,
446  'numResultRows' => $resultRowsCount,
447  'sectionId' => $id,
448  'sectionTitle' => $sectionTitleLinked
449  ];
450  // Render result rows
451  foreach ($resultRows as $row) {
452  $finalResultRows[] = $this->‪compileSingleResultRow($row);
453  }
454  }
455  } else {
456  // flat mode or no sections at all
457  foreach ($resultRows as $row) {
458  $finalResultRows[] = $this->‪compileSingleResultRow($row);
459  }
460  }
461  return $finalResultRows;
462  }
463 
471  protected function ‪compileSingleResultRow($row, $headerOnly = 0)
472  {
473  $specRowConf = $this->‪getSpecialConfigurationForResultRow($row);
474  $resultData = $row;
475  $resultData['headerOnly'] = $headerOnly;
476  $resultData['CSSsuffix'] = $specRowConf['CSSsuffix'] ? '-' . $specRowConf['CSSsuffix'] : '';
477  if ($this->‪multiplePagesType($row['item_type'])) {
478  $dat = json_decode($row['static_page_arguments'], true);
479  if (is_array($dat) && is_string($dat['key'] ?? null) && $dat['key'] !== '') {
480  $pp = explode('-', $dat['key']);
481  if ($pp[0] != $pp[1]) {
482  $resultData['titleaddition'] = ', ' . ‪LocalizationUtility::translate('result.pages', 'IndexedSearch') . ' ' . $dat['key'];
483  } else {
484  $resultData['titleaddition'] = ', ' . ‪LocalizationUtility::translate('result.page', 'IndexedSearch') . ' ' . $pp[0];
485  }
486  }
487  }
488  $title = $resultData['item_title'] . $resultData['titleaddition'];
489  $title = GeneralUtility::fixed_lgd_cs($title, $this->settings['results.']['titleCropAfter'], $this->settings['results.']['titleCropSignifier']);
490  // If external media, link to the media-file instead.
491  if ($row['item_type']) {
492  if ($row['show_resume']) {
493  // Can link directly.
494  $targetAttribute = '';
495  if (‪$GLOBALS['TSFE']->config['config']['fileTarget']) {
496  $targetAttribute = ' target="' . htmlspecialchars(‪$GLOBALS['TSFE']->config['config']['fileTarget']) . '"';
497  }
498  $title = '<a href="' . htmlspecialchars($row['data_filename']) . '"' . $targetAttribute . '>' . htmlspecialchars($title) . '</a>';
499  } else {
500  // Suspicious, so linking to page instead...
501  $copiedRow = $row;
502  unset($copiedRow['static_page_arguments']);
503  $title = $this->‪linkPageATagWrap(
504  $title,
505  $this->‪linkPage($row['page_id'], $copiedRow)
506  );
507  }
508  } else {
509  // Else the page:
510  // Prepare search words for markup in content:
511  $markUpSwParams = [];
512  if ($this->settings['forwardSearchWordsInResultLink']['_typoScriptNodeValue']) {
513  if ($this->settings['forwardSearchWordsInResultLink']['no_cache']) {
514  $markUpSwParams = ['no_cache' => 1];
515  }
516  foreach ($this->searchWords as $d) {
517  $markUpSwParams['sword_list'][] = $d['sword'];
518  }
519  }
520  $title = $this->‪linkPageATagWrap(
521  $title,
522  $this->‪linkPage($row['data_page_id'], $row, $markUpSwParams)
523  );
524  }
525  $resultData['title'] = $title;
526  $resultData['icon'] = $this->‪makeItemTypeIcon($row['item_type'], '', $specRowConf);
527  $resultData['rating'] = $this->‪makeRating($row);
528  $resultData['description'] = $this->‪makeDescription(
529  $row,
530  (bool)!($this->searchData['extResume'] && !$headerOnly),
531  $this->settings['results.']['summaryCropAfter']
532  );
533  $resultData['language'] = $this->‪makeLanguageIndication($row);
534  $resultData['size'] = GeneralUtility::formatSize($row['item_size']);
535  $resultData['created'] = $row['item_crdate'];
536  $resultData['modified'] = $row['item_mtime'];
537  $pI = parse_url($row['data_filename']);
538  if ($pI['scheme']) {
539  $targetAttribute = '';
540  if (‪$GLOBALS['TSFE']->config['config']['fileTarget']) {
541  $targetAttribute = ' target="' . htmlspecialchars(‪$GLOBALS['TSFE']->config['config']['fileTarget']) . '"';
542  }
543  $resultData['pathTitle'] = $row['data_filename'];
544  $resultData['pathUri'] = $row['data_filename'];
545  $resultData['path'] = '<a href="' . htmlspecialchars($row['data_filename']) . '"' . $targetAttribute . '>' . htmlspecialchars($row['data_filename']) . '</a>';
546  } else {
547  $pathId = $row['data_page_id'] ?: $row['page_id'];
548  $pathMP = $row['data_page_id'] ? $row['data_page_mp'] : '';
549  $pathStr = $this->‪getPathFromPageId($pathId, $pathMP);
550  $pathLinkData = $this->‪linkPage(
551  $pathId,
552  [
553  'data_page_type' => $row['data_page_type'],
554  'data_page_mp' => $pathMP,
555  'sys_language_uid' => $row['sys_language_uid'],
556  'static_page_arguments' => $row['static_page_arguments']
557  ]
558  );
559 
560  $resultData['pathTitle'] = $pathStr;
561  $resultData['pathUri'] = $pathLinkData['uri'];
562  $resultData['path'] = $this->‪linkPageATagWrap($pathStr, $pathLinkData);
563 
564  // check if the access is restricted
565  if (is_array($this->requiredFrontendUsergroups[$pathId]) && !empty($this->requiredFrontendUsergroups[$pathId])) {
566  $lockedIcon = GeneralUtility::getFileAbsFileName('EXT:indexed_search/Resources/Public/Icons/FileTypes/locked.gif');
567  $lockedIcon = ‪PathUtility::getAbsoluteWebPath($lockedIcon);
568  $resultData['access'] = '<img src="' . htmlspecialchars($lockedIcon) . '"'
569  . ' width="12" height="15" vspace="5" title="'
570  . sprintf(‪LocalizationUtility::translate('result.memberGroups', 'IndexedSearch') ?? '', implode(',', array_unique($this->requiredFrontendUsergroups[$pathId])))
571  . '" alt="" />';
572  }
573  }
574  // If there are subrows (eg. subpages in a PDF-file or if a duplicate page
575  // is selected due to user-login (phash_grouping))
576  if (is_array($row['_sub'])) {
577  $resultData['subresults'] = [];
578  if ($this->‪multiplePagesType($row['item_type'])) {
579  $resultData['subresults']['header'] = ‪LocalizationUtility::translate('result.otherMatching', 'IndexedSearch');
580  foreach ($row['_sub'] as $subRow) {
581  $resultData['subresults']['items'][] = $this->‪compileSingleResultRow($subRow, 1);
582  }
583  } else {
584  $resultData['subresults']['header'] = ‪LocalizationUtility::translate('result.otherMatching', 'IndexedSearch');
585  $resultData['subresults']['info'] = ‪LocalizationUtility::translate('result.otherPageAsWell', 'IndexedSearch');
586  }
587  }
588  return $resultData;
589  }
590 
598  protected function ‪getSpecialConfigurationForResultRow($row)
599  {
600  $pathId = $row['data_page_id'] ?: $row['page_id'];
601  $pathMP = $row['data_page_id'] ? $row['data_page_mp'] : '';
602  $specConf = $this->settings['specialConfiguration']['0'];
603  try {
604  $rl = GeneralUtility::makeInstance(RootlineUtility::class, $pathId, $pathMP)->get();
605  foreach ($rl as $dat) {
606  if (is_array($this->settings['specialConfiguration'][$dat['uid']])) {
607  $specConf = $this->settings['specialConfiguration'][$dat['uid']];
608  $specConf['_pid'] = $dat['uid'];
609  break;
610  }
611  }
612  } catch (RootLineException $e) {
613  // do nothing
614  }
615  return $specConf;
616  }
617 
625  protected function ‪makeRating($row)
626  {
627  $default = ' ';
628  switch ((string)$this->searchData['sortOrder']) {
629  case 'rank_count':
630  return $row['order_val'] . ' ' . ‪LocalizationUtility::translate('result.ratingMatches', 'IndexedSearch');
631  case 'rank_first':
632  return ceil(‪MathUtility::forceIntegerInRange(255 - $row['order_val'], 1, 255) / 255 * 100) . '%';
633  case 'rank_flag':
634  if ($this->firstRow['order_val2']) {
635  // (3 MSB bit, 224 is highest value of order_val1 currently)
636  $base = $row['order_val1'] * 256;
637  // 15-3 MSB = 12
638  $freqNumber = $row['order_val2'] / $this->firstRow['order_val2'] * 2 ** 12;
639  $total = ‪MathUtility::forceIntegerInRange($base + $freqNumber, 0, 32767);
640  return ceil(log($total) / log(32767) * 100) . '%';
641  }
642  return $default;
643  case 'rank_freq':
644  $max = 10000;
645  $total = ‪MathUtility::forceIntegerInRange($row['order_val'], 0, $max);
646  return ceil(log($total) / log($max) * 100) . '%';
647  case 'crdate':
648  return ‪$GLOBALS['TSFE']->cObj->calcAge(‪$GLOBALS['EXEC_TIME'] - $row['item_crdate'], 0);
649  case 'mtime':
650  return ‪$GLOBALS['TSFE']->cObj->calcAge(‪$GLOBALS['EXEC_TIME'] - $row['item_mtime'], 0);
651  default:
652  return $default;
653  }
654  }
655 
662  protected function ‪makeLanguageIndication($row)
663  {
664  ‪$output = '&nbsp;';
665  // If search result is a TYPO3 page:
666  if ((string)$row['item_type'] === '0') {
667  // If TypoScript is used to render the flag:
668  if (is_array($this->settings['flagRendering'])) {
670  $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
671  $cObj->setCurrentVal($row['sys_language_uid']);
672  $typoScriptArray = $this->typoScriptService->convertPlainArrayToTypoScriptArray($this->settings['flagRendering']);
673  ‪$output = $cObj->cObjGetSingle($this->settings['flagRendering']['_typoScriptNodeValue'], $typoScriptArray);
674  }
675  }
676  return ‪$output;
677  }
678 
687  public function ‪makeItemTypeIcon($imageType, $alt, $specRowConf)
688  {
689  // Build compound key if item type is 0, iconRendering is not used
690  // and specialConfiguration.[pid].pageIcon was set in TS
691  if ($imageType === '0' && $specRowConf['_pid'] && is_array($specRowConf['pageIcon']) && !is_array($this->settings['iconRendering'])) {
692  $imageType .= ':' . $specRowConf['_pid'];
693  }
694  if (!isset($this->iconFileNameCache[$imageType])) {
695  $this->iconFileNameCache[$imageType] = '';
696  // If TypoScript is used to render the icon:
697  if (is_array($this->settings['iconRendering'])) {
699  $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
700  $cObj->setCurrentVal($imageType);
701  $typoScriptArray = $this->typoScriptService->convertPlainArrayToTypoScriptArray($this->settings['iconRendering']);
702  $this->iconFileNameCache[$imageType] = $cObj->cObjGetSingle($this->settings['iconRendering']['_typoScriptNodeValue'], $typoScriptArray);
703  } else {
704  // Default creation / finding of icon:
705  $icon = '';
706  if ($imageType === '0' || strpos($imageType, '0:') === 0) {
707  if (is_array($specRowConf['pageIcon'])) {
708  $this->iconFileNameCache[$imageType] = ‪$GLOBALS['TSFE']->cObj->cObjGetSingle('IMAGE', $specRowConf['pageIcon']);
709  } else {
710  $icon = 'EXT:indexed_search/Resources/Public/Icons/FileTypes/pages.gif';
711  }
712  } elseif ($this->externalParsers[$imageType]) {
713  $icon = $this->externalParsers[$imageType]->getIcon($imageType);
714  }
715  if ($icon) {
716  $fullPath = GeneralUtility::getFileAbsFileName($icon);
717  if ($fullPath) {
718  $imageInfo = GeneralUtility::makeInstance(ImageInfo::class, $fullPath);
719  $iconPath = ‪PathUtility::stripPathSitePrefix($fullPath);
720  $this->iconFileNameCache[$imageType] = $imageInfo->getWidth()
721  ? '<img src="' . $iconPath
722  . '" width="' . $imageInfo->getWidth()
723  . '" height="' . $imageInfo->getHeight()
724  . '" title="' . htmlspecialchars($alt) . '" alt="" />'
725  : '';
726  }
727  }
728  }
729  }
730  return $this->iconFileNameCache[$imageType];
731  }
732 
742  protected function ‪makeDescription($row, $noMarkup = false, $length = 180)
743  {
744  $markedSW = '';
745  $outputStr = '';
746  if ($row['show_resume']) {
747  if (!$noMarkup) {
748  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('index_fulltext');
749  $ftdrow = $queryBuilder
750  ->select('*')
751  ->from('index_fulltext')
752  ->where(
753  $queryBuilder->expr()->eq(
754  'phash',
755  $queryBuilder->createNamedParameter($row['phash'], \PDO::PARAM_INT)
756  )
757  )
758  ->execute()
759  ->fetch();
760  if ($ftdrow !== false) {
761  // Cut HTTP references after some length
762  $content = preg_replace('/(http:\\/\\/[^ ]{' . $this->settings['results.']['hrefInSummaryCropAfter'] . '})([^ ]+)/i', '$1...', $ftdrow['fulltextdata']);
763  $markedSW = $this->‪markupSWpartsOfString($content);
764  }
765  }
766  if (!trim($markedSW)) {
767  $outputStr = GeneralUtility::fixed_lgd_cs($row['item_description'], $length, $this->settings['results.']['summaryCropSignifier']);
768  $outputStr = htmlspecialchars($outputStr);
769  }
770  ‪$output = $outputStr ?: $markedSW;
771  } else {
772  ‪$output = '<span class="noResume">' . ‪LocalizationUtility::translate('result.noResume', 'IndexedSearch') . '</span>';
773  }
774  return ‪$output;
775  }
776 
783  protected function ‪markupSWpartsOfString($str)
784  {
785  $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
786  // Init:
787  $str = str_replace('&nbsp;', ' ', $htmlParser->bidir_htmlspecialchars($str, -1));
788  $str = preg_replace('/\\s\\s+/', ' ', $str);
789  $swForReg = [];
790  // Prepare search words for regex:
791  foreach ($this->searchWords as $d) {
792  $swForReg[] = preg_quote($d['sword'], '/');
793  }
794  $regExString = '(' . implode('|', $swForReg) . ')';
795  // Split and combine:
796  $parts = preg_split('/' . $regExString . '/iu', ' ' . $str . ' ', 20000, PREG_SPLIT_DELIM_CAPTURE);
797  $parts = $parts ?: [];
798  // Constants:
799  $summaryMax = $this->settings['results.']['markupSW_summaryMax'];
800  $postPreLgd = (int)$this->settings['results.']['markupSW_postPreLgd'];
801  $postPreLgd_offset = (int)$this->settings['results.']['markupSW_postPreLgd_offset'];
802  $divider = $this->settings['results.']['markupSW_divider'];
803  $occurrences = (count($parts) - 1) / 2;
804  if ($occurrences) {
805  $postPreLgd = ‪MathUtility::forceIntegerInRange($summaryMax / $occurrences, $postPreLgd, $summaryMax / 2);
806  }
807  // Variable:
808  $summaryLgd = 0;
809  ‪$output = [];
810  // Shorten in-between strings:
811  foreach ($parts as $k => $strP) {
812  if ($k % 2 == 0) {
813  // Find length of the summary part:
814  $strLen = mb_strlen($parts[$k], 'utf-8');
815  ‪$output[$k] = $parts[$k];
816  // Possibly shorten string:
817  if (!$k) {
818  // First entry at all (only cropped on the frontside)
819  if ($strLen > $postPreLgd) {
820  ‪$output[$k] = $divider . preg_replace('/^[^[:space:]]+[[:space:]]/', '', GeneralUtility::fixed_lgd_cs($parts[$k], -($postPreLgd - $postPreLgd_offset)));
821  }
822  } elseif ($summaryLgd > $summaryMax || !isset($parts[$k + 1])) {
823  // In case summary length is exceed OR if there are no more entries at all:
824  if ($strLen > $postPreLgd) {
825  ‪$output[$k] = preg_replace('/[[:space:]][^[:space:]]+$/', '', GeneralUtility::fixed_lgd_cs(
826  $parts[$k],
827  $postPreLgd - $postPreLgd_offset
828  )) . $divider;
829  }
830  } else {
831  if ($strLen > $postPreLgd * 2) {
832  ‪$output[$k] = preg_replace('/[[:space:]][^[:space:]]+$/', '', GeneralUtility::fixed_lgd_cs(
833  $parts[$k],
834  $postPreLgd - $postPreLgd_offset
835  )) . $divider . preg_replace('/^[^[:space:]]+[[:space:]]/', '', GeneralUtility::fixed_lgd_cs($parts[$k], -($postPreLgd - $postPreLgd_offset)));
836  }
837  }
838  $summaryLgd += mb_strlen(‪$output[$k], 'utf-8');
839  // Protect output:
840  ‪$output[$k] = htmlspecialchars(‪$output[$k]);
841  // If summary lgd is exceed, break the process:
842  if ($summaryLgd > $summaryMax) {
843  break;
844  }
845  } else {
846  $summaryLgd += mb_strlen($strP, 'utf-8');
847  ‪$output[$k] = '<strong class="tx-indexedsearch-redMarkup">' . htmlspecialchars($parts[$k]) . '</strong>';
848  }
849  }
850  // Return result:
851  return implode('', ‪$output);
852  }
853 
862  protected function ‪writeSearchStat($searchParams, ‪$searchWords, $count, $pt)
863  {
864  $searchWord = $this->‪getSword();
865  if (empty($searchWord) && empty(‪$searchWords)) {
866  return;
867  }
868 
869  $ipAddress = '';
870  try {
871  $ipMask = isset($this->indexerConfig['trackIpInStatistic']) ? (int)$this->indexerConfig['trackIpInStatistic'] : 2;
872  $ipAddress = ‪IpAnonymizationUtility::anonymizeIp(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $ipMask);
873  } catch (\Exception $e) {
874  }
875  $insertFields = [
876  'searchstring' => mb_substr($searchWord, 0, 255),
877  'searchoptions' => serialize([$searchParams, ‪$searchWords, $pt]),
878  'feuser_id' => (int)‪$GLOBALS['TSFE']->fe_user->user['uid'],
879  // cookie as set or retrieved. If people has cookies disabled this will vary all the time
880  'cookie' => ‪$GLOBALS['TSFE']->fe_user->id,
881  // Remote IP address
882  'IP' => $ipAddress,
883  // Number of hits on the search
884  'hits' => (int)$count,
885  // Time stamp
886  'tstamp' => ‪$GLOBALS['EXEC_TIME']
887  ];
888  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('index_search_stat');
889  $connection->insert(
890  'index_stat_search',
891  $insertFields,
892  ['searchoptions' => ‪Connection::PARAM_LOB]
893  );
894  $newId = $connection->lastInsertId('index_stat_search');
895  if ($newId) {
896  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('index_stat_word');
897  foreach (‪$searchWords as $val) {
898  $insertFields = [
899  'word' => mb_substr($val['sword'], 0, 50),
900  'index_stat_search_id' => $newId,
901  // Time stamp
902  'tstamp' => ‪$GLOBALS['EXEC_TIME'],
903  // search page id for indexed search stats
904  'pageid' => ‪$GLOBALS['TSFE']->id
905  ];
906  $connection->insert('index_stat_word', $insertFields);
907  }
908  }
909  }
910 
927  protected function ‪getSearchWords($defaultOperator)
928  {
929  // Shorten search-word string to max 200 bytes - shortening the string here is only a run-away feature!
930  ‪$searchWords = mb_substr($this->‪getSword(), 0, 200);
931  // Convert to UTF-8 + conv. entities (was also converted during indexing!)
932  if (‪$GLOBALS['TSFE']->metaCharset && ‪$GLOBALS['TSFE']->metaCharset !== 'utf-8') {
933  ‪$searchWords = mb_convert_encoding(‪$searchWords, 'utf-8', ‪$GLOBALS['TSFE']->metaCharset);
934  ‪$searchWords = html_entity_decode(‪$searchWords);
935  }
936  $sWordArray = false;
937  if ($hookObj = $this->‪hookRequest('getSearchWords')) {
938  $sWordArray = $hookObj->getSearchWords_splitSWords(‪$searchWords, $defaultOperator);
939  } else {
940  // sentence
941  if ($this->searchData['searchType'] == 20) {
942  $sWordArray = [
943  [
944  'sword' => trim(‪$searchWords),
945  'oper' => 'AND'
946  ]
947  ];
948  } else {
949  // case-sensitive. Defines the words, which will be
950  // operators between words
951  $operatorTranslateTable = [
952  ['+', 'AND'],
953  ['|', 'OR'],
954  ['-', 'AND NOT'],
955  // Add operators for various languages
956  // Converts the operators to lowercase
957  [mb_strtolower(‪LocalizationUtility::translate('localizedOperandAnd', 'IndexedSearch') ?? '', 'utf-8'), 'AND'],
958  [mb_strtolower(‪LocalizationUtility::translate('localizedOperandOr', 'IndexedSearch') ?? '', 'utf-8'), 'OR'],
959  [mb_strtolower(‪LocalizationUtility::translate('localizedOperandNot', 'IndexedSearch') ?? '', 'utf-8'), 'AND NOT']
960  ];
961  $swordArray = ‪IndexedSearchUtility::getExplodedSearchString(‪$searchWords, $defaultOperator == 1 ? 'OR' : 'AND', $operatorTranslateTable);
962  if (is_array($swordArray)) {
963  $sWordArray = $this->‪procSearchWordsByLexer($swordArray);
964  }
965  }
966  }
967  return $sWordArray;
968  }
969 
977  protected function ‪procSearchWordsByLexer(‪$searchWords)
978  {
979  $newSearchWords = [];
980  // Init lexer (used to post-processing of search words)
981  $lexerObjectClassName = ‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['lexer'] ?: Lexer::class;
982  $this->lexerObj = GeneralUtility::makeInstance($lexerObjectClassName);
983  // Traverse the search word array
984  foreach (‪$searchWords as $wordDef) {
985  // No space in word (otherwise it might be a sentence in quotes like "there is").
986  if (strpos($wordDef['sword'], ' ') === false) {
987  // Split the search word by lexer:
988  $res = $this->lexerObj->split2Words($wordDef['sword']);
989  // Traverse lexer result and add all words again:
990  foreach ($res as $word) {
991  $newSearchWords[] = [
992  'sword' => $word,
993  'oper' => $wordDef['oper']
994  ];
995  }
996  } else {
997  $newSearchWords[] = $wordDef;
998  }
999  }
1000  return $newSearchWords;
1001  }
1002 
1009  public function ‪formAction($search = [])
1010  {
1011  ‪$searchData = $this->‪initialize($search);
1012  // Adding search field value
1013  $this->view->assign('sword', $this->‪getSword());
1014  // Extended search
1015  if (!empty(‪$searchData['extendedSearch'])) {
1016  $this->view->assignMultiple($this->‪processExtendedSearchParameters());
1017  }
1018  $this->view->assign('searchParams', ‪$searchData);
1019  }
1020 
1024  public function ‪noTypoScriptAction()
1025  {
1026  }
1027 
1028  /****************************************
1029  * building together the available options for every dropdown
1030  ***************************************/
1036  protected function ‪getAllAvailableSearchTypeOptions()
1037  {
1038  $allOptions = [];
1039  $types = [0, 1, 2, 3, 10, 20];
1040  $blindSettings = $this->settings['blind'];
1041  if (!$blindSettings['searchType']) {
1042  foreach ($types as $typeNum) {
1043  $allOptions[$typeNum] = ‪LocalizationUtility::translate('searchTypes.' . $typeNum, 'IndexedSearch');
1044  }
1045  }
1046  // Remove this option if metaphone search is disabled)
1047  if (!$this->enableMetaphoneSearch) {
1048  unset($allOptions[10]);
1049  }
1050  // disable single entries by TypoScript
1051  $allOptions = $this->‪removeOptionsFromOptionList($allOptions, $blindSettings['searchType']);
1052  return $allOptions;
1053  }
1054 
1060  protected function ‪getAllAvailableOperandsOptions()
1061  {
1062  $allOptions = [];
1063  $blindSettings = $this->settings['blind'];
1064  if (!$blindSettings['defaultOperand']) {
1065  $allOptions = [
1066  0 => ‪LocalizationUtility::translate('defaultOperands.0', 'IndexedSearch'),
1067  1 => ‪LocalizationUtility::translate('defaultOperands.1', 'IndexedSearch')
1068  ];
1069  }
1070  // disable single entries by TypoScript
1071  $allOptions = $this->‪removeOptionsFromOptionList($allOptions, $blindSettings['defaultOperand']);
1072  return $allOptions;
1073  }
1074 
1080  protected function ‪getAllAvailableMediaTypesOptions()
1081  {
1082  $allOptions = [];
1083  $mediaTypes = [-1, 0, -2];
1084  $blindSettings = $this->settings['blind'];
1085  if (!$blindSettings['mediaType']) {
1086  foreach ($mediaTypes as $mediaType) {
1087  $allOptions[$mediaType] = ‪LocalizationUtility::translate('mediaTypes.' . $mediaType, 'IndexedSearch');
1088  }
1089  // Add media to search in:
1090  $additionalMedia = trim($this->settings['mediaList']);
1091  if ($additionalMedia !== '') {
1092  $additionalMedia = ‪GeneralUtility::trimExplode(',', $additionalMedia, true);
1093  } else {
1094  $additionalMedia = [];
1095  }
1096  foreach ($this->externalParsers as $extension => $obj) {
1097  // Skip unwanted extensions
1098  if (!empty($additionalMedia) && !in_array($extension, $additionalMedia)) {
1099  continue;
1100  }
1101  if ($name = $obj->searchTypeMediaTitle($extension)) {
1102  $translatedName = ‪LocalizationUtility::translate('mediaTypes.' . $extension, 'IndexedSearch');
1103  $allOptions[$extension] = $translatedName ?: $name;
1104  }
1105  }
1106  }
1107  // disable single entries by TypoScript
1108  $allOptions = $this->‪removeOptionsFromOptionList($allOptions, $blindSettings['mediaType']);
1109  return $allOptions;
1110  }
1111 
1117  protected function ‪getAllAvailableLanguageOptions()
1118  {
1119  $allOptions = [
1120  '-1' => ‪LocalizationUtility::translate('languageUids.-1', 'IndexedSearch')
1121  ];
1122  $blindSettings = $this->settings['blind'];
1123  if (!$blindSettings['languageUid']) {
1124  try {
1125  $site = GeneralUtility::makeInstance(SiteFinder::class)
1126  ->getSiteByPageId(‪$GLOBALS['TSFE']->id);
1127 
1128  $languages = $site->getLanguages();
1129  foreach ($languages as $language) {
1130  $allOptions[$language->getLanguageId()] = $language->getNavigationTitle() ?? $language->getTitle();
1131  }
1132  } catch (SiteNotFoundException $e) {
1133  // No Site found, no options
1134  $allOptions = [];
1135  }
1137  // disable single entries by TypoScript
1138  $allOptions = $this->‪removeOptionsFromOptionList($allOptions, $blindSettings['languageUid']);
1139  } else {
1140  $allOptions = [];
1141  }
1142  return $allOptions;
1143  }
1144 
1154  protected function ‪getAllAvailableSectionsOptions()
1155  {
1156  $allOptions = [];
1157  $sections = [0, -1, -2, -3];
1158  $blindSettings = $this->settings['blind'];
1159  if (!$blindSettings['sections']) {
1160  foreach ($sections as $section) {
1161  $allOptions[$section] = ‪LocalizationUtility::translate('sections.' . $section, 'IndexedSearch');
1162  }
1163  }
1164  // Creating levels for section menu:
1165  // This selects the first and secondary menus for the "sections" selector - so we can search in sections and sub sections.
1166  if ($this->settings['displayLevel1Sections']) {
1167  $firstLevelMenu = $this->‪getMenuOfPages((int)$this->searchRootPageIdList);
1168  $labelLevel1 = ‪LocalizationUtility::translate('sections.rootLevel1', 'IndexedSearch');
1169  $labelLevel2 = ‪LocalizationUtility::translate('sections.rootLevel2', 'IndexedSearch');
1170  foreach ($firstLevelMenu as $firstLevelKey => $menuItem) {
1171  if (!$menuItem['nav_hide']) {
1172  $allOptions['rl1_' . $menuItem['uid']] = trim($labelLevel1 . ' ' . $menuItem['title']);
1173  if ($this->settings['displayLevel2Sections']) {
1174  $secondLevelMenu = $this->‪getMenuOfPages($menuItem['uid']);
1175  foreach ($secondLevelMenu as $secondLevelKey => $menuItemLevel2) {
1176  if (!$menuItemLevel2['nav_hide']) {
1177  $allOptions['rl2_' . $menuItemLevel2['uid']] = trim($labelLevel2 . ' ' . $menuItemLevel2['title']);
1178  } else {
1179  unset($secondLevelMenu[$secondLevelKey]);
1180  }
1181  }
1182  $allOptions['rl2_' . implode(',', array_keys($secondLevelMenu))] = ‪LocalizationUtility::translate('sections.rootLevel2All', 'IndexedSearch');
1183  }
1184  } else {
1185  unset($firstLevelMenu[$firstLevelKey]);
1186  }
1187  }
1188  $allOptions['rl1_' . implode(',', array_keys($firstLevelMenu))] = ‪LocalizationUtility::translate('sections.rootLevel1All', 'IndexedSearch');
1189  }
1190  // disable single entries by TypoScript
1191  $allOptions = $this->‪removeOptionsFromOptionList($allOptions, $blindSettings['sections']);
1192  return $allOptions;
1193  }
1194 
1201  {
1202  $allOptions = [
1203  '-1' => ‪LocalizationUtility::translate('indexingConfigurations.-1', 'IndexedSearch'),
1204  '-2' => ‪LocalizationUtility::translate('indexingConfigurations.-2', 'IndexedSearch'),
1205  '0' => ‪LocalizationUtility::translate('indexingConfigurations.0', 'IndexedSearch')
1206  ];
1207  $blindSettings = $this->settings['blind'];
1208  if (!$blindSettings['indexingConfigurations']) {
1209  // add an additional index configuration
1210  if ($this->settings['defaultFreeIndexUidList']) {
1211  $uidList = ‪GeneralUtility::intExplode(',', $this->settings['defaultFreeIndexUidList']);
1212  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1213  ->getQueryBuilderForTable('index_config');
1214  $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
1215  $result = $queryBuilder
1216  ->select('uid', 'title')
1217  ->from('index_config')
1218  ->where(
1219  $queryBuilder->expr()->in(
1220  'uid',
1221  $queryBuilder->createNamedParameter($uidList, Connection::PARAM_INT_ARRAY)
1222  )
1223  )
1224  ->execute();
1225 
1226  while ($row = $result->fetch()) {
1227  $indexId = (int)$row['uid'];
1228  $title = ‪LocalizationUtility::translate('indexingConfigurations.' . $indexId, 'IndexedSearch');
1229  $allOptions[$indexId] = $title ?: $row['title'];
1230  }
1231  }
1232  // disable single entries by TypoScript
1233  $allOptions = $this->‪removeOptionsFromOptionList($allOptions, $blindSettings['indexingConfigurations']);
1234  } else {
1235  $allOptions = [];
1236  }
1237  return $allOptions;
1238  }
1239 
1249  protected function ‪getAllAvailableSortOrderOptions()
1250  {
1251  $allOptions = [];
1252  $sortOrders = ['rank_flag', 'rank_freq', 'rank_first', 'rank_count', 'mtime', 'title', 'crdate'];
1253  $blindSettings = $this->settings['blind'];
1254  if (!$blindSettings['sortOrder']) {
1255  foreach ($sortOrders as $order) {
1256  $allOptions[$order] = ‪LocalizationUtility::translate('sortOrders.' . $order, 'IndexedSearch');
1257  }
1258  }
1259  // disable single entries by TypoScript
1260  $allOptions = $this->‪removeOptionsFromOptionList($allOptions, $blindSettings['sortOrder.']);
1261  return $allOptions;
1262  }
1263 
1269  protected function ‪getAllAvailableGroupOptions()
1270  {
1271  $allOptions = [];
1272  $blindSettings = $this->settings['blind'];
1273  if (!$blindSettings['groupBy']) {
1274  $allOptions = [
1275  'sections' => ‪LocalizationUtility::translate('groupBy.sections', 'IndexedSearch'),
1276  'flat' => ‪LocalizationUtility::translate('groupBy.flat', 'IndexedSearch')
1277  ];
1278  }
1279  // disable single entries by TypoScript
1280  $allOptions = $this->‪removeOptionsFromOptionList($allOptions, $blindSettings['groupBy.']);
1281  return $allOptions;
1282  }
1283 
1289  protected function ‪getAllAvailableSortDescendingOptions()
1290  {
1291  $allOptions = [];
1292  $blindSettings = $this->settings['blind'];
1293  if (!$blindSettings['descending']) {
1294  $allOptions = [
1295  0 => ‪LocalizationUtility::translate('sortOrders.descending', 'IndexedSearch'),
1296  1 => ‪LocalizationUtility::translate('sortOrders.ascending', 'IndexedSearch')
1297  ];
1298  }
1299  // disable single entries by TypoScript
1300  $allOptions = $this->‪removeOptionsFromOptionList($allOptions, $blindSettings['descending.']);
1301  return $allOptions;
1302  }
1303 
1310  {
1311  $allOptions = [];
1312  if (count($this->availableResultsNumbers) > 1) {
1313  $allOptions = array_combine($this->availableResultsNumbers, $this->availableResultsNumbers) ?: [];
1314  }
1315  // disable single entries by TypoScript
1316  $allOptions = $this->‪removeOptionsFromOptionList($allOptions, $this->settings['blind']['numberOfResults']);
1317  return $allOptions;
1318  }
1319 
1327  protected function ‪removeOptionsFromOptionList($allOptions, $blindOptions)
1328  {
1329  if (is_array($blindOptions)) {
1330  foreach ($blindOptions as $key => $val) {
1331  if ($val == 1) {
1332  unset($allOptions[$key]);
1333  }
1334  }
1335  }
1336  return $allOptions;
1337  }
1338 
1347  protected function ‪linkPage($pageUid, $row = [], $markUpSwParams = [])
1348  {
1349  $pageLanguage = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'contentId', 0);
1350  // Parameters for link
1351  $urlParameters = [];
1352  if ($row['static_page_arguments'] !== null) {
1353  $urlParameters = json_decode($row['static_page_arguments'], true);
1354  }
1355  // Add &type and &MP variable:
1356  if ($row['data_page_mp']) {
1357  $urlParameters['MP'] = $row['data_page_mp'];
1358  }
1359  if (($pageLanguage === 0 && $row['sys_language_uid'] > 0) || $pageLanguage > 0) {
1360  $urlParameters['L'] = (int)$row['sys_language_uid'];
1361  }
1362  // markup-GET vars:
1363  $urlParameters = array_merge($urlParameters, $markUpSwParams);
1364  // This will make sure that the path is retrieved if it hasn't been
1365  // already. Used only for the sake of the domain_record thing.
1366  if (!is_array($this->domainRecords[$pageUid])) {
1367  $this->‪getPathFromPageId($pageUid);
1368  }
1369 
1370  return $this->‪preparePageLink($pageUid, $row, $urlParameters);
1371  }
1372 
1379  protected function ‪getMenuOfPages($pageUid)
1380  {
1381  $pageRepository = GeneralUtility::makeInstance(PageRepository::class);
1382  if ($this->settings['displayLevelxAllTypes']) {
1383  return $pageRepository->getMenuForPages([$pageUid]);
1384  }
1385  return $pageRepository->getMenu($pageUid);
1386  }
1387 
1395  protected function ‪getPathFromPageId($id, $pathMP = '')
1396  {
1397  $identStr = $id . '|' . $pathMP;
1398  if (!isset($this->pathCache[$identStr])) {
1399  $this->requiredFrontendUsergroups[$id] = [];
1400  $this->domainRecords[$id] = [];
1401  try {
1402  $rl = GeneralUtility::makeInstance(RootlineUtility::class, $id, $pathMP)->get();
1403  $path = '';
1404  $pageCount = count($rl);
1405  if (!empty($rl)) {
1406  $excludeDoktypesFromPath = ‪GeneralUtility::trimExplode(
1407  ',',
1408  $this->settings['results']['pathExcludeDoktypes'] ?? '',
1409  true
1410  );
1411  $breadcrumbWrap = $this->settings['breadcrumbWrap'] ?? '/';
1412  $breadcrumbWraps = GeneralUtility::makeInstance(TypoScriptService::class)
1413  ->explodeConfigurationForOptionSplit(['wrap' => $breadcrumbWrap], $pageCount);
1414  foreach ($rl as $k => $v) {
1415  if (in_array($v['doktype'], $excludeDoktypesFromPath, false)) {
1416  continue;
1417  }
1418  // Check fe_user
1419  if ($v['fe_group'] && ($v['uid'] == $id || $v['extendToSubpages'])) {
1420  $this->requiredFrontendUsergroups[$id][] = $v['fe_group'];
1421  }
1422  // Check sys_domain
1423  if ($this->settings['detectDomainRecords']) {
1424  $domainName = $this->‪getFirstDomainForPage((int)$v['uid']);
1425  if ($domainName) {
1426  $this->domainRecords[$id][] = $domainName;
1427  // Set path accordingly
1428  $path = $domainName . $path;
1429  break;
1430  }
1431  }
1432  // Stop, if we find that the current id is the current root page.
1433  if ($v['uid'] == ‪$GLOBALS['TSFE']->config['rootLine'][0]['uid']) {
1434  array_pop($breadcrumbWraps);
1435  break;
1436  }
1437  $path = ‪$GLOBALS['TSFE']->cObj->wrap(htmlspecialchars($v['title']), array_pop($breadcrumbWraps)['wrap']) . $path;
1438  }
1439  }
1440  } catch (RootLineException $e) {
1441  $path = '';
1442  }
1443  $this->pathCache[$identStr] = $path;
1444  }
1445  return $this->pathCache[$identStr];
1446  }
1447 
1454  protected function ‪getFirstDomainForPage(int $id): string
1455  {
1456  $domain = '';
1457  try {
1458  $domain = GeneralUtility::makeInstance(SiteFinder::class)
1459  ->getSiteByRootPageId($id)
1460  ->getBase()
1461  ->getHost();
1462  } catch (‪SiteNotFoundException $e) {
1463  // site was not found, we return an empty string as default
1464  }
1465  return $domain;
1466  }
1467 
1472  protected function ‪initializeExternalParsers()
1473  {
1474  // Initialize external document parsers for icon display and other soft operations
1475  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['external_parsers'] ?? [] as $extension => $className) {
1476  $this->externalParsers[$extension] = GeneralUtility::makeInstance($className);
1477  // Init parser and if it returns FALSE, unset its entry again
1478  if (!$this->externalParsers[$extension]->softInit($extension)) {
1479  unset($this->externalParsers[$extension]);
1480  }
1481  }
1482  }
1483 
1490  protected function ‪hookRequest($functionName)
1491  {
1492  // Hook: menuConfig_preProcessModMenu
1493  if (‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['pi1_hooks'][$functionName]) {
1494  $hookObj = GeneralUtility::makeInstance(‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['pi1_hooks'][$functionName]);
1495  if (method_exists($hookObj, $functionName)) {
1496  $hookObj->pObj = $this;
1497  return $hookObj;
1498  }
1499  }
1500  return null;
1501  }
1502 
1509  protected function ‪multiplePagesType($item_type)
1510  {
1511  return is_object($this->externalParsers[$item_type]) && $this->externalParsers[$item_type]->isMultiplePageExtension($item_type);
1512  }
1513 
1521  protected function ‪processExtendedSearchParameters()
1522  {
1523  $allSearchTypes = $this->‪getAllAvailableSearchTypeOptions();
1524  $allDefaultOperands = $this->‪getAllAvailableOperandsOptions();
1525  $allMediaTypes = $this->‪getAllAvailableMediaTypesOptions();
1526  $allLanguageUids = $this->‪getAllAvailableLanguageOptions();
1527  $allSortOrders = $this->‪getAllAvailableSortOrderOptions();
1528  $allSortDescendings = $this->‪getAllAvailableSortDescendingOptions();
1529 
1530  return [
1531  'allSearchTypes' => $allSearchTypes,
1532  'allDefaultOperands' => $allDefaultOperands,
1533  'showTypeSearch' => !empty($allSearchTypes) || !empty($allDefaultOperands),
1534  'allMediaTypes' => $allMediaTypes,
1535  'allLanguageUids' => $allLanguageUids,
1536  'showMediaAndLanguageSearch' => !empty($allMediaTypes) || !empty($allLanguageUids),
1537  'allSections' => $this->‪getAllAvailableSectionsOptions(),
1538  'allIndexConfigurations' => $this->‪getAllAvailableIndexConfigurationsOptions(),
1539  'allSortOrders' => $allSortOrders,
1540  'allSortDescendings' => $allSortDescendings,
1541  'showSortOrders' => !empty($allSortOrders) || !empty($allSortDescendings),
1542  'allNumberOfResults' => $this->‪getAllAvailableNumberOfResultsOptions(),
1543  'allGroups' => $this->‪getAllAvailableGroupOptions()
1544  ];
1545  }
1546 
1550  protected function ‪loadSettings()
1551  {
1552  if (!is_array($this->settings['results.'])) {
1553  $this->settings['results.'] = [];
1554  }
1555  $fullTypoScriptArray = $this->typoScriptService->convertPlainArrayToTypoScriptArray($this->settings);
1556  $this->settings['detectDomainRecords'] = $fullTypoScriptArray['detectDomainRecords'] ?? 0;
1557  $this->settings['detectDomainRecords.'] = $fullTypoScriptArray['detectDomainRecords.'] ?? [];
1558  $typoScriptArray = $fullTypoScriptArray['results.'];
1559 
1560  $this->settings['results.']['summaryCropAfter'] = ‪MathUtility::forceIntegerInRange(
1561  ‪$GLOBALS['TSFE']->cObj->stdWrap($typoScriptArray['summaryCropAfter'], $typoScriptArray['summaryCropAfter.']),
1562  10,
1563  5000,
1564  180
1565  );
1566  $this->settings['results.']['summaryCropSignifier'] = ‪$GLOBALS['TSFE']->cObj->stdWrap($typoScriptArray['summaryCropSignifier'], $typoScriptArray['summaryCropSignifier.']);
1567  $this->settings['results.']['titleCropAfter'] = ‪MathUtility::forceIntegerInRange(
1568  ‪$GLOBALS['TSFE']->cObj->stdWrap($typoScriptArray['titleCropAfter'], $typoScriptArray['titleCropAfter.']),
1569  10,
1570  500,
1571  50
1572  );
1573  $this->settings['results.']['titleCropSignifier'] = ‪$GLOBALS['TSFE']->cObj->stdWrap($typoScriptArray['titleCropSignifier'], $typoScriptArray['titleCropSignifier.']);
1574  $this->settings['results.']['markupSW_summaryMax'] = ‪MathUtility::forceIntegerInRange(
1575  ‪$GLOBALS['TSFE']->cObj->stdWrap($typoScriptArray['markupSW_summaryMax'], $typoScriptArray['markupSW_summaryMax.']),
1576  10,
1577  5000,
1578  300
1579  );
1580  $this->settings['results.']['markupSW_postPreLgd'] = ‪MathUtility::forceIntegerInRange(
1581  ‪$GLOBALS['TSFE']->cObj->stdWrap($typoScriptArray['markupSW_postPreLgd'], $typoScriptArray['markupSW_postPreLgd.']),
1582  1,
1583  500,
1584  60
1585  );
1586  $this->settings['results.']['markupSW_postPreLgd_offset'] = ‪MathUtility::forceIntegerInRange(
1587  ‪$GLOBALS['TSFE']->cObj->stdWrap($typoScriptArray['markupSW_postPreLgd_offset'], $typoScriptArray['markupSW_postPreLgd_offset.']),
1588  1,
1589  50,
1590  5
1591  );
1592  $this->settings['results.']['markupSW_divider'] = ‪$GLOBALS['TSFE']->cObj->stdWrap($typoScriptArray['markupSW_divider'], $typoScriptArray['markupSW_divider.']);
1593  $this->settings['results.']['hrefInSummaryCropAfter'] = ‪MathUtility::forceIntegerInRange(
1594  ‪$GLOBALS['TSFE']->cObj->stdWrap($typoScriptArray['hrefInSummaryCropAfter'], $typoScriptArray['hrefInSummaryCropAfter.']),
1595  10,
1596  400,
1597  60
1598  );
1599  $this->settings['results.']['hrefInSummaryCropSignifier'] = ‪$GLOBALS['TSFE']->cObj->stdWrap($typoScriptArray['hrefInSummaryCropSignifier'], $typoScriptArray['hrefInSummaryCropSignifier.']);
1600  }
1601 
1608  protected function ‪getNumberOfResults($numberOfResults)
1609  {
1610  $numberOfResults = (int)$numberOfResults;
1611 
1612  return in_array($numberOfResults, $this->availableResultsNumbers) ?
1613  $numberOfResults : ‪$this->defaultResultNumber;
1614  }
1615 
1625  protected function ‪preparePageLink(int $pageUid, array $row, array $urlParameters): array
1626  {
1627  $target = '';
1628  $uri = $this->controllerContext->getUriBuilder()
1629  ->setTargetPageUid($pageUid)
1630  ->setTargetPageType($row['data_page_type'])
1631  ->setArguments($urlParameters)
1632  ->build();
1633 
1634  // If external domain, then link to that:
1635  if (!empty($this->domainRecords[$pageUid])) {
1636  $scheme = GeneralUtility::getIndpEnv('TYPO3_SSL') ? 'https://' : 'http://';
1637  $firstDomain = reset($this->domainRecords[$pageUid]);
1638  $uri = $scheme . $firstDomain . $uri;
1639  $target = $this->settings['detectDomainRecords.']['target'] ?? '';
1640  }
1641 
1642  return ['uri' => $uri, 'target' => $target];
1643  }
1644 
1652  protected function ‪linkPageATagWrap(string $linkText, array $linkData): string
1653  {
1654  $attributes = [
1655  'href' => $linkData['uri']
1656  ];
1657  if (!empty($linkData['target'])) {
1658  $attributes['target'] = $linkData['target'];
1659  }
1660  return sprintf(
1661  '<a %s>%s</a>',
1662  GeneralUtility::implodeAttributes($attributes, true),
1663  htmlspecialchars($linkText, ENT_QUOTES | ENT_HTML5)
1664  );
1665  }
1666 
1671  public function ‪setSword(‪$sword)
1672  {
1673  $this->sword = (string)‪$sword;
1674  }
1675 
1680  public function ‪getSword()
1681  {
1682  return (string)‪$this->sword;
1683  }
1684 }
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\multiplePagesType
‪bool multiplePagesType($item_type)
Definition: SearchController.php:1491
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\markupSWpartsOfString
‪string markupSWpartsOfString($str)
Definition: SearchController.php:765
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\makeDescription
‪string makeDescription($row, $noMarkup=false, $length=180)
Definition: SearchController.php:724
‪TYPO3\CMS\IndexedSearch\Controller\SearchController
Definition: SearchController.php:51
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\noTypoScriptAction
‪noTypoScriptAction()
Definition: SearchController.php:1006
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:24
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$searchRootPageIdList
‪int string $searchRootPageIdList
Definition: SearchController.php:74
‪TYPO3\CMS\Extbase\Annotation
Definition: IgnoreValidation.php:18
‪TYPO3\CMS\Extbase\Utility\LocalizationUtility
Definition: LocalizationUtility.php:33
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$externalParsers
‪array $externalParsers
Definition: SearchController.php:99
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getAllAvailableOperandsOptions
‪array getAllAvailableOperandsOptions()
Definition: SearchController.php:1042
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$defaultResultNumber
‪int $defaultResultNumber
Definition: SearchController.php:78
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$indexerConfig
‪array $indexerConfig
Definition: SearchController.php:141
‪TYPO3\CMS\Core\Html\HtmlParser
Definition: HtmlParser.php:27
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$requiredFrontendUsergroups
‪array $requiredFrontendUsergroups
Definition: SearchController.php:117
‪TYPO3\CMS\Core\Configuration\ExtensionConfiguration
Definition: ExtensionConfiguration.php:45
‪TYPO3\CMS\IndexedSearch\Domain\Repository\IndexSearchRepository
Definition: IndexSearchRepository.php:39
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getAllAvailableSearchTypeOptions
‪array getAllAvailableSearchTypeOptions()
Definition: SearchController.php:1018
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:372
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\formAction
‪formAction($search=[])
Definition: SearchController.php:991
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$searchRepository
‪TYPO3 CMS IndexedSearch Domain Repository IndexSearchRepository $searchRepository
Definition: SearchController.php:88
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getPathFromPageId
‪string getPathFromPageId($id, $pathMP='')
Definition: SearchController.php:1377
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getAllAvailableGroupOptions
‪array getAllAvailableGroupOptions()
Definition: SearchController.php:1251
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$pathCache
‪array $pathCache
Definition: SearchController.php:129
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:32
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\compileSingleResultRow
‪array compileSingleResultRow($row, $headerOnly=0)
Definition: SearchController.php:453
‪TYPO3\CMS\Core\Utility\RootlineUtility
Definition: RootlineUtility.php:39
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getFirstDomainForPage
‪string getFirstDomainForPage(int $id)
Definition: SearchController.php:1436
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:26
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getMenuOfPages
‪array getMenuOfPages($pageUid)
Definition: SearchController.php:1361
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\compileResultRows
‪array compileResultRows($resultRows, $freeIndexUid=-1)
Definition: SearchController.php:368
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$iconFileNameCache
‪array $iconFileNameCache
Definition: SearchController.php:135
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getSword
‪string getSword()
Definition: SearchController.php:1662
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:53
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\searchAction
‪searchAction($search=[])
Definition: SearchController.php:248
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\writeSearchStat
‪writeSearchStat($searchParams, $searchWords, $count, $pt)
Definition: SearchController.php:844
‪TYPO3\CMS\Core\Utility\IpAnonymizationUtility
Definition: IpAnonymizationUtility.php:26
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\redirect
‪redirect($actionName, $controllerName=null, $extensionName=null, array $arguments=null, $pageUid=null, $delay=0, $statusCode=303)
Definition: ActionController.php:852
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getAllAvailableIndexConfigurationsOptions
‪array getAllAvailableIndexConfigurationsOptions()
Definition: SearchController.php:1182
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getAllAvailableSortOrderOptions
‪array getAllAvailableSortOrderOptions()
Definition: SearchController.php:1231
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\linkPageATagWrap
‪string linkPageATagWrap(string $linkText, array $linkData)
Definition: SearchController.php:1634
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\hookRequest
‪object null hookRequest($functionName)
Definition: SearchController.php:1472
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\linkPage
‪array linkPage($pageUid, $row=[], $markUpSwParams=[])
Definition: SearchController.php:1329
‪TYPO3\CMS\IndexedSearch\Controller
Definition: AdministrationController.php:16
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\setSword
‪setSword($sword)
Definition: SearchController.php:1653
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\initialize
‪array initialize($searchData=[])
Definition: SearchController.php:167
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$lexerObj
‪TYPO3 CMS IndexedSearch Lexer $lexerObj
Definition: SearchController.php:94
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$searchWords
‪array $searchWords
Definition: SearchController.php:60
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$resultSections
‪array $resultSections
Definition: SearchController.php:123
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$firstRow
‪array $firstRow
Definition: SearchController.php:105
‪TYPO3\CMS\Extbase\Utility\LocalizationUtility\translate
‪static string null translate(string $key, ?string $extensionName=null, array $arguments=null, string $languageKey=null, array $alternativeLanguageKeys=null)
Definition: LocalizationUtility.php:67
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\makeLanguageIndication
‪string makeLanguageIndication($row)
Definition: SearchController.php:644
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\procSearchWordsByLexer
‪array procSearchWordsByLexer($searchWords)
Definition: SearchController.php:959
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\removeOptionsFromOptionList
‪array removeOptionsFromOptionList($allOptions, $blindOptions)
Definition: SearchController.php:1309
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getAllAvailableMediaTypesOptions
‪array getAllAvailableMediaTypesOptions()
Definition: SearchController.php:1062
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$typoScriptService
‪TYPO3 CMS Core TypoScript TypoScriptService $typoScriptService
Definition: SearchController.php:151
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\injectTypoScriptService
‪injectTypoScriptService(TypoScriptService $typoScriptService)
Definition: SearchController.php:156
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$domainRecords
‪array $domainRecords
Definition: SearchController.php:111
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getSpecialConfigurationForResultRow
‪array getSpecialConfigurationForResultRow($row)
Definition: SearchController.php:580
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$sword
‪string $sword
Definition: SearchController.php:56
‪TYPO3\CMS\Core\Type\File\ImageInfo
Definition: ImageInfo.php:27
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\loadSettings
‪loadSettings()
Definition: SearchController.php:1532
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:1059
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getDisplayResults
‪array getDisplayResults($searchWords, $resultData, $freeIndexUid=-1)
Definition: SearchController.php:326
‪TYPO3\CMS\Core\TypoScript\TypoScriptService
Definition: TypoScriptService.php:25
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$availableResultsNumbers
‪int[] $availableResultsNumbers
Definition: SearchController.php:82
‪$output
‪$output
Definition: annotationChecker.php:119
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\makeRating
‪string makeRating($row)
Definition: SearchController.php:607
‪TYPO3\CMS\IndexedSearch\Lexer
Definition: Lexer.php:27
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$searchData
‪array $searchData
Definition: SearchController.php:64
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getNumberOfResults
‪int getNumberOfResults($numberOfResults)
Definition: SearchController.php:1590
‪TYPO3\CMS\IndexedSearch\Utility\IndexedSearchUtility\milliseconds
‪static int milliseconds()
Definition: IndexedSearchUtility.php:175
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\processExtendedSearchParameters
‪array processExtendedSearchParameters()
Definition: SearchController.php:1503
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController
Definition: ActionController.php:55
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static int[] intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:988
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:22
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:97
‪TYPO3\CMS\Core\Exception\Page\RootLineException
Definition: RootLineException.php:25
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\preparePageLink
‪array preparePageLink(int $pageUid, array $row, array $urlParameters)
Definition: SearchController.php:1607
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\$enableMetaphoneSearch
‪bool $enableMetaphoneSearch
Definition: SearchController.php:147
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getSearchWords
‪array getSearchWords($defaultOperator)
Definition: SearchController.php:909
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:52
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Utility\PathUtility\getAbsoluteWebPath
‪static string getAbsoluteWebPath($targetPath)
Definition: PathUtility.php:43
‪TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer
Definition: FrontendRestrictionContainer.php:31
‪TYPO3\CMS\IndexedSearch\Utility\IndexedSearchUtility
Definition: IndexedSearchUtility.php:26
‪TYPO3\CMS\Core\Utility\IpAnonymizationUtility\anonymizeIp
‪static string anonymizeIp(string $address, int $mask=null)
Definition: IpAnonymizationUtility.php:62
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getAllAvailableLanguageOptions
‪array getAllAvailableLanguageOptions()
Definition: SearchController.php:1099
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\makeItemTypeIcon
‪string makeItemTypeIcon($imageType, $alt, $specRowConf)
Definition: SearchController.php:669
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getAllAvailableSortDescendingOptions
‪array getAllAvailableSortDescendingOptions()
Definition: SearchController.php:1271
‪TYPO3\CMS\IndexedSearch\Utility\IndexedSearchUtility\getExplodedSearchString
‪static array getExplodedSearchString($sword, $defaultOperator, $operatorTranslateTable)
Definition: IndexedSearchUtility.php:62
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getAllAvailableNumberOfResultsOptions
‪array getAllAvailableNumberOfResultsOptions()
Definition: SearchController.php:1291
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\getAllAvailableSectionsOptions
‪array getAllAvailableSectionsOptions()
Definition: SearchController.php:1136
‪TYPO3\CMS\IndexedSearch\Controller\SearchController\initializeExternalParsers
‪initializeExternalParsers()
Definition: SearchController.php:1454
‪TYPO3\CMS\Core\Database\Connection\PARAM_LOB
‪const PARAM_LOB
Definition: Connection.php:57