2 namespace TYPO3\CMS\IndexedSearch\Controller;
19 use TYPO3\CMS\IndexedSearch\Utility;
185 $this->pi_loadLL(
'EXT:indexed_search/Resources/Private/Language/locallang_pi.xlf');
191 if (is_array($this->sWArr) && !empty($this->sWArr)) {
192 $content = $this->
doSearch($this->sWArr);
207 $this->indexerConfig = unserialize(
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXT'][
'extConf'][
'indexed_search']);
208 $this->enableMetaphoneSearch = (bool)$this->indexerConfig[
'enableMetaphoneSearch'];
209 $this->storeMetaphoneInfoAsWords = !\TYPO3\CMS\IndexedSearch\Utility\IndexedSearchUtility::isTableUsed(
'index_words');
211 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'indexed_search'][
'external_parsers'])) {
212 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'indexed_search'][
'external_parsers'] as $extension => $_objRef) {
215 if (!$this->external_parsers[$extension]->softInit($extension)) {
216 unset($this->external_parsers[$extension]);
221 $lexerObjRef =
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'indexed_search'][
'lexer'] ?: \TYPO3\CMS\IndexedSearch\Lexer::class;
224 if ($this->piVars[
'_sections']) {
225 $this->piVars[
'sections'] = $this->piVars[
'_sections'];
228 if ($this->piVars[
'_freeIndexUid'] !==
'_') {
229 $this->piVars[
'freeIndexUid'] = $this->piVars[
'_freeIndexUid'];
232 if ($this->piVars[
'sword_prev_include'] && $this->piVars[
'sword_prev']) {
233 $this->piVars[
'sword'] = trim($this->piVars[
'sword_prev']) .
' ' . $this->piVars[
'sword'];
240 $this->optValues = array(
242 '0' => $this->
pi_getLL(
'opt_type_0'),
243 '1' => $this->
pi_getLL(
'opt_type_1'),
244 '2' => $this->
pi_getLL(
'opt_type_2'),
245 '3' => $this->
pi_getLL(
'opt_type_3'),
246 '10' => $this->
pi_getLL(
'opt_type_10'),
247 '20' => $this->
pi_getLL(
'opt_type_20')
250 '0' => $this->
pi_getLL(
'opt_defOp_0'),
251 '1' => $this->
pi_getLL(
'opt_defOp_1')
254 '0' => $this->
pi_getLL(
'opt_sections_0'),
255 '-1' => $this->
pi_getLL(
'opt_sections_-1'),
256 '-2' => $this->
pi_getLL(
'opt_sections_-2'),
257 '-3' => $this->
pi_getLL(
'opt_sections_-3')
259 'freeIndexUid' => array(
260 '-1' => $this->
pi_getLL(
'opt_freeIndexUid_-1'),
261 '-2' => $this->
pi_getLL(
'opt_freeIndexUid_-2'),
262 '0' => $this->
pi_getLL(
'opt_freeIndexUid_0')
265 '-1' => $this->
pi_getLL(
'opt_media_-1'),
266 '0' => $this->
pi_getLL(
'opt_media_0'),
267 '-2' => $this->
pi_getLL(
'opt_media_-2')
270 'rank_flag' => $this->
pi_getLL(
'opt_order_rank_flag'),
271 'rank_freq' => $this->
pi_getLL(
'opt_order_rank_freq'),
272 'rank_first' => $this->
pi_getLL(
'opt_order_rank_first'),
273 'rank_count' => $this->
pi_getLL(
'opt_order_rank_count'),
274 'mtime' => $this->
pi_getLL(
'opt_order_mtime'),
275 'title' => $this->
pi_getLL(
'opt_order_title'),
276 'crdate' => $this->
pi_getLL(
'opt_order_crdate')
279 'sections' => $this->
pi_getLL(
'opt_group_sections'),
280 'flat' => $this->
pi_getLL(
'opt_group_flat')
283 -1 => $this->
pi_getLL(
'opt_lang_-1'),
287 '0' => $this->
pi_getLL(
'opt_desc_0'),
288 '1' => $this->
pi_getLL(
'opt_desc_1')
298 if (!$this->enableMetaphoneSearch) {
299 unset($this->optValues[
'type'][
'10']);
302 if ($this->conf[
'search.'][
'defaultFreeIndexUidList']) {
304 $indexCfgRecords = $this->databaseConnection->exec_SELECTgetRows(
'uid,title',
'index_config',
'uid IN (' . implode(
',', $uidList) .
')' . $this->cObj->enableFields(
'index_config'),
'',
'',
'',
'uid');
305 foreach ($uidList as $uidValue) {
306 if (is_array($indexCfgRecords[$uidValue])) {
307 $this->optValues[
'freeIndexUid'][$uidValue] = $indexCfgRecords[$uidValue][
'title'];
312 if ($this->conf[
'search.'][
'skipExtendToSubpagesChecking']) {
313 $this->join_pages = 1;
316 if (trim($this->conf[
'search.'][
'mediaList']) !==
'') {
319 foreach ($this->external_parsers as $extension => $obj) {
324 if ($name = $obj->searchTypeMediaTitle($extension)) {
325 $this->optValues[
'media'][$extension] = $this->
pi_getLL(
'opt_sections_' . $extension, $name);
330 $this->operator_translate_table[] = array($this->frontendController->csConvObj->conv_case(
'utf-8', $this->frontendController->csConvObj->utf8_encode($this->pi_getLL(
'local_operator_AND'), $this->frontendController->renderCharset),
'toLower'),
'AND');
331 $this->operator_translate_table[] = array($this->frontendController->csConvObj->conv_case(
'utf-8', $this->frontendController->csConvObj->utf8_encode($this->pi_getLL(
'local_operator_OR'), $this->frontendController->renderCharset),
'toLower'),
'OR');
332 $this->operator_translate_table[] = array($this->frontendController->csConvObj->conv_case(
'utf-8', $this->frontendController->csConvObj->utf8_encode($this->pi_getLL(
'local_operator_NOT'), $this->frontendController->renderCharset),
'toLower'),
'AND NOT');
334 $this->wholeSiteIdList = (int)$this->frontendController->config[
'rootLine'][0][
'uid'];
337 if ($this->conf[
'show.'][
'L1sections']) {
338 $firstLevelMenu = $this->
getMenu($this->wholeSiteIdList);
339 foreach ($firstLevelMenu as $optionName => $mR) {
340 if (!$mR[
'nav_hide']) {
341 $this->optValues[
'sections'][
'rl1_' . $mR[
'uid']] = trim($this->
pi_getLL(
'opt_RL1') .
' ' . $mR[
'title']);
342 if ($this->conf[
'show.'][
'L2sections']) {
343 $secondLevelMenu = $this->
getMenu($mR[
'uid']);
344 foreach ($secondLevelMenu as $kk2 => $mR2) {
345 if (!$mR2[
'nav_hide']) {
346 $this->optValues[
'sections'][
'rl2_' . $mR2[
'uid']] = trim($this->
pi_getLL(
'opt_RL2') .
' ' . $mR2[
'title']);
348 unset($secondLevelMenu[$kk2]);
351 $this->optValues[
'sections'][
'rl2_' . implode(
',', array_keys($secondLevelMenu))] = $this->
pi_getLL(
'opt_RL2ALL');
354 unset($firstLevelMenu[$optionName]);
357 $this->optValues[
'sections'][
'rl1_' . implode(
',', array_keys($firstLevelMenu))] = $this->
pi_getLL(
'opt_RL1ALL');
361 if ($this->conf[
'search.'][
'rootPidList']) {
365 $this->templateCode = $this->cObj->fileResource($this->conf[
'templateFile']);
367 $res = $this->databaseConnection->exec_SELECTquery(
'*',
'sys_language',
'1=1' . $this->cObj->enableFields(
'sys_language'));
368 while (
false !== ($data = $this->databaseConnection->sql_fetch_assoc($res))) {
369 $this->optValues[
'lang'][$data[
'uid']] = $data[
'title'];
371 $this->databaseConnection->sql_free_result($res);
373 if ($hookObj = $this->
hookRequest(
'initialize_postProc')) {
374 $hookObj->initialize_postProc();
378 foreach ($this->optValues as $optionName => $optionValue) {
379 if (!isset($this->piVars[$optionName])) {
381 $this->piVars[$optionName] = key($optionValue);
385 if (is_array($this->conf[
'blind.'])) {
386 foreach ($this->conf[
'blind.'] as $optionName => $optionValue) {
387 if (is_array($optionValue)) {
388 foreach ($optionValue as $optionValueSubKey => $optionValueSubValue) {
389 if (!is_array($optionValueSubValue) && $optionValueSubValue && is_array($this->optValues[substr($optionName, 0, -1)])) {
390 unset($this->optValues[substr($optionName, 0, -1)][$optionValueSubKey]);
395 unset($this->optValues[$optionName]);
421 $inSW = substr($this->piVars[
'sword'], 0, 200);
423 $inSW = $this->frontendController->csConvObj->utf8_encode($inSW, $this->frontendController->metaCharset);
424 $inSW = $this->frontendController->csConvObj->entities_to_utf8($inSW,
true);
426 if ($hookObj = $this->
hookRequest(
'getSearchWords')) {
427 $sWordArray = $hookObj->getSearchWords_splitSWords($inSW, $defOp);
429 if ($this->piVars[
'type'] == 20) {
431 $sWordArray = array(array(
'sword' => trim($inSW),
'oper' =>
'AND'));
433 $searchWords = \TYPO3\CMS\IndexedSearch\Utility\IndexedSearchUtility::getExplodedSearchString($inSW, $defOp == 1 ?
'OR' :
'AND', $this->operator_translate_table);
434 if (is_array($searchWords)) {
454 foreach ($SWArr as $wordDef) {
455 if (!strstr($wordDef[
'sword'],
' ')) {
458 $res = $this->lexerObj->split2Words($wordDef[
'sword']);
460 foreach ($res as $word) {
461 $newSWArr[] = array(
'sword' => $word,
'oper' => $wordDef[
'oper']);
464 $newSWArr[] = $wordDef;
485 $freeIndexUid = $this->piVars[
'freeIndexUid'];
486 if ($freeIndexUid == -2) {
487 $freeIndexUid = $this->conf[
'search.'][
'defaultFreeIndexUidList'];
490 $accumulatedContent =
'';
491 foreach ($indexCfgs as $freeIndexUid) {
494 if ($hookObj = $this->
hookRequest(
'getResultRows')) {
495 $resData = $hookObj->getResultRows(
$sWArr, $freeIndexUid);
501 if ($hookObj = $this->
hookRequest(
'getDisplayResults')) {
502 $content = $hookObj->getDisplayResults(
$sWArr, $resData, $freeIndexUid);
508 if (count($indexCfgs) > 1) {
509 if ($freeIndexUid > 0) {
510 $indexCfgRec = $this->databaseConnection->exec_SELECTgetSingleRow(
'title',
'index_config',
'uid=' . (
int)$freeIndexUid . $this->cObj->enableFields(
'index_config'));
511 $titleString = $indexCfgRec[
'title'];
513 $titleString = $this->
pi_getLL(
'opt_freeIndexUid_header_' . $freeIndexUid);
515 $content =
'<h1 class="tx-indexedsearch-category">' . htmlspecialchars($titleString) .
'</h1>' . $content;
517 $accumulatedContent .= $content;
522 return $accumulatedContent;
535 $GLOBALS[
'TT']->push(
'Searching result');
536 if ($hookObj = &$this->
hookRequest(
'getResultRows_SQLpointer')) {
537 $res = $hookObj->getResultRows_SQLpointer($searchWordArray, $freeIndexUid);
545 $totalSearchResultCount = $this->databaseConnection->sql_num_rows($res);
550 $positionInSearchResults = 0;
551 $groupingPhashes = array();
553 $groupingChashes = array();
557 $resultRows = array();
563 $calculateExactCount = (bool)$this->conf[
'search.'][
'exactCount'];
564 $lastResultNumberOnPreviousPage = $currentPageNumber * $this->piVars[
'results'];
565 $firstResultNumberOnNextPage = ($currentPageNumber + 1) * $this->piVars[
'results'];
566 $lastResultNumberToAnalyze = ($currentPageNumber + 1) * $this->piVars[
'results'] + $this->piVars[
'results'];
569 while (
false !== ($row = $this->databaseConnection->sql_fetch_assoc($res))) {
574 $totalSearchResultCount--;
578 if ($positionInSearchResults === 0) {
583 $phashGr = !in_array($row[
'phash_grouping'], $groupingPhashes);
584 $chashGr = !in_array(($row[
'contentHash'] .
'.' . $row[
'data_page_id']), $groupingChashes);
585 if ($phashGr && $chashGr) {
586 if ($row[
'show_resume'] || $this->conf[
'show.'][
'forbiddenRecords']) {
590 $groupingPhashes[] = $row[
'phash_grouping'];
592 $groupingChashes[] = $row[
'contentHash'] .
'.' . $row[
'data_page_id'];
593 $positionInSearchResults++;
595 if ($positionInSearchResults > $lastResultNumberOnPreviousPage && $positionInSearchResults <= $lastResultNumberToAnalyze) {
597 $row[
'result_number'] = $positionInSearchResults;
598 $resultRows[] = $row;
606 $nextResultPosition = $positionInSearchResults + 1;
607 if (!$calculateExactCount && $nextResultPosition > $firstResultNumberOnNextPage) {
613 $totalSearchResultCount--;
619 $totalSearchResultCount--;
622 $this->databaseConnection->sql_free_result($res);
624 'resultRows' => $resultRows,
626 'count' => $totalSearchResultCount
646 $GLOBALS[
'TT']->push(
'execFinalQuery');
668 $GLOBALS[
'TT']->push(
'Display Final result');
670 $this->firstRow = $resData[
'firstRow'];
673 $rowcontent .= $this->
compileResult($resData[
'resultRows'], $freeIndexUid);
675 if ($resData[
'count']) {
676 $this->
internal[
'res_count'] = $resData[
'count'];
677 $this->
internal[
'results_at_a_time'] = $this->piVars[
'results'];
679 $resultSectionsCount = count($this->resultSections);
680 $addString = $resData[
'count'] && $this->piVars[
'group'] ==
'sections' && $freeIndexUid <= 0 ?
' ' . sprintf($this->
pi_getLL(($resultSectionsCount > 1 ?
'inNsections' :
'inNsection')), $resultSectionsCount) :
'';
684 $content = $browseBox1 . $rowcontent . $browseBox2;
686 $content =
'<p' . $this->
pi_classParam(
'noresults') .
'>' . $this->
pi_getLL(
'noResults',
'',
true) .
'</p>';
690 $content .=
'<p' . $this->
pi_classParam(
'noresults') .
'>' . $this->
pi_getLL(
'noResults',
'',
true) .
'</p>';
694 $what =
'<div' . $this->
pi_classParam(
'whatis') .
'>' . $this->cObj->stdWrap($what, $this->conf[
'whatis_stdWrap.']) .
'</div>';
695 $content = $what . $content;
712 $newResultRows = array();
713 foreach ($resultRows as $row) {
714 $id = md5($row[
'phash_grouping']);
715 if (is_array($newResultRows[$id])) {
716 if (!$newResultRows[$id][
'show_resume'] && $row[
'show_resume']) {
719 $subrows = $newResultRows[$id][
'_sub'];
720 unset($newResultRows[$id][
'_sub']);
721 $subrows[] = $newResultRows[$id];
723 $newResultRows[$id] = $row;
724 $newResultRows[$id][
'_sub'] = $subrows;
726 $newResultRows[$id][
'_sub'][] = $row;
729 $newResultRows[$id] = $row;
732 $resultRows = $newResultRows;
733 $this->resultSections = array();
734 if ($freeIndexUid <= 0) {
735 switch ($this->piVars[
'group']) {
737 $rl2flag = substr($this->piVars[
'sections'], 0, 2) ==
'rl';
739 foreach ($resultRows as $row) {
740 $id = $row[
'rl0'] .
'-' . $row[
'rl1'] . ($rl2flag ?
'-' . $row[
'rl2'] :
'');
741 $sections[$id][] = $row;
743 $this->resultSections = array();
744 foreach ($sections as $id => $resultRows) {
745 $rlParts = explode(
'-', $id);
746 $theId = $rlParts[2] ? $rlParts[2] : ($rlParts[1] ? $rlParts[1] : $rlParts[0]);
747 $theRLid = $rlParts[2] ?
'rl2_' . $rlParts[2] : ($rlParts[1] ?
'rl1_' . $rlParts[1] :
'0');
749 if ($sectionName[0] ==
'/') {
750 $sectionName = substr($sectionName, 1);
752 if (!trim($sectionName)) {
753 $sectionTitleLinked = $this->
pi_getLL(
'unnamedSection',
'',
true) .
':';
754 }
elseif ($this->conf[
'linkSectionTitles']) {
757 $sectionTitleLinked =
'<a href="#" onclick="' . htmlspecialchars($onclick) .
'">' . $sectionName .
':</a>';
759 $sectionTitleLinked = $sectionName;
761 $resultRowsCount = count($resultRows);
762 $this->resultSections[$id] = array($sectionName, $resultRowsCount);
764 $content .= $this->
makeSectionHeader($id, $sectionTitleLinked, $resultRowsCount);
767 foreach ($resultRows as $row) {
770 $content .= $this->cObj->stdWrap($resultlist, $this->conf[
'resultlist_stdWrap.']);
776 foreach ($resultRows as $row) {
779 $content .= $this->cObj->stdWrap($resultlist, $this->conf[
'resultlist_stdWrap.']);
783 foreach ($resultRows as $row) {
786 $content .= $this->cObj->stdWrap($resultlist, $this->conf[
'resultlist_stdWrap.']);
788 return '<div' . $this->
pi_classParam(
'res') .
'>' . $content .
'</div>';
803 public function getPhashList(
$sWArr)
807 $totalHashList = array();
810 foreach (
$sWArr as $k => $v) {
812 $sWord = $v[
'sword'];
813 $theType = (string)$this->piVars[
'type'];
814 if (strstr($sWord,
' ')) {
818 $GLOBALS[
'TT']->push(
'SearchWord "' . $sWord .
'" - $theType=' . $theType);
843 $res = $this->
searchMetaphone($indexerObj->metaphone($sWord, $this->storeMetaphoneInfoAsWords));
849 $this->piVars[
'order'] =
'mtime';
859 $phashList = array();
860 while ($row = $this->databaseConnection->sql_fetch_assoc($res)) {
861 $phashList[] = $row[
'phash'];
863 $this->databaseConnection->sql_free_result($res);
866 switch ($v[
'oper']) {
868 $totalHashList = array_unique(array_merge($phashList, $totalHashList));
871 $totalHashList = array_diff($totalHashList, $phashList);
875 $totalHashList = array_intersect($totalHashList, $phashList);
878 $totalHashList = $phashList;
884 return implode(
',', $totalHashList);
896 return $this->databaseConnection->exec_SELECTquery(
'IR.phash',
'index_words IW,
898 index_section ISEC', $wordSel .
'
900 AND ISEC.phash = IR.phash
902 ' . $plusQ,
'IR.phash');
914 $likeWildcard = Utility\LikeWildcard::cast($wildcard);
915 $wSel = $likeWildcard->getLikeQueryPart(
921 $this->wSelClauses[] = $wSel;
934 $wSel =
'IW.wid=' . \TYPO3\CMS\IndexedSearch\Utility\IndexedSearchUtility::md5inthash($sWord);
935 $this->wSelClauses[] = $wSel;
948 $this->wSelClauses[] =
'1=1';
950 $likePart = $likeWildcard->getLikeQueryPart(
956 return $this->databaseConnection->exec_SELECTquery(
'ISEC.phash',
957 'index_section ISEC, index_fulltext IFT',
958 $likePart .
' AND ISEC.phash = IFT.phash' . $this->
sectionTableWhere(),
'ISEC.phash'
970 $wSel =
'IW.metaphone=' . $sWord;
971 $this->wSelClauses[] = $wSel;
982 $out = $this->wholeSiteIdList < 0 ?
'' :
' AND ISEC.rl0 IN (' . $this->wholeSiteIdList .
')';
984 if (substr($this->piVars[
'sections'], 0, 4) ==
'rl1_') {
986 $out .=
' AND ISEC.rl1 IN (' .
$list .
')';
988 }
elseif (substr($this->piVars[
'sections'], 0, 4) ==
'rl2_') {
990 $out .=
' AND ISEC.rl2 IN (' .
$list .
')';
992 }
elseif (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'indexed_search'][
'addRootLineFields'])) {
994 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'indexed_search'][
'addRootLineFields'] as $fieldName => $rootLineLevel) {
995 if (substr($this->piVars[
'sections'], 0, strlen($fieldName) + 1) == $fieldName .
'_') {
997 $out .=
' AND ISEC.' . $fieldName .
' IN (' .
$list .
')';
1005 switch ((
string)$this->piVars[
'sections']) {
1008 $out .=
' AND ISEC.page_id=' . $this->frontendController->id;
1012 $out .=
' AND ISEC.rl2=0';
1016 $out .=
' AND ISEC.rl2>0';
1030 switch ((
string)$this->piVars[
'media']) {
1033 $out =
' AND IP.item_type=' . $this->databaseConnection->fullQuoteStr(
'0',
'index_phash');
1037 $out =
' AND IP.item_type<>' . $this->databaseConnection->fullQuoteStr(
'0',
'index_phash');
1044 $out =
' AND IP.item_type=' . $this->databaseConnection->fullQuoteStr($this->piVars[
'media'],
'index_phash');
1056 $languageWhere =
'';
1057 if ($this->piVars[
'lang'] >= 0) {
1059 $languageWhere =
'AND IP.sys_language_uid=' . (int)$this->piVars[
'lang'];
1061 return $languageWhere;
1072 if ($freeIndexUid < 0) {
1076 $indexCfgRec = $this->databaseConnection->exec_SELECTgetSingleRow(
'indexcfgs',
'index_config',
'type=5 AND uid=' . (
int)$freeIndexUid . $this->cObj->enableFields(
'index_config'));
1077 if (is_array($indexCfgRec)) {
1081 foreach ($refs as $ref) {
1084 case 'index_config':
1085 $idxRec = $this->databaseConnection->exec_SELECTgetSingleRow(
'uid',
'index_config',
'uid=' . (
int)$uid . $this->cObj->enableFields(
'index_config'));
1091 $indexCfgRecordsFromPid = $this->databaseConnection->exec_SELECTgetRows(
'uid',
'index_config',
'pid=' . (
int)$uid . $this->cObj->enableFields(
'index_config'));
1092 foreach ($indexCfgRecordsFromPid as $idxRec) {
1093 $list[] = $idxRec[
'uid'];
1100 $list = array((
int)$freeIndexUid);
1102 return ' AND IP.freeIndexUid IN (' . implode(
',',
$list) .
')';
1118 if ($hookObj = $this->
hookRequest(
'execFinalQuery_idList')) {
1119 $page_where = $hookObj->execFinalQuery_idList(
$list);
1120 }
elseif ($this->join_pages) {
1124 $page_where =
'pages.uid = ISEC.page_id
1125 ' . $this->cObj->enableFields(
'pages') .
'
1126 AND pages.no_search=0
1127 AND pages.doktype<200
1129 }
elseif ($this->wholeSiteIdList >= 0) {
1133 foreach ($siteIdNumbers as $rootId) {
1134 $id_list[] = $this->cObj->getTreeList(-1 * $rootId, 9999);
1136 $page_where =
'ISEC.page_id IN (' . implode(
',', $id_list) .
')';
1139 $page_where =
'1=1';
1144 if (substr($this->piVars[
'order'], 0, 5) ==
'rank_') {
1145 switch ($this->piVars[
'order']) {
1149 $grsel =
'MAX(IR.flags) AS order_val1, SUM(IR.freq) AS order_val2';
1154 $grsel =
'AVG(IR.first) AS order_val';
1159 $grsel =
'SUM(IR.count) AS order_val';
1164 $grsel =
'SUM(IR.freq) AS order_val';
1169 $wordSel =
'(' . implode(
' OR ', $this->wSelClauses) .
') AND ';
1171 $res = $this->databaseConnection->exec_SELECTquery(
1172 'ISEC.*, IP.*, ' . $grsel,
1176 index_phash IP' . $page_join,
1178 'IP.phash IN (' .
$list .
') ' .
1181 AND ISEC.phash = IR.phash
1182 AND IP.phash = IR.phash
1183 AND ' . $page_where,
1184 'IP.phash,ISEC.phash,ISEC.phash_t3,ISEC.rl0,ISEC.rl1,ISEC.rl2 ,ISEC.page_id,ISEC.uniqid,IP.phash_grouping,IP.data_filename ,IP.data_page_id ,IP.data_page_reg1,IP.data_page_type,IP.data_page_mp,IP.gr_list,IP.item_type,IP.item_title,IP.item_description,IP.item_mtime,IP.tstamp,IP.item_size,IP.contentHash,IP.crdate,IP.parsetime,IP.sys_language_uid,IP.item_crdate,IP.cHashParams,IP.externalUrl,IP.recordUid,IP.freeIndexUid,IP.freeIndexSetId',
1190 switch ((
string)$this->piVars[
'order']) {
1201 $res = $this->databaseConnection->exec_SELECTquery(
'ISEC.*, IP.*',
'index_phash IP,index_section ISEC' . $page_join,
'IP.phash IN (' .
$list .
') ' . $this->
mediaTypeWhere() .
' ' . $this->
languageWhere() . $freeIndexUidClause .
'
1202 AND IP.phash = ISEC.phash
1203 AND ' . $page_where,
'IP.phash,ISEC.phash,ISEC.phash_t3,ISEC.rl0,ISEC.rl1,ISEC.rl2 ,ISEC.page_id,ISEC.uniqid,IP.phash_grouping,IP.data_filename ,IP.data_page_id ,IP.data_page_reg1,IP.data_page_type,IP.data_page_mp,IP.gr_list,IP.item_type,IP.item_title,IP.item_description,IP.item_mtime,IP.tstamp,IP.item_size,IP.contentHash,IP.crdate,IP.parsetime,IP.sys_language_uid,IP.item_crdate,IP.cHashParams,IP.externalUrl,IP.recordUid,IP.freeIndexUid,IP.freeIndexSetId', $orderBy);
1220 if ($row[
'freeIndexUid']) {
1224 if ($row[
'item_type']) {
1231 $res = $this->databaseConnection->exec_SELECTquery(
'phash',
'index_grlist',
'phash=' . (
int)$row[
'phash_t3'] .
' AND gr_list=' . $this->databaseConnection->fullQuoteStr($this->frontendController->gr_list,
'index_grlist'));
1235 if ($res && $this->databaseConnection->sql_num_rows($res)) {
1242 if ((
string)$row[
'gr_list'] !== (string)$this->frontendController->gr_list) {
1245 $res = $this->databaseConnection->exec_SELECTquery(
'phash',
'index_grlist',
'phash=' . (
int)$row[
'phash'] .
' AND gr_list=' . $this->databaseConnection->fullQuoteStr($this->frontendController->gr_list,
'index_grlist'));
1249 if ($res && $this->databaseConnection->sql_num_rows($res)) {
1283 $recordExists =
true;
1285 if ($row[
'item_type']) {
1287 if (!is_file($row[
'data_filename']) || !file_exists($row[
'data_filename'])) {
1288 $recordExists =
false;
1291 return $recordExists;
1302 $desc = $this->piVars[
'desc'];
1306 return !$desc ?
' DESC' :
'';
1319 $insertFields = array(
1320 'searchstring' => $this->piVars[
'sword'],
1321 'searchoptions' => serialize(array($this->piVars,
$sWArr, $pt)),
1322 'feuser_id' => (
int)
$GLOBALS[
'TSFE']->user[
'uid'],
1324 'cookie' => (
string)
$GLOBALS[
'TSFE']->
id,
1328 'hits' => (
int)$count,
1332 $this->databaseConnection->exec_INSERTquery(
'index_stat_search', $insertFields);
1333 $newId = $this->databaseConnection->sql_insert_id();
1335 foreach (
$sWArr as $val) {
1336 $insertFields = array(
1337 'word' => $val[
'sword'],
1338 'index_stat_search_id' => $newId,
1341 'pageid' => $this->frontendController->id
1343 $this->databaseConnection->exec_INSERTquery(
'index_stat_word', $insertFields);
1361 $html = $this->cObj->getSubpart($this->templateCode,
'###SEARCH_FORM###');
1363 $substituteArray = array(
'legend',
'searchFor',
'extResume',
'atATime',
'orderBy',
'fromSection',
'searchIn',
'match',
'style',
'freeIndexUid');
1364 foreach ($substituteArray as $marker) {
1367 $markerArray[
'###FORM_SUBMIT###'] = $this->
pi_getLL(
'submit_button_label',
'',
true);
1369 $markerArray[
'###SWORD_VALUE###'] = htmlspecialchars($this->piVars[
'sword']);
1371 if ($this->conf[
'show.'][
'clearSearchBox'] && $this->conf[
'show.'][
'clearSearchBox.'][
'enableSubSearchCheckBox']) {
1372 $markerArray[
'###SWORD_PREV_VALUE###'] = htmlspecialchars($this->conf[
'show.'][
'clearSearchBox'] ?
'' : $this->piVars[
'sword']);
1373 $markerArray[
'###SWORD_PREV_INCLUDE_CHECKED###'] = $this->piVars[
'sword_prev_include'] ?
' checked="checked"' :
'';
1374 $markerArray[
'###ADD_TO_CURRENT_SEARCH###'] = $this->
pi_getLL(
'makerating_addToCurrentSearch',
'',
true);
1376 $html = $this->cObj->substituteSubpart($html,
'###ADDITONAL_KEYWORD###',
'');
1379 $hiddenFieldCode = $this->cObj->getSubpart($this->templateCode,
'###HIDDEN_FIELDS###');
1380 $hiddenFieldCode = preg_replace(
'/^\\n\\t(.+)/ms',
'$1', $hiddenFieldCode);
1382 $hiddenFieldArr = array();
1384 $hiddenFieldMarkerArray = array();
1385 $hiddenFieldMarkerArray[
'###HIDDEN_FIELDNAME###'] = $this->prefixId .
'[' . $fieldName .
']';
1386 $hiddenFieldMarkerArray[
'###HIDDEN_VALUE###'] = htmlspecialchars((
string)$this->piVars[$fieldName]);
1387 $hiddenFieldArr[$fieldName] = $this->cObj->substituteMarkerArrayCached($hiddenFieldCode, $hiddenFieldMarkerArray, array(), array());
1390 if ($this->piVars[
'ext']) {
1392 if (!is_array(
$optValues[
'type']) && !is_array(
$optValues[
'defOp']) || $this->conf[
'blind.'][
'type'] && $this->conf[
'blind.'][
'defOp']) {
1393 $html = $this->cObj->substituteSubpart($html,
'###SELECT_SEARCH_FOR###',
'');
1395 if (is_array(
$optValues[
'type']) && !$this->conf[
'blind.'][
'type']) {
1396 unset($hiddenFieldArr[
'type']);
1399 $html = $this->cObj->substituteSubpart($html,
'###SELECT_SEARCH_TYPE###',
'');
1401 if (is_array(
$optValues[
'defOp']) || !$this->conf[
'blind.'][
'defOp']) {
1404 $html = $this->cObj->substituteSubpart($html,
'###SELECT_SEARCH_DEFOP###',
'');
1408 if (!is_array(
$optValues[
'media']) && !is_array(
$optValues[
'lang']) || $this->conf[
'blind.'][
'media'] && $this->conf[
'blind.'][
'lang']) {
1409 $html = $this->cObj->substituteSubpart($html,
'###SELECT_SEARCH_IN###',
'');
1411 if (is_array(
$optValues[
'media']) && !$this->conf[
'blind.'][
'media']) {
1412 unset($hiddenFieldArr[
'media']);
1415 $html = $this->cObj->substituteSubpart($html,
'###SELECT_SEARCH_MEDIA###',
'');
1417 if (is_array(
$optValues[
'lang']) || !$this->conf[
'blind.'][
'lang']) {
1418 unset($hiddenFieldArr[
'lang']);
1421 $html = $this->cObj->substituteSubpart($html,
'###SELECT_SEARCH_LANG###',
'');
1425 if (!is_array(
$optValues[
'sections']) || $this->conf[
'blind.'][
'sections']) {
1426 $html = $this->cObj->substituteSubpart($html,
'###SELECT_SECTION###',
'');
1431 if (!is_array(
$optValues[
'freeIndexUid']) || $this->conf[
'blind.'][
'freeIndexUid']) {
1432 $html = $this->cObj->substituteSubpart($html,
'###SELECT_FREEINDEXUID###',
'');
1437 if (!is_array(
$optValues[
'order']) || !is_array(
$optValues[
'desc']) || $this->conf[
'blind.'][
'order']) {
1438 $html = $this->cObj->substituteSubpart($html,
'###SELECT_ORDER###',
'');
1440 unset($hiddenFieldArr[
'order']);
1441 unset($hiddenFieldArr[
'desc']);
1442 unset($hiddenFieldArr[
'results']);
1448 if (!is_array(
$optValues[
'results']) || !is_array(
$optValues[
'results']) || $this->conf[
'blind.'][
'results']) {
1449 $html = $this->cObj->substituteSubpart($html,
'###SELECT_RESULTS###',
'');
1454 if (!is_array(
$optValues[
'group']) || $this->conf[
'blind.'][
'group']) {
1455 $html = $this->cObj->substituteSubpart($html,
'###SELECT_GROUP###',
'');
1457 unset($hiddenFieldArr[
'group']);
1460 if ($this->conf[
'blind.'][
'extResume']) {
1461 $html = $this->cObj->substituteSubpart($html,
'###SELECT_EXTRESUME###',
'');
1463 $markerArray[
'###EXT_RESUME_CHECKED###'] = $this->piVars[
'extResume'] ?
' checked="checked"' :
'';
1467 $html = $this->cObj->substituteSubpart($html,
'###SEARCH_FORM_EXTENDED###',
'');
1469 if ($this->conf[
'show.'][
'advancedSearchLink']) {
1470 $linkToOtherMode = $this->piVars[
'ext'] ? $this->
pi_getPageLink($this->frontendController->id, $this->frontendController->sPre) : $this->
pi_getPageLink($this->frontendController->id, $this->frontendController->sPre, array($this->prefixId .
'[ext]' => 1));
1471 $markerArray[
'###LINKTOOTHERMODE###'] =
'<a href="' . htmlspecialchars($linkToOtherMode) .
'">' . $this->
pi_getLL(($this->piVars[
'ext'] ?
'link_regularSearch' :
'link_advancedSearch'),
'',
true) .
'</a>';
1473 $markerArray[
'###LINKTOOTHERMODE###'] =
'';
1476 $html = $this->cObj->substituteSubpart($html,
'###HIDDEN_FIELDS###', implode(
'', $hiddenFieldArr));
1477 $substitutedContent = $this->cObj->substituteMarkerArrayCached($html, $markerArray, array(), array());
1478 return $substitutedContent;
1496 $sel = (string)$k === (
string)$value ?
' selected="selected"' :
'';
1500 $opt[] =
'<option value="' . htmlspecialchars($k) .
'"' . $sel .
'>' . htmlspecialchars($v) .
'</option>';
1502 return implode(
'', $opt);
1512 if (!$this->conf[
'show.'][
'rules']) {
1515 $html = $this->cObj->getSubpart($this->templateCode,
'###RULES###');
1516 $markerArray[
'###RULES_HEADER###'] = $this->
pi_getLL(
'rules_header',
'',
true);
1517 $markerArray[
'###RULES_TEXT###'] = nl2br(trim($this->
pi_getLL(
'rules_text',
'',
true)));
1518 $substitutedContent = $this->cObj->substituteMarkerArrayCached($html, $markerArray, array(), array());
1519 return $this->cObj->stdWrap($substitutedContent, $this->conf[
'rules_stdWrap.']);
1529 if (empty($this->resultSections)) {
1533 $html = $this->cObj->getSubpart($this->templateCode,
'###RESULT_SECTION_LINKS###');
1534 $item = $this->cObj->getSubpart($this->templateCode,
'###RESULT_SECTION_LINKS_LINK###');
1536 foreach ($this->resultSections as $id => $dat) {
1537 $markerArray = array();
1538 $aBegin =
'<a href="' . htmlspecialchars($anchorPrefix .
'#anchor_' . md5($id)) .
'">';
1539 $aContent = (trim($dat[0]) ? trim($dat[0]) : htmlspecialchars($this->
pi_getLL(
'unnamedSection'))) .
' (' . $dat[1] .
' ' . $this->
pi_getLL(($dat[1] > 1 ?
'word_pages' :
'word_page'),
'',
true) .
')';
1541 $markerArray[
'###LINK###'] = $aBegin . $aContent . $aEnd;
1542 $links[] = $this->cObj->substituteMarkerArrayCached($item, $markerArray, array(), array());
1544 $html = $this->cObj->substituteMarkerArrayCached($html, array(
'###LINKS###' => implode(
'', $links)), array(), array());
1545 return '<div' . $this->
pi_classParam(
'sectionlinks') .
'>' . $this->cObj->stdWrap($html, $this->conf[
'sectionlinks_stdWrap.']) .
'</div>';
1558 $html = $this->cObj->getSubpart($this->templateCode,
'###SECTION_HEADER###');
1559 $markerArray[
'###ANCHOR_URL###'] =
'anchor_' . md5($id);
1560 $markerArray[
'###SECTION_TITLE###'] = $sectionTitleLinked;
1561 $markerArray[
'###RESULT_COUNT###'] = $countResultRows;
1562 $markerArray[
'###RESULT_NAME###'] = $this->
pi_getLL(
'word_page' . ($countResultRows > 1 ?
's' :
''));
1563 $substitutedContent = $this->cObj->substituteMarkerArrayCached($html, $markerArray, array(), array());
1564 return $substitutedContent;
1578 if ($hookObj = $this->
hookRequest(
'printResultRow')) {
1579 return $hookObj->printResultRow($row, $headerOnly, $tmplContent);
1581 $html = $this->cObj->getSubpart($this->templateCode,
'###RESULT_OUTPUT###');
1582 if (!is_array($row[
'_sub'])) {
1583 $html = $this->cObj->substituteSubpart($html,
'###ROW_SUB###',
'');
1586 $html = $this->cObj->substituteSubpart($html,
'###ROW_SHORT###',
'');
1587 }
elseif ($headerOnly == 1) {
1588 $html = $this->cObj->substituteSubpart($html,
'###ROW_LONG###',
'');
1589 }
elseif ($headerOnly == 2) {
1590 $html = $this->cObj->substituteSubpart($html,
'###ROW_SHORT###',
'');
1591 $html = $this->cObj->substituteSubpart($html,
'###ROW_LONG###',
'');
1593 if (is_array($tmplContent)) {
1594 foreach ($tmplContent as $k => $v) {
1599 $markerArray[
'###TEXT_ITEM_SIZE###'] = $this->
pi_getLL(
'res_size',
'',
true);
1600 $markerArray[
'###TEXT_ITEM_CRDATE###'] = $this->
pi_getLL(
'res_created',
'',
true);
1601 $markerArray[
'###TEXT_ITEM_MTIME###'] = $this->
pi_getLL(
'res_modified',
'',
true);
1602 $markerArray[
'###TEXT_ITEM_PATH###'] = $this->
pi_getLL(
'res_path',
'',
true);
1603 $html = $this->cObj->substituteMarkerArrayCached($html, $markerArray, array(), array());
1605 if (is_array($row[
'_sub'])) {
1607 $html = str_replace(
'###TEXT_ROW_SUB###', $this->
pi_getLL(
'res_otherMatching',
'',
true), $html);
1608 foreach ($row[
'_sub'] as $subRow) {
1612 $markerArray[
'###TEXT_ROW_SUB###'] = $this->
pi_getLL(
'res_otherMatching',
'',
true);
1613 $html = str_replace(
'###TEXT_ROW_SUB###', $this->
pi_getLL(
'res_otherPageAsWell',
'',
true), $html);
1632 $pointer = (int)$this->piVars[
'pointer'];
1633 $count = (int)$this->
internal[
'res_count'];
1635 $pageCount = (int)ceil($count / $results_at_a_time);
1639 if ($pageCount > 1) {
1645 $links[] =
'<li>' . $this->
makePointerSelector_link($this->
pi_getLL(
'pi_list_browseresults_prev',
'< Previous',
true), $pointer - 1, $freeIndexUid) .
'</li>';
1647 $minPage = $pointer - (int)floor($maxPages / 2);
1648 $maxPage = $minPage + $maxPages - 1;
1651 $maxPage -= $minPage;
1653 }
elseif ($maxPage >= $pageCount) {
1654 $minPage -= $maxPage - $pageCount + 1;
1655 $maxPage = $pageCount - 1;
1657 $pageLabel = $this->
pi_getLL(
'pi_list_browseresults_page',
'Page',
true);
1658 for ($a = $minPage; $a <= $maxPage; $a++) {
1659 $label = trim($pageLabel .
' ' . ($a + 1));
1661 if ($a === $pointer) {
1662 $links[] =
'<li' . $this->
pi_classParam(
'browselist-currentPage') .
'><strong>' . $link .
'</strong></li>';
1664 $links[] =
'<li>' . $link .
'</li>';
1667 if ($pointer + 1 < $pageCount) {
1671 if (!empty($links)) {
1673 <ul class="browsebox">
1674 ' . implode(
'', $links) .
'
1677 $label = str_replace(
1678 array(
'###TAG_BEGIN###',
'###TAG_END###'),
1679 array(
'<strong>',
'</strong>'),
1680 $this->
pi_getLL(
'pi_list_browseresults_display',
'Displaying results ###TAG_BEGIN###%1$s to %2$s###TAG_END### out of ###TAG_BEGIN###%3$s###TAG_END###')
1682 $resultsFrom = $pointer * $results_at_a_time + 1;
1683 $resultsTo = min($resultsFrom + $results_at_a_time - 1, $count);
1684 $resultCountText =
'';
1685 if ($showResultCount) {
1686 $resultCountText =
'<p>' . sprintf($label, $resultsFrom, $resultsTo, $count) . $addString .
'</p>';
1690 . $addPart .
'</div>';
1710 $CSSsuffix = $specRowConf[
'CSSsuffix'] ?
'-' . $specRowConf[
'CSSsuffix'] :
'';
1712 if ($row[
'item_type']) {
1714 if ($row[
'show_resume']) {
1716 $targetAttribute =
'';
1717 if ($this->frontendController->config[
'config'][
'fileTarget']) {
1718 $targetAttribute =
' target="' . htmlspecialchars($this->frontendController->config[
'config'][
'fileTarget']) .
'"';
1720 $title =
'<a href="' . htmlspecialchars($row[
'data_filename']) .
'"' . $targetAttribute .
'>' . htmlspecialchars($this->
makeTitle($row)) .
'</a>';
1724 unset($copy_row[
'cHashParams']);
1725 $title = $this->
linkPage($row[
'page_id'], htmlspecialchars($this->
makeTitle($row)), $copy_row);
1730 if ($this->conf[
'forwardSearchWordsInResultLink']) {
1731 if ($this->conf[
'forwardSearchWordsInResultLink.'][
'no_cache']) {
1732 $markUpSwParams = array(
'no_cache' => 1);
1734 $markUpSwParams = array();
1736 foreach ($this->sWArr as $d) {
1737 $markUpSwParams[
'sword_list'][] = $d[
'sword'];
1740 $markUpSwParams = array();
1742 $title = $this->
linkPage($row[
'data_page_id'], htmlspecialchars($this->
makeTitle($row)), $row, $markUpSwParams);
1744 $tmplContent = array();
1745 $tmplContent[
'title'] = $title;
1746 $tmplContent[
'result_number'] = $this->conf[
'show.'][
'resultNumber'] ? $row[
'result_number'] .
': ' :
' ';
1747 $tmplContent[
'icon'] = $this->
makeItemTypeIcon($row[
'item_type'],
'', $specRowConf);
1748 $tmplContent[
'rating'] = $this->
makeRating($row);
1751 !($this->piVars[
'extResume'] && !$headerOnly),
1752 $this->conf[
'results.'][
'summaryCropAfter']
1754 $tmplContent = $this->
makeInfo($row, $tmplContent);
1757 $tmplContent[
'CSSsuffix'] = $CSSsuffix;
1759 if ($hookObj = $this->
hookRequest(
'prepareResultRowTemplateData_postProc')) {
1760 $tmplContent = $hookObj->prepareResultRowTemplateData_postProc($tmplContent, $row, $headerOnly);
1762 return $tmplContent;
1777 foreach (
$sWArr as $k => $v) {
1779 switch ($v[
'oper']) {
1795 return $searchingFor;
1806 return '"<span' . $this->
pi_classParam(
'sw') .
'>' . htmlspecialchars($str) .
'</span>"';
1823 $sel = (string)$k === (
string)$value ?
' selected="selected"' :
'';
1827 $opt[] =
'<option value="' . htmlspecialchars($k) .
'"' . $sel .
'>' . htmlspecialchars($v) .
'</option>';
1829 return '<select name="' . $name .
'">' . implode(
'', $opt) .
'</select>';
1844 $onclick =
'document.getElementById(\'' . $this->prefixId .
'_pointer\').value=\'' . $p .
'\';
' . 'document.getElementById(\
'' . $this->prefixId .
'_freeIndexUid\').value=\'' . rawurlencode($freeIndexUid) .
'\';
' . 'document.getElementById(\
'' . $this->prefixId .
'\').submit();
return false;
';
1845 return '<a href=
"#" onclick=
"' . htmlspecialchars($onclick) . '">
' . $str . '</a>
';
1856 public function makeItemTypeIcon($it, $alt = '', $specRowConf)
1858 // Build compound key if item type is 0, iconRendering is not used
1859 // and specConfs.[pid].pageIcon was set in TS
1860 if ($it === '0
' && $specRowConf['_pid
'] && is_array($specRowConf['pageIcon.
']) && !is_array($this->conf['iconRendering.
'])) {
1861 $it .= ':
' . $specRowConf['_pid
'];
1863 if (!isset($this->iconFileNameCache[$it])) {
1864 $this->iconFileNameCache[$it] = '';
1865 // If TypoScript is used to render the icon:
1866 if (is_array($this->conf['iconRendering.
'])) {
1867 $this->cObj->setCurrentVal($it);
1868 $this->iconFileNameCache[$it] = $this->cObj->cObjGetSingle($this->conf['iconRendering
'], $this->conf['iconRendering.
']);
1870 // Default creation / finding of icon:
1872 if ($it === '0
' || substr($it, 0, 2) == '0:
') {
1873 if (is_array($specRowConf['pageIcon.
'])) {
1874 $this->iconFileNameCache[$it] = $this->cObj->cObjGetSingle('IMAGE
', $specRowConf['pageIcon.
']);
1876 $icon = 'EXT:indexed_search/Resources/Public/Icons/FileTypes/pages.gif
';
1878 } elseif ($this->external_parsers[$it]) {
1879 $icon = $this->external_parsers[$it]->getIcon($it);
1882 $fullPath = GeneralUtility::getFileAbsFileName($icon);
1884 $info = @getimagesize($fullPath);
1885 $iconPath = \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($fullPath);
1886 $this->iconFileNameCache[$it] = is_array($info) ? '<img src=
"' . $iconPath . '" ' . $info[3] . ' title=
"' . htmlspecialchars($alt) . '" alt=
"" />
' : '';
1891 return $this->iconFileNameCache[$it];
1900 public function makeRating($row)
1902 switch ((string)$this->piVars['order
']) {
1904 // Number of occurencies on page
1905 return $row['order_val
'] . ' ' . $this->pi_getLL('maketitle_matches
');
1908 // Close to top of page
1909 return ceil(MathUtility::forceIntegerInRange((255 - $row['order_val
']), 1, 255) / 255 * 100) . '%
';
1912 // Based on priority assigned to <title> / <meta-keywords> / <meta-description> / <body>
1913 if ($this->firstRow['order_val2
']) {
1914 $base = $row['order_val1
'] * 256;
1915 // (3 MSB bit, 224 is highest value of order_val1 currently)
1916 $freqNumber = $row['order_val2
'] / $this->firstRow['order_val2
'] * pow(2, 12);
1918 $total = MathUtility::forceIntegerInRange($base + $freqNumber, 0, 32767);
1919 return ceil(log($total) / log(32767) * 100) . '%
';
1923 // Based on frequency
1925 $total = MathUtility::forceIntegerInRange($row['order_val
'], 0, $max);
1926 return ceil(log($total) / log($max) * 100) . '%
';
1929 // Based on creation date
1930 return $this->cObj->calcAge($GLOBALS['EXEC_TIME
'] - $row['item_crdate
'], 0);
1933 // Based on modification time
1934 return $this->cObj->calcAge($GLOBALS['EXEC_TIME
'] - $row['item_mtime
'], 0);
1950 public function makeDescription($row, $noMarkup = false, $lgd = 180)
1952 if ($row['show_resume
']) {
1956 if (\TYPO3\CMS\IndexedSearch\Utility\IndexedSearchUtility::isTableUsed('index_fulltext
')) {
1957 $res = $this->databaseConnection->exec_SELECTquery('*
', 'index_fulltext
', 'phash=
' . (int)$row['phash
']);
1962 if ($ftdrow = $this->databaseConnection->sql_fetch_assoc($res)) {
1963 // Cut HTTP references after some length
1964 $content = preg_replace('/(http:\\/\\/[^ ]{
' . $this->conf['results.
']['hrefInSummaryCropAfter
'] . '})([^ ]+)/i
', '$1...
', $ftdrow['fulltextdata
']);
1965 $markedSW = $this->markupSWpartsOfString($content);
1967 $this->databaseConnection->sql_free_result($res);
1970 if (!trim($markedSW)) {
1971 $outputStr = $this->frontendController->csConvObj->crop('utf-8
', $row['item_description
'], $lgd, $this->conf['results.
']['summaryCropSignifier
']);
1972 $outputStr = htmlspecialchars($outputStr);
1974 $output = $this->utf8_to_currentCharset($outputStr ?: $markedSW);
1976 $output = '<span
class=
"noResume">
' . $this->pi_getLL('res_noResume
', '', true) . '</span>
';
1987 public function markupSWpartsOfString($str)
1989 $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
1991 $str = str_replace('
', ' ', $htmlParser->bidir_htmlspecialchars($str, -1));
1992 $str = preg_replace('/\\s\\s+/
', ' ', $str);
1993 $swForReg = array();
1994 // Prepare search words for regex:
1995 foreach ($this->sWArr as $d) {
1996 $swForReg[] = preg_quote($d['sword
'], '/
');
1998 $regExString = '(
' . implode('|
', $swForReg) . ')
';
1999 // Split and combine:
2000 $parts = preg_split('/
' . $regExString . '/ui
', ' ' . $str . ' ', 20000, PREG_SPLIT_DELIM_CAPTURE);
2002 $summaryMax = $this->conf['results.
']['markupSW_summaryMax
'];
2003 $postPreLgd = $this->conf['results.
']['markupSW_postPreLgd
'];
2004 $postPreLgd_offset = $this->conf['results.
']['markupSW_postPreLgd_offset
'];
2005 $divider = $this->conf['results.
']['markupSW_divider
'];
2006 $occurencies = (count($parts) - 1) / 2;
2008 $postPreLgd = MathUtility::forceIntegerInRange($summaryMax / $occurencies, $postPreLgd, $summaryMax / 2);
2013 // Shorten in-between strings:
2014 foreach ($parts as $k => $strP) {
2016 // Find length of the summary part:
2017 $strLen = $this->frontendController->csConvObj->strlen('utf-8
', $parts[$k]);
2018 $output[$k] = $parts[$k];
2019 // Possibly shorten string:
2021 // First entry at all (only cropped on the frontside)
2022 if ($strLen > $postPreLgd) {
2023 $output[$k] = $divider . preg_replace('/^[^[:space:]]+[[:space:]]/
', '', $this->frontendController->csConvObj->crop('utf-8
', $parts[$k], -($postPreLgd - $postPreLgd_offset)));
2025 } elseif ($summaryLgd > $summaryMax || !isset($parts[($k + 1)])) {
2026 // In case summary length is exceed OR if there are no more entries at all:
2027 if ($strLen > $postPreLgd) {
2028 $output[$k] = preg_replace('/[[:space:]][^[:space:]]+$/
', '', $this->frontendController->csConvObj->crop('utf-8
', $parts[$k], ($postPreLgd - $postPreLgd_offset))) . $divider;
2031 // In-between search words:
2032 if ($strLen > $postPreLgd * 2) {
2033 $output[$k] = preg_replace('/[[:space:]][^[:space:]]+$/
', '', $this->frontendController->csConvObj->crop('utf-8
', $parts[$k], ($postPreLgd - $postPreLgd_offset))) . $divider . preg_replace('/^[^[:space:]]+[[:space:]]/
', '', $this->frontendController->csConvObj->crop('utf-8
', $parts[$k], -($postPreLgd - $postPreLgd_offset)));
2036 $summaryLgd += $this->frontendController->csConvObj->strlen('utf-8
', $output[$k]);
2038 $output[$k] = htmlspecialchars($output[$k]);
2039 // If summary lgd is exceed, break the process:
2040 if ($summaryLgd > $summaryMax) {
2044 $summaryLgd += $this->frontendController->csConvObj->strlen('utf-8
', $strP);
2045 $output[$k] = '<strong
class=
"tx-indexedsearch-redMarkup">
' . htmlspecialchars($parts[$k]) . '</strong>
';
2049 return implode('', $output);
2058 public function makeTitle($row)
2061 if ($this->multiplePagesType($row['item_type
'])) {
2062 $dat = unserialize($row['cHashParams
']);
2063 $pp = explode('-
', $dat['key
']);
2064 if ($pp[0] != $pp[1]) {
2065 $add = ',
' . $this->pi_getLL('word_pages
') . ' ' . $dat['key
'];
2067 $add = ',
' . $this->pi_getLL('word_page
') . ' ' . $pp[0];
2070 $outputString = $this->frontendController->csConvObj->crop('utf-8
', $row['item_title
'], $this->conf['results.
']['titleCropAfter
'], $this->conf['results.
']['titleCropSignifier
']);
2071 return $this->utf8_to_currentCharset($outputString) . $add;
2081 public function makeInfo($row, $tmplArray)
2083 $tmplArray['size
'] = GeneralUtility::formatSize($row['item_size
']);
2084 $tmplArray['created
'] = $this->formatCreatedDate($row['item_crdate
']);
2085 $tmplArray['modified
'] = $this->formatModifiedDate($row['item_mtime
']);
2086 $pathId = $row['data_page_id
'] ?: $row['page_id
'];
2087 $pathMP = $row['data_page_id
'] ? $row['data_page_mp
'] : '';
2088 $pI = parse_url($row['data_filename
']);
2089 if ($pI['scheme
']) {
2090 $targetAttribute = '';
2091 if ($this->frontendController->config['config
']['fileTarget
']) {
2092 $targetAttribute = ' target=
"' . htmlspecialchars($this->frontendController->config['config']['fileTarget']) . '"';
2094 $tmplArray['path'] = '<a href=
"' . htmlspecialchars($row['data_filename']) . '"' . $targetAttribute . '>
' . htmlspecialchars($row['data_filename
']) . '</a>
';
2096 $pathStr = $this->getPathFromPageId($pathId, $pathMP);
2097 $tmplArray['path'] = $this->linkPage($pathId, $pathStr, array(
2098 'cHashParams
' => $row['cHashParams
'],
2099 'data_page_type
' => $row['data_page_type
'],
2100 'data_page_mp
' => $pathMP,
2101 'sys_language_uid
' => $row['sys_language_uid
']
2113 public function getSpecialConfigForRow($row)
2115 $pathId = $row['data_page_id
'] ?: $row['page_id
'];
2116 $pathMP = $row['data_page_id
'] ? $row['data_page_mp
'] : '';
2117 $rl = $this->getRootLine($pathId, $pathMP);
2118 $specConf = $this->conf['specConfs.
']['0.
'];
2119 if (is_array($rl)) {
2120 foreach ($rl as $dat) {
2121 if (is_array($this->conf['specConfs.
'][$dat['uid
'] . '.
'])) {
2122 $specConf = $this->conf['specConfs.
'][$dat['uid
'] . '.
'];
2123 $specConf['_pid
'] = $dat['uid
'];
2137 public function makeLanguageIndication($row)
2139 // If search result is a TYPO3 page:
2140 if ((string)$row['item_type
'] === '0
') {
2141 // If TypoScript is used to render the flag:
2142 if (is_array($this->conf['flagRendering.
'])) {
2143 $this->cObj->setCurrentVal($row['sys_language_uid
']);
2144 return $this->cObj->cObjGetSingle($this->conf['flagRendering
'], $this->conf['flagRendering.
']);
2157 public function makeAccessIndication($id)
2159 if (is_array($this->fe_groups_required[$id]) && !empty($this->fe_groups_required[$id])) {
2160 return '<img src=
"' . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath('indexed_search') . 'Resources/Public/Icons/FileTypes/locked.gif" width=
"12" height=
"15" vspace=
"5" title=
"' . sprintf($this->pi_getLL('res_memberGroups', '', true), implode(',', array_unique($this->fe_groups_required[$id]))) . '" alt=
"" />
';
2175 public function linkPage($id, $str, $row = array(), $markUpSwParams = array())
2177 // Parameters for link:
2178 $urlParameters = (array)unserialize($row['cHashParams
']);
2179 // Add &type and &MP variable:
2180 if ($row['data_page_type
']) {
2181 $urlParameters['type
'] = $row['data_page_type
'];
2183 if ($row['data_page_mp
']) {
2184 $urlParameters['MP
'] = $row['data_page_mp
'];
2186 if ($row['sys_language_uid
']) {
2187 $urlParameters['L
'] = $row['sys_language_uid
'];
2190 $urlParameters = array_merge($urlParameters, $markUpSwParams);
2191 // This will make sure that the path is retrieved if it hasn't been already. Used only
for the sake of the domain_record thing...
2192 if (!is_array($this->domain_records[$id])) {
2196 if (!empty($this->domain_records[$id])) {
2197 reset($this->domain_records[$id]);
2198 $firstDom = current($this->domain_records[$id]);
2201 if (is_array($urlParameters) && !empty($urlParameters)) {
2204 if ($target = $this->conf[
'search.'][
'detect_sys_domain_records.'][
'target']) {
2205 $target =
' target="' . $target .
'"';
2207 return '<a href="' . htmlspecialchars(($scheme . $firstDom .
'/index.php?id=' . $id . $addParams)) .
'"' . $target .
'>' . htmlspecialchars($str) .
'</a>';
2209 return $this->
pi_linkToPage($str, $id, $this->conf[
'result_link_target'], $urlParameters);
2222 $identStr = $id .
'|' . $pathMP;
2223 if (!isset($this->cache_path[$identStr])) {
2224 $this->cache_rl[$identStr] = $this->frontendController->sys_page->getRootLine($id, $pathMP);
2226 return $this->cache_rl[$identStr];
2237 $res = $this->databaseConnection->exec_SELECTquery(
'domainName',
'sys_domain',
'pid=' . (
int)$id . $this->cObj->enableFields(
'sys_domain'),
'',
'sorting');
2238 $row = $this->databaseConnection->sql_fetch_assoc($res);
2239 return rtrim($row[
'domainName'],
'/');
2251 $identStr = $id .
'|' . $pathMP;
2252 if (!isset($this->cache_path[$identStr])) {
2253 $this->fe_groups_required[$id] = array();
2254 $this->domain_records[$id] = array();
2257 $pageCount = count($rl);
2258 if (is_array($rl) && !empty($rl)) {
2260 $breadcrumbWrap = isset($this->conf[
'breadcrumbWrap']) ? $this->conf[
'breadcrumbWrap'] :
'/';
2261 $breadcrumbWraps =
$GLOBALS[
'TSFE']->tmpl->splitConfArray(array(
'wrap' => $breadcrumbWrap), $pageCount);
2262 foreach ($rl as $k => $v) {
2264 if ($v[
'fe_group'] && ($v[
'uid'] == $id || $v[
'extendToSubpages'])) {
2265 $this->fe_groups_required[$id][] = $v[
'fe_group'];
2268 if ($this->conf[
'search.'][
'detect_sys_domain_records']) {
2271 $this->domain_records[$id][] = $sysDName;
2273 $path = $sysDName . $path;
2278 if ($v[
'uid'] == $this->frontendController->config[
'rootLine'][0][
'uid']) {
2279 array_pop($breadcrumbWraps);
2282 $path = $this->cObj->wrap(htmlspecialchars($v[
'title']), array_pop($breadcrumbWraps)[
'wrap']) . $path;
2285 $this->cache_path[$identStr] = $path;
2286 if (is_array($this->conf[
'path_stdWrap.'])) {
2287 $this->cache_path[$identStr] = $this->cObj->stdWrap($this->cache_path[$identStr], $this->conf[
'path_stdWrap.']);
2290 return $this->cache_path[$identStr];
2301 if ($this->conf[
'show.'][
'LxALLtypes']) {
2303 $res = $this->databaseConnection->exec_SELECTquery(
'title,uid',
'pages',
'pid=' . (
int)$id . $this->cObj->enableFields(
'pages'),
'',
'sorting');
2304 while ($row = $this->databaseConnection->sql_fetch_assoc($res)) {
2305 $output[$row[
'uid']] = $this->frontendController->sys_page->getPageOverlay($row);
2307 $this->databaseConnection->sql_free_result($res);
2310 return $this->frontendController->sys_page->getMenu($id);
2322 return is_object($this->external_parsers[$item_type]) && $this->external_parsers[$item_type]->isMultiplePageExtension($item_type);
2333 return $this->frontendController->csConv($str,
'utf-8');
2345 if (
$GLOBALS[
'TYPO3_CONF_VARS'][
'EXTCONF'][
'indexed_search'][
'pi1_hooks'][$functionName]) {
2347 if (method_exists($hookObj, $functionName)) {
2348 $hookObj->pObj = $this;
2362 if ($targetUrlPid == 0) {
2363 $targetUrlPid = $this->frontendController->id;
2365 return $this->
pi_getPageLink($targetUrlPid, $this->frontendController->sPre);
2376 if (isset($this->conf[
'search.'][
'targetPid']) || isset($this->conf[
'search.'][
'targetPid.'])) {
2377 if (is_array($this->conf[
'search.'][
'targetPid.'])) {
2378 $result = $this->cObj->stdWrap($this->conf[
'search.'][
'targetPid'], $this->conf[
'search.'][
'targetPid.']);
2380 $result = $this->conf[
'search.'][
'targetPid'];
2382 $result = (int)$result;
2395 $defaultFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'];
2396 return $this->
formatDate($date,
'created', $defaultFormat);
2407 $defaultFormat =
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'ddmmyy'] .
' ' .
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'hhmm'];
2408 return $this->
formatDate($date,
'modified', $defaultFormat);
2422 $strftimeFormat = $this->conf[
'dateFormat.'][$tsKey];
2423 if ($strftimeFormat) {
2424 $result = strftime($strftimeFormat, $date);
2426 $result = date($defaultFormat, $date);
2439 return (
int)$this->piVars[
'type'];
2449 return \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(
',', $this->wholeSiteIdList);
2468 if (!is_array($this->conf[
'results.'])) {
2469 $this->conf[
'results.'] = array();
2472 $this->cObj->stdWrap($this->conf[
'results.'][
'summaryCropAfter'], $this->conf[
'results.'][
'summaryCropAfter.']),
2475 $this->conf[
'results.'][
'summaryCropSignifier'] = $this->cObj->stdWrap($this->conf[
'results.'][
'summaryCropSignifier'], $this->conf[
'results.'][
'summaryCropSignifier.']);
2477 $this->cObj->stdWrap($this->conf[
'results.'][
'titleCropAfter'], $this->conf[
'results.'][
'titleCropAfter.']),
2480 $this->conf[
'results.'][
'titleCropSignifier'] = $this->cObj->stdWrap($this->conf[
'results.'][
'titleCropSignifier'], $this->conf[
'results.'][
'titleCropSignifier.']);
2482 $this->cObj->stdWrap($this->conf[
'results.'][
'markupSW_summaryMax'], $this->conf[
'results.'][
'markupSW_summaryMax.']),
2486 $this->cObj->stdWrap($this->conf[
'results.'][
'markupSW_postPreLgd'], $this->conf[
'results.'][
'markupSW_postPreLgd.']),
2490 $this->cObj->stdWrap($this->conf[
'results.'][
'markupSW_postPreLgd_offset'], $this->conf[
'results.'][
'markupSW_postPreLgd_offset.']),
2493 $this->conf[
'results.'][
'markupSW_divider'] = $this->cObj->stdWrap($this->conf[
'results.'][
'markupSW_divider'], $this->conf[
'results.'][
'markupSW_divider.']);
2495 $this->cObj->stdWrap($this->conf[
'results.'][
'hrefInSummaryCropAfter'], $this->conf[
'results.'][
'hrefInSummaryCropAfter.']),
2498 $this->conf[
'results.'][
'hrefInSummaryCropSignifier'] = $this->cObj->stdWrap($this->conf[
'results.'][
'hrefInSummaryCropSignifier'], $this->conf[
'results.'][
'hrefInSummaryCropSignifier.']);