00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00106 require_once(PATH_tslib.'class.tslib_pibase.php');
00107 require_once(PATH_tslib.'class.tslib_search.php');
00108 require_once(t3lib_extMgm::extPath('indexed_search').'class.indexer.php');
00109
00110
00121 class tx_indexedsearch extends tslib_pibase {
00122 var $prefixId = 'tx_indexedsearch';
00123 var $scriptRelPath = 'pi/class.tx_indexedsearch.php';
00124 var $extKey = 'indexed_search';
00125
00126 var $join_pages = 0;
00127 var $defaultResultNumber = 20;
00128
00129 var $operator_translate_table = Array (
00130 Array ('+' , 'AND'),
00131 Array ('|' , 'OR'),
00132 Array ('-' , 'AND NOT'),
00133
00134 # Array ('AND' , 'AND'),
00135 # Array ('OR' , 'OR'),
00136 # Array ('NOT' , 'AND NOT'),
00137 );
00138
00139
00140 var $wholeSiteIdList = 0;
00141
00142
00143 var $sWArr = array();
00144 var $optValues = array();
00145 var $firstRow = Array();
00146
00147 var $cache_path = array();
00148 var $cache_rl = array();
00149 var $fe_groups_required = array();
00150 var $domain_records = array();
00151 var $wSelClauses = array();
00152 var $resultSections = array();
00153 var $external_parsers = array();
00154 var $iconFileNameCache = array();
00155 var $lexerObj;
00156
00157
00165 function main($content, $conf) {
00166
00167
00168 $this->conf = $conf;
00169 $this->pi_loadLL();
00170 $this->pi_setPiVarDefaults();
00171
00172
00173 $this->indexerObj = t3lib_div::makeInstance('tx_indexedsearch_indexer');
00174
00175
00176 $this->initialize();
00177
00178
00179
00180 if (is_array($this->sWArr)) {
00181 $content = $this->doSearch($this->sWArr);
00182 }
00183
00184
00185 $content=
00186 $this->makeSearchForm($this->optValues).
00187 $this->printRules().
00188 $content;
00189
00190 return $this->pi_wrapInBaseClass($content);
00191 }
00192
00198 function initialize() {
00199 global $TYPO3_CONF_VARS;
00200
00201
00202 if (is_array($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['external_parsers'])) {
00203 foreach($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['external_parsers'] as $extension => $_objRef) {
00204 $this->external_parsers[$extension] = &t3lib_div::getUserObj($_objRef);
00205
00206
00207 if (!$this->external_parsers[$extension]->softInit($extension)) {
00208 unset($this->external_parsers[$extension]);
00209 }
00210 }
00211 }
00212
00213
00214 $lexerObjRef = $TYPO3_CONF_VARS['EXTCONF']['indexed_search']['lexer'] ?
00215 $TYPO3_CONF_VARS['EXTCONF']['indexed_search']['lexer'] :
00216 'EXT:indexed_search/class.lexer.php:&tx_indexedsearch_lexer';
00217 $this->lexerObj = &t3lib_div::getUserObj($lexerObjRef);
00218
00219
00220 if ($this->piVars['_sections']) $this->piVars['sections'] = $this->piVars['_sections'];
00221
00222
00223 if ($this->piVars['sword_prev_include'] && $this->piVars['sword_prev']) {
00224 $this->piVars['sword'] = trim($this->piVars['sword_prev']).' '.$this->piVars['sword'];
00225 }
00226
00227 $this->piVars['results'] = t3lib_div::intInRange($this->piVars['results'],1,100000,$this->defaultResultNumber);
00228
00229
00230 $this->optValues = Array(
00231 'type' => Array(
00232 '0' => $this->pi_getLL('opt_type_0'),
00233 '1' => $this->pi_getLL('opt_type_1'),
00234 '2' => $this->pi_getLL('opt_type_2'),
00235 '3' => $this->pi_getLL('opt_type_3'),
00236 '10' => $this->pi_getLL('opt_type_10'),
00237 '20' => $this->pi_getLL('opt_type_20'),
00238 ),
00239 'defOp' => Array(
00240 '0' => $this->pi_getLL('opt_defOp_0'),
00241 '1' => $this->pi_getLL('opt_defOp_1'),
00242 ),
00243 'sections' => Array(
00244 '0' => $this->pi_getLL('opt_sections_0'),
00245 '-1' => $this->pi_getLL('opt_sections_-1'),
00246 '-2' => $this->pi_getLL('opt_sections_-2'),
00247 '-3' => $this->pi_getLL('opt_sections_-3'),
00248
00249 ),
00250 'media' => Array(
00251 '-1' => $this->pi_getLL('opt_media_-1'),
00252 '0' => $this->pi_getLL('opt_media_0'),
00253 '-2' => $this->pi_getLL('opt_media_-2'),
00254 ),
00255 'order' => Array(
00256 'rank_flag' => $this->pi_getLL('opt_order_rank_flag'),
00257 'rank_freq' => $this->pi_getLL('opt_order_rank_freq'),
00258 'rank_first' => $this->pi_getLL('opt_order_rank_first'),
00259 'rank_count' => $this->pi_getLL('opt_order_rank_count'),
00260 'mtime' => $this->pi_getLL('opt_order_mtime'),
00261 'title' => $this->pi_getLL('opt_order_title'),
00262 'crdate' => $this->pi_getLL('opt_order_crdate'),
00263 ),
00264 'group' => Array (
00265 'sections' => $this->pi_getLL('opt_group_sections'),
00266 'flat' => $this->pi_getLL('opt_group_flat'),
00267 ),
00268 'lang' => Array (
00269 -1 => $this->pi_getLL('opt_lang_-1'),
00270 0 => $this->pi_getLL('opt_lang_0'),
00271 ),
00272 'desc' => Array (
00273 '0' => $this->pi_getLL('opt_desc_0'),
00274 '1' => $this->pi_getLL('opt_desc_1'),
00275 ),
00276 'results' => Array (
00277 '10' => '10',
00278 '20' => '20',
00279 '50' => '50',
00280 '100' => '100',
00281 )
00282 );
00283
00284
00285 foreach($this->external_parsers as $extension => $obj) {
00286 if ($name = $obj->searchTypeMediaTitle($extension)) {
00287 $this->optValues['media'][$extension] = $this->pi_getLL('opt_sections_'.$extension,$name);
00288 }
00289 }
00290
00291
00292
00293 $this->operator_translate_table[] = Array($GLOBALS['TSFE']->csConvObj->conv_case('utf-8',$GLOBALS['TSFE']->csConvObj->utf8_encode($this->pi_getLL('local_operator_AND'), $GLOBALS['TSFE']->renderCharset),'toLower') , 'AND');
00294 $this->operator_translate_table[] = Array($GLOBALS['TSFE']->csConvObj->conv_case('utf-8',$GLOBALS['TSFE']->csConvObj->utf8_encode($this->pi_getLL('local_operator_OR'), $GLOBALS['TSFE']->renderCharset),'toLower') , 'OR');
00295 $this->operator_translate_table[] = Array($GLOBALS['TSFE']->csConvObj->conv_case('utf-8',$GLOBALS['TSFE']->csConvObj->utf8_encode($this->pi_getLL('local_operator_NOT'), $GLOBALS['TSFE']->renderCharset),'toLower') , 'AND NOT');
00296
00297
00298 $this->wholeSiteIdList = intval($GLOBALS['TSFE']->config['rootLine'][0]['uid']);
00299
00300
00301
00302 if ($this->conf['show.']['L1sections']) {
00303 $firstLevelMenu = $this->getMenu($this->wholeSiteIdList);
00304 while(list($kk,$mR) = each($firstLevelMenu)) {
00305 if ($mR['doktype']!=5) {
00306 $this->optValues['sections']['rl1_'.$mR['uid']] = trim($this->pi_getLL('opt_RL1').' '.$mR['title']);
00307 if ($this->conf['show.']['L2sections']) {
00308 $secondLevelMenu = $this->getMenu($mR['uid']);
00309 while(list($kk2,$mR2) = each($secondLevelMenu)) {
00310 if ($mR['doktype']!=5) {
00311 $this->optValues['sections']['rl2_'.$mR2['uid']] = trim($this->pi_getLL('opt_RL2').' '.$mR2['title']);
00312 } else unset($secondLevelMenu[$kk2]);
00313 }
00314 $this->optValues['sections']['rl2_'.implode(',',array_keys($secondLevelMenu))] = $this->pi_getLL('opt_RL2ALL');
00315 }
00316 } else unset($firstLevelMenu[$kk]);
00317 }
00318 $this->optValues['sections']['rl1_'.implode(',',array_keys($firstLevelMenu))] = $this->pi_getLL('opt_RL1ALL');
00319 }
00320
00321
00322
00323 if ($this->conf['search.']['rootPidList']) {
00324 $this->wholeSiteIdList = implode(',',t3lib_div::intExplode(',',$this->conf['search.']['rootPidList']));
00325 }
00326
00327
00328 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_language', '1=1'.$this->cObj->enableFields('sys_language'));
00329 while($lR = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00330 $this->optValues['lang'][$lR['uid']] = $lR['title'];
00331 }
00332
00333
00334 if ($hookObj = &$this->hookRequest('initialize_postProc')) {
00335 $hookObj->initialize_postProc();
00336 }
00337
00338
00339
00340 foreach($this->optValues as $kk => $vv) {
00341 if (!isset($this->piVars[$kk])) {
00342 reset($vv);
00343 $this->piVars[$kk] = key($vv);
00344 }
00345 }
00346
00347
00348 if (is_array($this->conf['blind.'])) {
00349 foreach($this->conf['blind.'] as $kk => $vv) {
00350 if (is_array($vv)) {
00351 foreach($vv as $kkk => $vvv) {
00352 if (!is_array($vvv) && $vvv && is_array($this->optValues[substr($kk,0,-1)])) {
00353 unset($this->optValues[substr($kk,0,-1)][$kkk]);
00354 }
00355 }
00356 } elseif ($vv) {
00357 unset($this->optValues[$kk]);
00358 }
00359 }
00360 }
00361
00362
00363 $this->sWArr = $this->getSearchWords($this->piVars['defOp']);
00364 }
00365
00381 function getSearchWords($defOp) {
00382
00383 $inSW = substr($this->piVars['sword'],0,200);
00384
00385
00386 $inSW = $GLOBALS['TSFE']->csConvObj->utf8_encode($inSW, $GLOBALS['TSFE']->metaCharset);
00387 $inSW = $GLOBALS['TSFE']->csConvObj->entities_to_utf8($inSW,TRUE);
00388
00389 if ($hookObj = &$this->hookRequest('getSearchWords')) {
00390 return $hookObj->getSearchWords_splitSWords($inSW, $defOp);
00391 } else {
00392
00393 if ($this->piVars['type']==20) {
00394 return array(array('sword'=>trim($inSW), 'oper'=>'AND'));
00395 } else {
00396 $search = t3lib_div::makeInstance('tslib_search');
00397 $search->default_operator = $defOp==1 ? 'OR' : 'AND';
00398 $search->operator_translate_table = $this->operator_translate_table;
00399 $search->register_and_explode_search_string($inSW);
00400
00401 if (is_array($search->sword_array)) {
00402 return $this->procSearchWordsByLexer($search->sword_array);
00403 }
00404 }
00405 }
00406 }
00407
00415 function procSearchWordsByLexer($SWArr) {
00416
00417
00418 $newSWArr = array();
00419
00420
00421 foreach($SWArr as $wordDef) {
00422 if (!strstr($wordDef['sword'],' ')) {
00423
00424 $res = $this->lexerObj->split2Words($wordDef['sword']);
00425
00426
00427 foreach($res as $word) {
00428 $newSWArr[] = array('sword'=>$word, 'oper'=>$wordDef['oper']);
00429 }
00430 } else {
00431 $newSWArr[] = $wordDef;
00432 }
00433 }
00434
00435
00436 return $newSWArr;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00459 function doSearch($sWArr) {
00460
00461
00462 $pt1 = t3lib_div::milliseconds();
00463 if ($hookObj = &$this->hookRequest('getResultRows')) {
00464 $resData = $hookObj->getResultRows($sWArr);
00465 } else {
00466 $resData = $this->getResultRows($sWArr);
00467 }
00468
00469
00470 $pt2 = t3lib_div::milliseconds();
00471 if ($hookObj = &$this->hookRequest('getDisplayResults')) {
00472 $content = $hookObj->getDisplayResults($sWArr, $resData);
00473 } else {
00474 $content = $this->getDisplayResults($sWArr, $resData);
00475 }
00476
00477 $pt3 = t3lib_div::milliseconds();
00478
00479
00480 $this->writeSearchStat($sWArr,$resData['count'],array($pt1,$pt2,$pt3));
00481
00482
00483 return $content;
00484 }
00485
00492 function getResultRows($sWArr) {
00493
00494
00495 $GLOBALS['TT']->push('Searching result');
00496 $res = $this->getResultRows_SQLpointer($sWArr);
00497 $GLOBALS['TT']->pull();
00498
00499
00500 if ($res) {
00501
00502
00503 $count = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
00504 $pointer = t3lib_div::intInRange($this->piVars['pointer'],0,floor($count/$this->piVars['results']));
00505
00506
00507 $c = 0;
00508 $lines = Array();
00509 $grouping_phashes = array();
00510 $grouping_chashes = array();
00511 $firstRow = Array();
00512 $resultRows = Array();
00513
00514
00515
00516 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00517
00518
00519 if (!$c) {
00520 $firstRow = $row;
00521 }
00522
00523 $row['show_resume'] = $this->checkResume($row);
00524 $phashGr = !in_array($row['phash_grouping'], $grouping_phashes);
00525 $chashGr = !in_array($row['contentHash'].'.'.$row['data_page_id'], $grouping_chashes);
00526 if ($phashGr && $chashGr) {
00527 if ($row['show_resume']) {
00528 if (!$this->multiplePagesType($row['item_type'])) {
00529 $grouping_phashes[] = $row['phash_grouping'];
00530 }
00531 $grouping_chashes[] = $row['contentHash'].'.'.$row['data_page_id'];
00532 }
00533 $c++;
00534
00535
00536 if ($c > $pointer * $this->piVars['results']) {
00537 $row['result_number'] = $c;
00538 $resultRows[] = $row;
00539 if ($c+1 > ($pointer+1)*$this->piVars['results']) break;
00540 }
00541 } else {
00542 $count--;
00543 }
00544 }
00545
00546 return array(
00547 'resultRows' => $resultRows,
00548 'firstRow' => $firstRow,
00549 'count' => $count
00550 );
00551 } else {
00552 return FALSE;
00553 }
00554 }
00555
00562 function getResultRows_SQLpointer($sWArr) {
00563
00564 $list = $this->getPhashList($sWArr);
00565
00566
00567 if ($list) {
00568
00569 return $this->execFinalQuery($list);
00570 } else {
00571 return FALSE;
00572 }
00573 }
00574
00582 function getDisplayResults($sWArr, $resData) {
00583
00584 if ($resData) {
00585 $GLOBALS['TT']->push('Display Final result');
00586
00587
00588 $this->firstRow = $resData['firstRow'];
00589
00590
00591 $rowcontent = '';
00592 $rowcontent.= $this->compileResult($resData['resultRows']);
00593
00594
00595 if ($resData['count']) {
00596 $this->internal['res_count'] = $resData['count'];
00597 $this->internal['results_at_a_time'] = $this->piVars['results'];
00598 $this->internal['maxPages'] = t3lib_div::intInRange($this->conf['search.']['page_links'],1,100,10);
00599 $addString = ($resData['count']&&$this->piVars['group']=='sections' ? ' '.sprintf($this->pi_getLL(count($this->resultSections)>1?'inNsections':'inNsection'),count($this->resultSections)):'');
00600 $browseBox1 = $this->pi_list_browseresults(1,$addString,$this->printResultSectionLinks());
00601 $browseBox2 = $this->pi_list_browseresults(0);
00602 }
00603
00604
00605 if ($resData['count']) {
00606 $content = $browseBox1.$rowcontent.$browseBox2;
00607 } else {
00608 $content = '<p'.$this->pi_classParam('noresults').'>'.$this->pi_getLL('noResults','',1).'</p>';
00609 }
00610
00611 $GLOBALS['TT']->pull();
00612 } else {
00613 $content.='<p'.$this->pi_classParam('noresults').'>'.$this->pi_getLL('noResults','',1).'</p>';
00614 }
00615
00616
00617 $what = $this->tellUsWhatIsSeachedFor($sWArr).
00618 (substr($this->piVars['sections'],0,2)=='rl'?' '.$this->pi_getLL('inSection','',1).' "'.substr($this->getPathFromPageId(substr($this->piVars['sections'],4)),1).'"':'');
00619 $what = '<div'.$this->pi_classParam('whatis').'><p>'.$what.'</p></div>';
00620 $content = $what.$content;
00621
00622
00623 return $content;
00624 }
00625
00633 function compileResult($resultRows) {
00634 $content = '';
00635
00636
00637 $newResultRows = array();
00638 foreach($resultRows as $row) {
00639 $id = md5($row['phash_grouping']);
00640 if (is_array($newResultRows[$id])) {
00641 if (!$newResultRows[$id]['show_resume'] && $row['show_resume']) {
00642
00643
00644 $subrows = $newResultRows[$id]['_sub'];
00645 unset($newResultRows[$id]['_sub']);
00646 $subrows[] = $newResultRows[$id];
00647
00648
00649 $newResultRows[$id] = $row;
00650 $newResultRows[$id]['_sub'] = $subrows;
00651 } else $newResultRows[$id]['_sub'][] = $row;
00652 } else {
00653 $newResultRows[$id] = $row;
00654 }
00655 }
00656 $resultRows = $newResultRows;
00657
00658
00659 switch($this->piVars['group']) {
00660 case 'sections':
00661
00662 $rl2flag = substr($this->piVars['sections'],0,2)=='rl';
00663 $sections = array();
00664 foreach($resultRows as $row) {
00665 $id = $row['rl0'].'-'.$row['rl1'].($rl2flag?'-'.$row['rl2']:'');
00666 $sections[$id][] = $row;
00667 }
00668
00669 $this->resultSections = array();
00670
00671 foreach($sections as $id => $resultRows) {
00672 $rlParts = explode('-',$id);
00673 $theId = $rlParts[2] ? $rlParts[2] : ($rlParts[1]?$rlParts[1]:$rlParts[0]);
00674 $theRLid = $rlParts[2] ? 'rl2_'.$rlParts[2]:($rlParts[1]?'rl1_'.$rlParts[1]:'0');
00675
00676 $sectionName = substr($this->getPathFromPageId($theId),1);
00677 if (!trim($sectionName)) {
00678 $sectionTitleLinked = $this->pi_getLL('unnamedSection','',1).':';
00679 } else {
00680 $onclick = 'document.'.$this->prefixId.'[\''.$this->prefixId.'[_sections]\'].value=\''.$theRLid.'\';document.'.$this->prefixId.'.submit();return false;';
00681 $sectionTitleLinked = '<a href="#" onclick="'.htmlspecialchars($onclick).'">'.htmlspecialchars($sectionName).':</a>';
00682 }
00683 $this->resultSections[$id] = array($sectionName,count($resultRows));
00684
00685
00686 $content.= $this->makeSectionHeader($id,$sectionTitleLinked,count($resultRows));
00687
00688
00689 foreach($resultRows as $row) {
00690 $content.= $this->printResultRow($row);
00691 }
00692 }
00693 break;
00694 default:
00695 foreach($resultRows as $row) {
00696 $content.= $this->printResultRow($row);
00697 }
00698 break;
00699 }
00700 return '<div'.$this->pi_classParam('res').'>'.$content.'</div>';
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00726 function getPhashList($sWArr) {
00727
00728
00729 $c=0;
00730 $totalHashList = array();
00731 $this->wSelClauses = array();
00732
00733
00734 foreach($sWArr as $k => $v) {
00735 $GLOBALS['TT']->push('SearchWord '.$sWord);
00736
00737
00738 $sWord = $v['sword'];
00739
00740 $theType = (string)$this->piVars['type'];
00741 if (strstr($sWord,' ')) $theType = 20;
00742 $res = '';
00743 $wSel='';
00744
00745
00746 switch($theType) {
00747 case '1':
00748 $wSel = "IW.baseword LIKE '%".$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_words')."%'";
00749 $res = $this->execPHashListQuery($wSel,' AND is_stopword=0');
00750 break;
00751 case '2':
00752 $wSel = "IW.baseword LIKE '".$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_words')."%'";
00753 $res = $this->execPHashListQuery($wSel,' AND is_stopword=0');
00754 break;
00755 case '3':
00756 $wSel = "IW.baseword LIKE '%".$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_words')."'";
00757 $res = $this->execPHashListQuery($wSel,' AND is_stopword=0');
00758 break;
00759 case '10':
00760 $wSel = 'IW.metaphone = '.$this->indexerObj->metaphone($sWord);
00761 $res = $this->execPHashListQuery($wSel,' AND is_stopword=0');
00762 break;
00763 case '20':
00764 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00765 'ISEC.phash',
00766 'index_section ISEC, index_fulltext IFT',
00767 'IFT.fulltextdata LIKE \'%'.$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_fulltext').'%\' AND
00768 ISEC.phash = IFT.phash
00769 '.$this->sectionTableWhere(),
00770 'ISEC.phash'
00771 );
00772 $wSel = '1=1';
00773
00774 if ($this->piVars['type']==20) $this->piVars['order'] = 'mtime';
00775 break;
00776 default:
00777 $wSel = 'IW.wid = '.$hash = $this->indexerObj->md5inthash($sWord);
00778 $res = $this->execPHashListQuery($wSel,' AND is_stopword=0');
00779 break;
00780 }
00781
00782
00783 $this->wSelClauses[] = $wSel;
00784
00785
00786 if ($res) {
00787
00788
00789 $phashList = array();
00790 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00791 $phashList[] = $row['phash'];
00792 }
00793 $GLOBALS['TYPO3_DB']->sql_free_result($res);
00794
00795
00796 if ($c) {
00797 switch($v['oper']) {
00798 case 'OR':
00799 $totalHashList = array_unique(array_merge($phashList,$totalHashList));
00800 break;
00801 case 'AND NOT':
00802 $totalHashList = array_diff($totalHashList,$phashList);
00803 break;
00804 default:
00805 $totalHashList = array_intersect($totalHashList,$phashList);
00806 break;
00807 }
00808 } else {
00809 $totalHashList = $phashList;
00810 }
00811 }
00812
00813 $GLOBALS['TT']->pull();
00814 $c++;
00815 }
00816
00817 return implode(',',$totalHashList);
00818 }
00819
00827 function execPHashListQuery($wordSel,$plusQ='') {
00828 return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00829 'IR.phash',
00830 'index_words IW,
00831 index_rel IR,
00832 index_section ISEC',
00833 $wordSel.'
00834 AND IW.wid=IR.wid
00835 AND ISEC.phash = IR.phash
00836 '.$this->sectionTableWhere().'
00837 '.$plusQ,
00838 'IR.phash'
00839 );
00840 }
00841
00847 function sectionTableWhere() {
00848 $out = $this->wholeSiteIdList<0 ? '' : 'AND ISEC.rl0 IN ('.$this->wholeSiteIdList.')';
00849
00850 $match = '';
00851 if (substr($this->piVars['sections'],0,4)=='rl1_') {
00852 $list = implode(',',t3lib_div::intExplode(',',substr($this->piVars['sections'],4)));
00853 $out.= 'AND ISEC.rl1 IN ('.$list.')';
00854 $match = TRUE;
00855 } elseif (substr($this->piVars['sections'],0,4)=='rl2_') {
00856 $list = implode(',',t3lib_div::intExplode(',',substr($this->piVars['sections'],4)));
00857 $out.= 'AND ISEC.rl2 IN ('.$list.')';
00858 $match = TRUE;
00859 } elseif (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['addRootLineFields'])) {
00860
00861 foreach($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['addRootLineFields'] as $fieldName => $rootLineLevel) {
00862 if (substr($this->piVars['sections'],0,strlen($fieldName)+1)==$fieldName.'_') {
00863 $list = implode(',',t3lib_div::intExplode(',',substr($this->piVars['sections'],strlen($fieldName)+1)));
00864 $out.= 'AND ISEC.'.$fieldName.' IN ('.$list.')';
00865 $match = TRUE;
00866 break;
00867 }
00868 }
00869 }
00870
00871
00872 if (!$match) {
00873 switch((string)$this->piVars['sections']) {
00874 case '-1':
00875 $out.= ' AND ISEC.page_id='.$GLOBALS['TSFE']->id;
00876 break;
00877 case '-2':
00878 $out.= ' AND ISEC.rl2=0';
00879 break;
00880 case '-3':
00881 $out.= ' AND ISEC.rl2>0';
00882 break;
00883 }
00884 }
00885
00886 return $out;
00887 }
00888
00894 function mediaTypeWhere() {
00895
00896 switch((string)$this->piVars['media']) {
00897 case '0':
00898 $out = 'AND IP.item_type='.$GLOBALS['TYPO3_DB']->fullQuoteStr('0', 'index_phash');;
00899 break;
00900 case '-2':
00901 $out = 'AND IP.item_type!='.$GLOBALS['TYPO3_DB']->fullQuoteStr('0', 'index_phash');;
00902 break;
00903 case '-1':
00904 $out='';
00905 break;
00906 default:
00907 $out = 'AND IP.item_type='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->piVars['media'], 'index_phash');
00908 break;
00909 }
00910
00911 return $out;
00912 }
00913
00919 function languageWhere() {
00920 if ($this->piVars['lang']>=0) {
00921 return 'AND IP.sys_language_uid='.intval($this->piVars['lang']);
00922 }
00923 }
00924
00931 function execFinalQuery($list) {
00932
00933
00934 $page_join = '';
00935 $page_where = '';
00936
00937
00938 if ($hookObj = &$this->hookRequest('execFinalQuery_idList')) {
00939 $page_where = $hookObj->execFinalQuery_idList($list);
00940 } elseif ($this->join_pages) {
00941 $page_join = ',
00942 pages';
00943 $page_where = 'pages.uid = ISEC.page_id
00944 '.$this->cObj->enableFields('pages').'
00945 AND pages.no_search=0
00946 AND pages.doktype<200
00947 ';
00948 } elseif ($this->wholeSiteIdList>=0) {
00949 $siteIdNumbers = t3lib_div::intExplode(',',$this->wholeSiteIdList);
00950 $id_list=array();
00951 while(list(,$rootId)=each($siteIdNumbers)) {
00952 $id_list[] = $this->cObj->getTreeList($rootId,9999,0,0,'','').$rootId;
00953 }
00954 $page_where = 'ISEC.page_id IN ('.implode(',',$id_list).')';
00955 } else {
00956 $page_where = ' 1=1 ';
00957 }
00958
00959
00960
00961 if (substr($this->piVars['order'],0,5)=='rank_') {
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991 switch($this->piVars['order']) {
00992 case 'rank_flag':
00993
00994 $grsel = 'MAX(IR.flags) AS order_val1, SUM(IR.freq) AS order_val2';
00995 $orderBy = 'order_val1'.$this->isDescending().',order_val2'.$this->isDescending();
00996 break;
00997 case 'rank_first':
00998 $grsel = 'AVG(IR.first) AS order_val';
00999 $orderBy = 'order_val'.$this->isDescending(1);
01000 break;
01001 case 'rank_count':
01002 $grsel = 'SUM(IR.count) AS order_val';
01003 $orderBy = 'order_val'.$this->isDescending();
01004 break;
01005 default:
01006 $grsel = 'SUM(IR.freq) AS order_val';
01007 $orderBy = 'order_val'.$this->isDescending();
01008 break;
01009 }
01010
01011
01012 $wordSel='('.implode(' OR ',$this->wSelClauses).') AND ';
01013
01014 return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
01015 'ISEC.*, IP.*, '
01016 .$grsel,
01017 'index_words IW,
01018 index_rel IR,
01019 index_section ISEC,
01020 index_phash IP'.
01021 $page_join,
01022 $wordSel.'
01023 IP.phash IN ('.$list.') '.
01024 $this->mediaTypeWhere().' '.
01025 $this->languageWhere().'
01026 AND IW.wid=IR.wid
01027 AND ISEC.phash = IR.phash
01028 AND IP.phash = IR.phash
01029 AND '.$page_where,
01030 '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',
01031 $orderBy
01032 );
01033 } else {
01034
01035 $orderBy = '';
01036 switch((string)$this->piVars['order']) {
01037 case 'title':
01038 $orderBy = 'IP.item_title'.$this->isDescending();
01039 break;
01040 case 'crdate':
01041 $orderBy = 'IP.item_crdate'.$this->isDescending();
01042 break;
01043 case 'mtime':
01044 $orderBy = 'IP.item_mtime'.$this->isDescending();
01045 break;
01046 }
01047
01048 return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
01049 'ISEC.*, IP.*',
01050 'index_phash IP,index_section ISEC'.$page_join,
01051 'IP.phash IN ('.$list.') '.
01052 $this->mediaTypeWhere().' '.
01053 $this->languageWhere().'
01054 AND IP.phash = ISEC.phash
01055 AND '.$page_where,
01056 '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',
01057 $orderBy
01058 );
01059 }
01060 }
01061
01069 function checkResume($row) {
01070
01071
01072
01073
01074 if ($row['freeIndexUid']) {
01075 return TRUE;
01076 }
01077
01078
01079 if ($row['item_type']) {
01080
01081
01082
01083
01084 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('phash', 'index_grlist', 'phash='.intval($row['phash_t3']).' AND gr_list='.$GLOBALS['TYPO3_DB']->fullQuoteStr($GLOBALS['TSFE']->gr_list, 'index_grlist'));
01085 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
01086 #debug("Look up for external media '".$row['data_filename']."': phash:".$row['phash_t3'].' YES - ('.$GLOBALS['TSFE']->gr_list.")!",1);
01087 return TRUE;
01088 } else {
01089 #debug("Look up for external media '".$row['data_filename']."': phash:".$row['phash_t3'].' NO - ('.$GLOBALS['TSFE']->gr_list.")!",1);
01090 return FALSE;
01091 }
01092 } else {
01093 if (strcmp($row['gr_list'],$GLOBALS['TSFE']->gr_list)) {
01094
01095 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('phash', 'index_grlist', 'phash='.intval($row['phash']).' AND gr_list='.$GLOBALS['TYPO3_DB']->fullQuoteStr($GLOBALS['TSFE']->gr_list, 'index_grlist'));
01096 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
01097 #debug('Checking on it ...'.$row['item_title'].'/'.$row['phash'].' - YES ('.$GLOBALS['TSFE']->gr_list.")",1);
01098 return TRUE;
01099 } else {
01100 #debug('Checking on it ...'.$row['item_title'].'/'.$row['phash']." - NOPE",1);
01101 return FALSE;
01102 }
01103 } else {
01104 #debug('Resume can be shown, because the document was in fact indexed by this combination of groups!'.$GLOBALS['TSFE']->gr_list.' - '.$row['item_title'].'/'.$row['phash'],1);
01105 return TRUE;
01106 }
01107 }
01108 }
01109
01116 function isDescending($inverse=FALSE) {
01117 $desc = $this->piVars['desc'];
01118 if ($inverse) $desc=!$desc;
01119 return !$desc ? ' DESC':'';
01120 }
01121
01130 function writeSearchStat($sWArr,$count,$pt) {
01131 $insertFields = array(
01132 'searchstring' => $this->piVars['sword'],
01133 'searchoptions' => serialize(array($this->piVars,$sWArr,$pt)),
01134 'feuser_id' => intval($this->fe_user->user['uid']),
01135 'cookie' => $this->fe_user->id,
01136 'IP' => t3lib_div::getIndpEnv('REMOTE_ADDR'),
01137 'hits' => intval($count),
01138 'tstamp' => $GLOBALS['EXEC_TIME']
01139 );
01140
01141 $GLOBALS['TYPO3_DB']->exec_INSERTquery('index_stat_search', $insertFields);
01142 $newId = $GLOBALS['TYPO3_DB']->sql_insert_id();
01143
01144 if ($newId) {
01145 foreach($sWArr as $val) {
01146 $insertFields = array(
01147 'word' => $val['sword'],
01148 'index_stat_search_id' => $newId,
01149 'tstamp' => $GLOBALS['EXEC_TIME'],
01150 'pageid' => $GLOBALS['TSFE']->id
01151 );
01152
01153 $GLOBALS['TYPO3_DB']->exec_INSERTquery('index_stat_word', $insertFields);
01154 }
01155 }
01156 }
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01182 function makeSearchForm($optValues) {
01183
01184
01185 $rows = array();
01186
01187
01188 $rows[]='<tr>
01189 <td nowrap="nowrap"><p>'.$this->pi_getLL('form_searchFor','',1).' </p></td>
01190 <td><input type="text" name="'.$this->prefixId.'[sword]" value="'.htmlspecialchars($this->conf['show.']['clearSearchBox']?'':$this->piVars['sword']).'"'.$this->pi_classParam('searchbox-sword').' /> <input type="submit" name="'.$this->prefixId.'[submit_button]" value="'.$this->pi_getLL('submit_button_label','',1).'"'.$this->pi_classParam('searchbox-button').' /></td>
01191 </tr>';
01192
01193 if ($this->conf['show.']['clearSearchBox'] && $this->conf['show.']['clearSearchBox.']['enableSubSearchCheckBox']) {
01194 $rows[]='<tr>
01195 <td></td>
01196 <td><input type="hidden" name="'.$this->prefixId.'[sword_prev]" value="'.htmlspecialchars($this->piVars['sword']).'" /><input type="checkbox" name="'.$this->prefixId.'[sword_prev_include]" value="1"'.($this->piVars['sword_prev_include']?' checked="checked"':'').' /> '.$this->pi_getLL('makerating_addToCurrentSearch').'</td>
01197 </tr>';
01198 }
01199
01200
01201 if ($this->piVars['ext']) {
01202 if (is_array($optValues['type']) || is_array($optValues['defOp'])) $rows[]='<tr>
01203 <td nowrap="nowrap"><p>'.$this->pi_getLL('form_match','',1).' </p></td>
01204 <td>'.$this->renderSelectBox($this->prefixId.'[type]',$this->piVars['type'],$optValues['type']).
01205 $this->renderSelectBox($this->prefixId.'[defOp]',$this->piVars['defOp'],$optValues['defOp']).'</td>
01206 </tr>';
01207 if (is_array($optValues['media']) || is_array($optValues['lang'])) $rows[]='<tr>
01208 <td nowrap="nowrap"><p>'.$this->pi_getLL('form_searchIn','',1).' </p></td>
01209 <td>'.$this->renderSelectBox($this->prefixId.'[media]',$this->piVars['media'],$optValues['media']).
01210 $this->renderSelectBox($this->prefixId.'[lang]',$this->piVars['lang'],$optValues['lang']).'</td>
01211 </tr>';
01212 if (is_array($optValues['sections'])) $rows[]='<tr>
01213 <td nowrap="nowrap"><p>'.$this->pi_getLL('form_fromSection','',1).' </p></td>
01214 <td>'.$this->renderSelectBox($this->prefixId.'[sections]',$this->piVars['sections'],$optValues['sections']).'</td>
01215 </tr>';
01216 if (is_array($optValues['order']) || is_array($optValues['desc']) || is_array($optValues['results'])) $rows[]='<tr>
01217 <td nowrap="nowrap"><p>'.$this->pi_getLL('form_orderBy','',1).' </p></td>
01218 <td><p>'.$this->renderSelectBox($this->prefixId.'[order]',$this->piVars['order'],$optValues['order']).
01219 $this->renderSelectBox($this->prefixId.'[desc]',$this->piVars['desc'],$optValues['desc']).
01220 $this->renderSelectBox($this->prefixId.'[results]',$this->piVars['results'],$optValues['results']).' '.$this->pi_getLL('form_atATime','',1).'</p></td>
01221 </tr>';
01222 if (is_array($optValues['group']) || !$this->conf['blind.']['extResume']) $rows[]='<tr>
01223 <td nowrap="nowrap"><p>'.$this->pi_getLL('form_style','',1).' </p></td>
01224 <td><p>'.$this->renderSelectBox($this->prefixId.'[group]',$this->piVars['group'],$optValues['group']).
01225 (!$this->conf['blind.']['extResume'] ? '
01226 <input type="hidden" name="'.$this->prefixId.'[extResume]" value="0" /><input type="checkbox" value="1" name="'.$this->prefixId.'[extResume]"'.($this->piVars['extResume']?' checked="checked"':'').' />'.$this->pi_getLL('form_extResume','',1):'').'</p></td>
01227 </tr>';
01228 }
01229
01230
01231 $out='
01232 <form action="'.htmlspecialchars($this->pi_getPageLink($GLOBALS['TSFE']->id,$GLOBALS['TSFE']->sPre)).'" method="post" name="'.$this->prefixId.'" style="margin: 0 0 0 0;">
01233 <table '.$this->conf['tableParams.']['searchBox'].'>
01234 '.implode(chr(10),$rows).'
01235 </table>
01236 <input type="hidden" name="'.$this->prefixId.'[_sections]" value="0" />
01237 <input type="hidden" name="'.$this->prefixId.'[pointer]" value="0" />
01238 <input type="hidden" name="'.$this->prefixId.'[ext]" value="'.($this->piVars['ext']?1:0).'" />
01239 </form>';
01240 $out.='<p>'.
01241 ($this->piVars['ext'] ?
01242 '<a href="'.htmlspecialchars($this->pi_getPageLink($GLOBALS['TSFE']->id,$GLOBALS['TSFE']->sPre,array($this->prefixId.'[ext]'=>0))).'">'.$this->pi_getLL('link_regularSearch','',1).'</a>' :
01243 '<a href="'.htmlspecialchars($this->pi_getPageLink($GLOBALS['TSFE']->id,$GLOBALS['TSFE']->sPre,array($this->prefixId.'[ext]'=>1))).'">'.$this->pi_getLL('link_advancedSearch','',1).'</a>'
01244 ).'</p>';
01245
01246 return '<div'.$this->pi_classParam('searchbox').'>'.$out.'</div>';
01247 }
01248
01254 function printRules() {
01255 $out = '';
01256 if ($this->conf['show.']['rules']) {
01257 $out = '<h2>'.$this->pi_getLL('rules_header','',1).'</h2>
01258 <p>'.nl2br(trim($this->pi_getLL('rules_text','',1))).'</p>';
01259 $out = '
01260 <div'.$this->pi_classParam('rules').'>'.$this->cObj->stdWrap($out, $this->conf['rules_stdWrap.']).'</div>';
01261 }
01262 return $out;
01263 }
01264
01270 function printResultSectionLinks() {
01271 if (count($this->resultSections)) {
01272 $lines = array();
01273
01274 foreach($this->resultSections as $id => $dat) {
01275 $lines[] = '<li><a href="'.htmlspecialchars($GLOBALS['TSFE']->anchorPrefix.'#'.md5($id)).'">'.
01276 htmlspecialchars(trim($dat[0])?trim($dat[0]):$this->pi_getLL('unnamedSection')).' ('.$dat[1].' '.$this->pi_getLL($dat[1]>1?'word_pages':'word_page','',1).')'.
01277 '</a></li>';
01278 }
01279 $out = '<ul>'.implode(chr(10),$lines).'</ul>';
01280 return '<div'.$this->pi_classParam('sectionlinks').'>'.$this->cObj->stdWrap($out, $this->conf['sectionlinks_stdWrap.']).'</div>';
01281 }
01282 }
01283
01292 function makeSectionHeader($id,$sectionTitleLinked,$countResultRows) {
01293 return '<div'.$this->pi_classParam('secHead').'><a name="'.md5($id).'"></a><table '.$this->conf['tableParams.']['secHead'].'>
01294 <tr>
01295 <td width="95%"><h2>'.$sectionTitleLinked.'</h2></td>
01296 <td align="right" nowrap="nowrap"><p>'.$countResultRows.' '.$this->pi_getLL($countResultRows>1?'word_pages':'word_page','',1).'</p></td>
01297 </tr>
01298 </table></div>';
01299 }
01300
01308 function printResultRow($row, $headerOnly=0) {
01309
01310
01311 $tmplContent = $this->prepareResultRowTemplateData($row, $headerOnly);
01312
01313 if ($hookObj = &$this->hookRequest('printResultRow')) {
01314 return $hookObj->printResultRow($row, $headerOnly, $tmplContent);
01315 } else {
01316
01317
01318 $out.='<tr '.$this->pi_classParam('title'.$tmplContent['CSSsuffix']).'>
01319 <td width="16" '.$this->pi_classParam('title-icon'.$tmplContent['CSSsuffix']).'>'.$tmplContent['icon'].'</td>
01320 <td width="95%" nowrap="nowrap"><p>'.
01321 #$row['phash'].'
01322 '<span '.$this->pi_classParam('title-number'.$tmplContent['CSSsuffix']).'>'.$tmplContent['result_number'].': </span>'.
01323 '<span '.$this->pi_classParam('title-caption'.$tmplContent['CSSsuffix']).'>'.$tmplContent['title'].'</span>'.
01324 '</p></td>
01325 <td nowrap="nowrap"><p'.$this->pi_classParam('percent'.$tmplContent['CSSsuffix']).'>'.$tmplContent['rating'].'</p></td>
01326 </tr>';
01327
01328
01329 if (!$headerOnly) {
01330 $out.='<tr>
01331 <td></td>
01332 <td colspan="2"'.$this->pi_classParam('descr'.$tmplContent['CSSsuffix']).'><p>'.$tmplContent['description'].'</p></td>
01333 </tr>';
01334 $out.='<tr>
01335 <td></td>
01336 <td '.$this->pi_classParam('info'.$tmplContent['CSSsuffix']).' nowrap="nowrap"><p>'.
01337 $tmplContent['size'].' - '.$tmplContent['created'].' - '.$tmplContent['modified'].
01338 ($tmplContent['path'] ? '<br/>'.$this->pi_getLL('res_path','',1).' '.$tmplContent['path'] : '').
01339 '</p></td>
01340 <td '.$this->pi_classParam('info'.$tmplContent['CSSsuffix']).' align="right"><p>'.$tmplContent['access'].$tmplContent['language'].'</p></td>
01341 </tr>';
01342 } elseif ($headerOnly==1) {
01343 $out.='<tr>
01344 <td></td>
01345 <td colspan="2"'.$this->pi_classParam('descr'.$tmplContent['CSSsuffix']).'><p>'.$tmplContent['description'].'</p></td>
01346 </tr>';
01347 }
01348
01349
01350 if (is_array($row['_sub'])) {
01351 if ($this->multiplePagesType($row['item_type'])) {
01352 $out.='<tr>
01353 <td></td>
01354 <td colspan="2"><p><br/>'.$this->pi_getLL('res_otherMatching','',1).'<br/><br/></p></td>
01355 </tr>';
01356
01357 foreach($row['_sub'] as $subRow) {
01358 $out.='<tr>
01359 <td></td>
01360 <td colspan="2"><p>'.$this->printResultRow($subRow,1).'</p></td>
01361 </tr>';
01362 }
01363 } else {
01364 $out.='<tr>
01365 <td></td>
01366 <td colspan="2"><p>'.$this->pi_getLL('res_otherPageAsWell','',1).'</p></td>
01367 </tr>';
01368 }
01369 }
01370
01371 return '<table '.$this->conf['tableParams.']['searchRes'].'>'.$out.'</table><br/>';
01372 }
01373 }
01374
01383 function pi_list_browseresults($showResultCount=1,$addString='',$addPart='') {
01384
01385
01386 $pointer=$this->piVars['pointer'];
01387 $count=$this->internal['res_count'];
01388 $results_at_a_time = t3lib_div::intInRange($this->internal['results_at_a_time'],1,1000);
01389 $maxPages = t3lib_div::intInRange($this->internal['maxPages'],1,100);
01390 $max = t3lib_div::intInRange(ceil($count/$results_at_a_time),1,$maxPages);
01391 $pointer=intval($pointer);
01392 $links=array();
01393
01394
01395 if ($pointer>0) {
01396 $links[]='<td><p>'.$this->makePointerSelector_link($this->pi_getLL('pi_list_browseresults_prev','< Previous',1),$pointer-1).'</p></td>';
01397 }
01398 for($a=0;$a<$max;$a++) {
01399 $links[]='<td'.($pointer==$a?$this->pi_classParam('browsebox-SCell'):'').'><p>'.$this->makePointerSelector_link(trim($this->pi_getLL('pi_list_browseresults_page','Page',1).' '.($a+1)),$a).'</p></td>';
01400 }
01401 if ($pointer<ceil($count/$results_at_a_time)-1) {
01402 $links[]='<td><p>'.$this->makePointerSelector_link($this->pi_getLL('pi_list_browseresults_next','Next >',1),$pointer+1).'</p></td>';
01403 }
01404
01405 $pR1 = $pointer*$results_at_a_time+1;
01406 $pR2 = $pointer*$results_at_a_time+$results_at_a_time;
01407 $sTables = '<div'.$this->pi_classParam('browsebox').'>'.
01408 ($showResultCount ? '<p>'.sprintf(
01409 str_replace('###SPAN_BEGIN###','<span'.$this->pi_classParam('browsebox-strong').'>',$this->pi_getLL('pi_list_browseresults_displays','Displaying results ###SPAN_BEGIN###%s to %s</span> out of ###SPAN_BEGIN###%s</span>')),
01410 $pR1,
01411 min(array($this->internal['res_count'],$pR2)),
01412 $this->internal['res_count']
01413 ).$addString.'</p>':''
01414 ).$addPart.
01415 '<table>
01416 <tr>'.implode('',$links).'</tr>
01417 </table></div>';
01418
01419 return $sTables;
01420 }
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01446 function prepareResultRowTemplateData($row, $headerOnly) {
01447
01448
01449 $specRowConf = $this->getSpecialConfigForRow($row);
01450 $CSSsuffix = $specRowConf['CSSsuffix']?'-'.$specRowConf['CSSsuffix']:'';
01451
01452
01453 if ($row['item_type']) {
01454 if ($row['show_resume']) {
01455 $title = '<a href="'.htmlspecialchars($row['data_filename']).'">'.htmlspecialchars($this->makeTitle($row)).'</a>';
01456 } else {
01457 $copy_row = $row;
01458 unset($copy_row['cHashParams']);
01459 $title = $this->linkPage($row['page_id'],htmlspecialchars($this->makeTitle($row)),$copy_row);
01460 }
01461 } else {
01462
01463
01464 if ($this->conf['forwardSearchWordsInResultLink']) {
01465 $markUpSwParams = array('no_cache' => 1);
01466 foreach($this->sWArr as $d) {
01467 $markUpSwParams['sword_list'][] = $d['sword'];
01468 }
01469 } else {
01470 $markUpSwParams = array();
01471 }
01472 $title = $this->linkPage($row['data_page_id'],htmlspecialchars($this->makeTitle($row)),$row,$markUpSwParams);
01473 }
01474
01475 $tmplContent = array();
01476 $tmplContent['title'] = $title;
01477 $tmplContent['result_number'] = $row['result_number'];
01478 $tmplContent['icon'] = $this->makeItemTypeIcon($row['item_type'],'',$specRowConf);
01479 $tmplContent['rating'] = $this->makeRating($row);
01480 $tmplContent['description'] = $this->makeDescription($row,$this->piVars['extResume'] && !$headerOnly?0:1);
01481 $tmplContent = $this->makeInfo($row,$tmplContent);
01482 $tmplContent['access'] = $this->makeAccessIndication($row['page_id']);
01483 $tmplContent['language'] = $this->makeLanguageIndication($row);
01484 $tmplContent['CSSsuffix'] = $CSSsuffix;
01485
01486
01487 if ($hookObj = &$this->hookRequest('prepareResultRowTemplateData_postProc')) {
01488 $tmplContent = $hookObj->prepareResultRowTemplateData_postProc($tmplContent, $row, $headerOnly);
01489 }
01490
01491 return $tmplContent;
01492 }
01493
01500 function tellUsWhatIsSeachedFor($sWArr) {
01501
01502
01503 $searchingFor = '';
01504 $c=0;
01505
01506
01507 foreach($sWArr as $k => $v) {
01508 if ($c) {
01509 switch($v['oper']) {
01510 case 'OR':
01511 $searchingFor.= ' '.$this->pi_getLL('searchFor_or','',1).' '.$this->wrapSW($this->utf8_to_currentCharset($v['sword']));
01512 break;
01513 case 'AND NOT':
01514 $searchingFor.= ' '.$this->pi_getLL('searchFor_butNot','',1).' '.$this->wrapSW($this->utf8_to_currentCharset($v['sword']));
01515 break;
01516 default:
01517 $searchingFor.= ' '.$this->pi_getLL('searchFor_and','',1).' '.$this->wrapSW($this->utf8_to_currentCharset($v['sword']));
01518 break;
01519 }
01520 } else {
01521 $searchingFor = $this->pi_getLL('searchFor','',1).' '.$this->wrapSW($this->utf8_to_currentCharset($v['sword']));
01522 }
01523 $c++;
01524 }
01525 return $searchingFor;
01526 }
01527
01534 function wrapSW($str) {
01535 return '"<span'.$this->pi_classParam('sw').'>'.htmlspecialchars($str).'</span>"';
01536 }
01537
01546 function renderSelectBox($name,$value,$optValues) {
01547 if (is_array($optValues)) {
01548 $opt = array();
01549 $isSelFlag = 0;
01550
01551 foreach($optValues as $k => $v) {
01552 $sel = (!strcmp($k,$value) ? ' selected="selected"' : '');
01553 if ($sel) $isSelFlag++;
01554 $opt[] = '<option value="'.htmlspecialchars($k).'"'.$sel.'>'.htmlspecialchars($v).'</option>';
01555 }
01556
01557 return '<select name="'.$name.'">'.implode('',$opt).'</select>';
01558 }
01559 }
01560
01569 function makePointerSelector_link($str,$p) {
01570 $onclick = 'document.'.$this->prefixId.'[\''.$this->prefixId.'[pointer]\'].value=\''.$p.'\';document.'.$this->prefixId.'.submit();return false;';
01571 return '<a href="#" onclick="'.htmlspecialchars($onclick).'">'.$str.'</a>';
01572 }
01573
01582 function makeItemTypeIcon($it,$alt='',$specRowConf) {
01583 if (!isset($this->iconFileNameCache[$it])) {
01584 $this->iconFileNameCache[$it] = '';
01585
01586
01587 if (is_array($this->conf['iconRendering.'])) {
01588 $this->cObj->setCurrentVal($it);
01589 $this->iconFileNameCache[$it] = $this->cObj->cObjGetSingle($this->conf['iconRendering'],$this->conf['iconRendering.']);
01590 } else {
01591
01592
01593 $icon = '';
01594 if ($it==='0') {
01595 if (is_array($specRowConf['pageIcon.'])) {
01596 $this->iconFileNameCache[$it] = $this->cObj->IMAGE($specRowConf['pageIcon.']);
01597 } else {
01598 $icon = 'EXT:indexed_search/pi/res/pages.gif';
01599 }
01600 } elseif ($this->external_parsers[$it]) {
01601 $icon = $this->external_parsers[$it]->getIcon($it);
01602 }
01603
01604 if ($icon) {
01605 $fullPath = t3lib_div::getFileAbsFileName($icon);
01606
01607 if ($fullPath) {
01608 $info = @getimagesize($fullPath);
01609 $iconPath = substr($fullPath,strlen(PATH_site));
01610 $this->iconFileNameCache[$it] = is_array($info) ? '<img src="'.$iconPath.'" '.$info[3].' title="'.htmlspecialchars($alt).'" alt="" />' : '';
01611 }
01612 }
01613 }
01614 }
01615 return $this->iconFileNameCache[$it];
01616 }
01617
01624 function makeRating($row) {
01625
01626 switch((string)$this->piVars['order']) {
01627 case 'rank_count':
01628 return $row['order_val'].' '.$this->pi_getLL('maketitle_matches');
01629 break;
01630 case 'rank_first':
01631 return ceil(t3lib_div::intInRange(255-$row['order_val'],1,255)/255*100).'%';
01632 break;
01633 case 'rank_flag':
01634 if ($this->firstRow['order_val2']) {
01635 $base = $row['order_val1']*256;
01636 $freqNumber = $row['order_val2']/$this->firstRow['order_val2']*pow(2,12);
01637 $total = t3lib_div::intInRange($base+$freqNumber,0,32767);
01638 #debug($total);
01639 return ceil(log($total)/log(32767)*100).'%';
01640 }
01641 break;
01642 case 'rank_freq':
01643 $max = 10000;
01644 $total = t3lib_div::intInRange($row['order_val'],0,$max);
01645 # debug($total);
01646 return ceil(log($total)/log($max)*100).'%';
01647 break;
01648 case 'crdate':
01649 return $this->cObj->calcAge(time()-$row['item_crdate'],0);
01650 break;
01651 case 'mtime':
01652 return $this->cObj->calcAge(time()-$row['item_mtime'],0);
01653 break;
01654 default:
01655 return ' ';
01656 break;
01657 }
01658 }
01659
01668 function makeDescription($row,$noMarkup=0,$lgd=180) {
01669 if ($row['show_resume']) {
01670 if (!$noMarkup) {
01671 $markedSW = '';
01672 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'index_fulltext', 'phash='.intval($row['phash']));
01673 if ($ftdrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
01674 $markedSW = $this->markupSWpartsOfString($ftdrow['fulltextdata']);
01675 }
01676 $GLOBALS['TYPO3_DB']->sql_free_result($res);
01677 }
01678
01679 if (trim($markedSW)) {
01680 return $this->utf8_to_currentCharset($markedSW);
01681 } else {
01682 $outputStr = $GLOBALS['TSFE']->csConvObj->crop('utf-8',$row['item_description'],$lgd);
01683 $outputStr = htmlspecialchars($outputStr);
01684
01685 return $this->utf8_to_currentCharset($outputStr);
01686 }
01687 } else {
01688 return '<span class="noResume">'.$this->pi_getLL('res_noResume','',1).'</span>';
01689 }
01690 }
01691
01698 function markupSWpartsOfString($str) {
01699
01700
01701 $str = str_replace(' ',' ',t3lib_parsehtml::bidir_htmlspecialchars($str,-1));
01702 $str = ereg_replace('[[:space:]]+',' ',$str);
01703 $swForReg = array();
01704
01705
01706 foreach($this->sWArr as $d) {
01707 $swForReg[] = quotemeta($d['sword']);
01708 }
01709 $regExString = '('.implode('|',$swForReg).')';
01710
01711
01712 $parts = preg_split('/'.$regExString.'/i', ' '.$str.' ', 20000, PREG_SPLIT_DELIM_CAPTURE);
01713 #debug($parts,$regExString);
01714
01715 $summaryMax = 300;
01716 $postPreLgd = 60;
01717 $postPreLgd_offset = 5;
01718 $divider = ' ... ';
01719
01720 $occurencies = (count($parts)-1)/2;
01721 if ($occurencies) {
01722 $postPreLgd = t3lib_div::intInRange($summaryMax/$occurencies,$postPreLgd,$summaryMax/2);
01723 }
01724
01725
01726 $summaryLgd = 0;
01727 $output = array();
01728
01729
01730 foreach($parts as $k => $strP) {
01731 if (($k%2)==0) {
01732
01733
01734 $strLen = $GLOBALS['TSFE']->csConvObj->strlen('utf-8', $parts[$k]);
01735 $output[$k] = $parts[$k];
01736
01737
01738 if (!$k) {
01739 if ($strLen > $postPreLgd) {
01740 $output[$k] = $divider.ereg_replace('^[^[:space:]]+[[:space:]]','',$GLOBALS['TSFE']->csConvObj->crop('utf-8',$parts[$k],-($postPreLgd-$postPreLgd_offset)));
01741 }
01742 } elseif ($summaryLgd > $summaryMax || !isset($parts[$k+1])) {
01743 if ($strLen > $postPreLgd) {
01744 $output[$k] = ereg_replace('[[:space:]][^[:space:]]+$','',$GLOBALS['TSFE']->csConvObj->crop('utf-8',$parts[$k],$postPreLgd-$postPreLgd_offset)).$divider;
01745 }
01746 } else {
01747 if ($strLen > $postPreLgd*2) {
01748 $output[$k] = ereg_replace('[[:space:]][^[:space:]]+$','',$GLOBALS['TSFE']->csConvObj->crop('utf-8',$parts[$k],$postPreLgd-$postPreLgd_offset)).
01749 $divider.
01750 ereg_replace('^[^[:space:]]+[[:space:]]','',$GLOBALS['TSFE']->csConvObj->crop('utf-8',$parts[$k],-($postPreLgd-$postPreLgd_offset)));
01751 }
01752 }
01753 $summaryLgd+= $GLOBALS['TSFE']->csConvObj->strlen('utf-8', $output[$k]);;
01754
01755
01756 $output[$k] = htmlspecialchars($output[$k]);
01757
01758
01759 if ($summaryLgd > $summaryMax) {
01760 break;
01761 }
01762 } else {
01763 $summaryLgd+= $GLOBALS['TSFE']->csConvObj->strlen('utf-8',$strP);
01764 $output[$k] = '<span class="tx-indexedsearch-redMarkup">'.htmlspecialchars($parts[$k]).'</span>';
01765 }
01766 }
01767
01768
01769 return implode('',$output);
01770 }
01771
01778 function makeTitle($row) {
01779 $add = '';
01780
01781 if ($this->multiplePagesType($row['item_type'])) {
01782 $dat = unserialize($row['cHashParams']);
01783
01784 $pp = explode('-',$dat['key']);
01785 if ($pp[0]!=$pp[1]) {
01786 $add=', '.$this->pi_getLL('word_pages').' '.$dat['key'];
01787 } else $add=', '.$this->pi_getLL('word_page').' '.$pp[0];
01788 }
01789
01790 $outputString = $GLOBALS['TSFE']->csConvObj->crop('utf-8',$row['item_title'],50,'...');
01791
01792 return $this->utf8_to_currentCharset(htmlspecialchars($outputString)).$add;
01793 }
01794
01802 function makeInfo($row,$tmplArray) {
01803 $tmplArray['size'] = $this->pi_getLL('res_size','',1).' '.t3lib_div::formatSize($row['item_size']).'';
01804 $tmplArray['created'] = $this->pi_getLL('res_created','',1).' '.date('d-m-y',$row['item_crdate']).'';
01805 $tmplArray['modified'] = $this->pi_getLL('res_modified','',1).' '.date('d-m-y H:i',$row['item_mtime']).'';
01806
01807 $pathId = $row['data_page_id']?$row['data_page_id']:$row['page_id'];
01808 $pathMP = $row['data_page_id']?$row['data_page_mp']:'';
01809
01810 $pI = parse_url($row['data_filename']);
01811 if ($pI['scheme']) {
01812 $tmplArray['path'] = '<a href="'.htmlspecialchars($row['data_filename']).'">'.htmlspecialchars($row['data_filename']).'</a>';
01813 } else {
01814 $pathStr = htmlspecialchars($this->getPathFromPageId($pathId,$pathMP));
01815 $tmplArray['path'] = $this->linkPage($pathId,htmlspecialchars($pathStr),array(
01816 'data_page_type' => $row['data_page_type'],
01817 'data_page_mp' => $pathMP,
01818 'sys_language_uid' => $row['sys_language_uid'],
01819 ));
01820 }
01821
01822 return $tmplArray;
01823 }
01824
01831 function getSpecialConfigForRow($row) {
01832 $pathId = $row['data_page_id'] ? $row['data_page_id'] : $row['page_id'];
01833 $pathMP = $row['data_page_id'] ? $row['data_page_mp'] : '';
01834
01835 $rl = $this->getRootLine($pathId,$pathMP);
01836 $specConf = $this->conf['specConfs.']['0.'];
01837 if (is_array($rl)) {
01838 foreach($rl as $dat) {
01839 if (is_array($this->conf['specConfs.'][$dat['uid'].'.'])) {
01840 $specConf = $this->conf['specConfs.'][$dat['uid'].'.'];
01841 break;
01842 }
01843 }
01844 }
01845
01846 return $specConf;
01847 }
01848
01855 function makeLanguageIndication($row) {
01856
01857
01858 if ((string)$row['item_type']==='0') {
01859
01860
01861 if (is_array($this->conf['flagRendering.'])) {
01862 $this->cObj->setCurrentVal($row['sys_language_uid']);
01863 return $this->cObj->cObjGetSingle($this->conf['flagRendering'],$this->conf['flagRendering.']);
01864 } else {
01865
01866
01867 $rowDat = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_language', 'uid='.intval($row['sys_language_uid']).' '.$this->cObj->enableFields('sys_language'));
01868
01869
01870 $flag = $rowDat[0]['flag'];
01871 if ($flag) {
01872 $file = 't3lib/gfx/flags/'.$flag;
01873 $imgInfo = @getimagesize(PATH_site.$file);
01874
01875 if (is_array($imgInfo)) {
01876 $output = '<img src="'.$file.'" '.$imgInfo[3].' title="'.htmlspecialchars($rowDat[0]['title']).'" alt="'.htmlspecialchars($rowDat[0]['title']).'" />';
01877 return $output;
01878 }
01879 }
01880 }
01881 }
01882 return ' ';
01883 }
01884
01892 function makeAccessIndication($id) {
01893 if (is_array($this->fe_groups_required[$id]) && count($this->fe_groups_required[$id])) {
01894 return '<img src="'.t3lib_extMgm::siteRelPath('indexed_search').'pi/res/locked.gif" width="12" height="15" vspace="5" title="'.sprintf($this->pi_getLL('res_memberGroups','',1),implode(',',array_unique($this->fe_groups_required[$id]))).'" alt="" />';
01895 }
01896 }
01897
01906 function linkPage($id,$str,$row=array(),$markUpSwParams=array()) {
01907
01908
01909 $urlParameters = (array)unserialize($row['cHashParams']);
01910
01911
01912 if ($row['data_page_type']) $urlParameters['type'] = $row['data_page_type'];
01913 if ($row['data_page_mp']) $urlParameters['MP'] = $row['data_page_mp'];
01914 if ($row['sys_language_uid']) $urlParameters['L'] = $row['sys_language_uid'];
01915
01916
01917 $urlParameters = array_merge($urlParameters, $markUpSwParams);
01918
01919
01920 if (!is_array($this->domain_records[$id])) {
01921 $this->getPathFromPageId($id);
01922 }
01923
01924
01925 if (count($this->domain_records[$id])) {
01926 reset($this->domain_records[$id]);
01927 $firstDom = current($this->domain_records[$id]);
01928 $scheme = t3lib_div::getIndpEnv('TYPO3_SSL') ? 'https:
01929
01930 $addParams = '';
01931 if (is_array($urlParameters)) {
01932 if (count($urlParameters)) {
01933 $addParams.= t3lib_div::implodeArrayForUrl('',$urlParameters);
01934 }
01935 }
01936
01937 return '<a href="'.$scheme.$firstDom.'/index.php?id='.$id.$addParams.'" target="'.$this->conf['search.']['detect_sys_domain_records.']['target'].'">'.htmlspecialchars($str).'</a>';
01938 } else {
01939 return $this->pi_linkToPage($str,$id,$this->conf['result_link_target'],$urlParameters);
01940 }
01941 }
01942
01950 function getRootLine($id,$pathMP='') {
01951 $identStr = $id.'|'.$pathMP;
01952
01953 if (!isset($this->cache_path[$identStr])) {
01954 $this->cache_rl[$identStr] = $GLOBALS['TSFE']->sys_page->getRootLine($id,$pathMP);
01955 }
01956 return $this->cache_rl[$identStr];
01957 }
01958
01965 function getFirstSysDomainRecordForPage($id) {
01966 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('domainName', 'sys_domain', 'pid='.intval($id).$this->cObj->enableFields('sys_domain'), '', 'sorting');
01967 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
01968 return ereg_replace('\/$','',$row['domainName']);
01969 }
01970
01978 function getPathFromPageId($id,$pathMP='') {
01979
01980 $identStr = $id.'|'.$pathMP;
01981
01982 if (!isset($this->cache_path[$identStr])) {
01983 $this->fe_groups_required[$id] = array();
01984 $this->domain_records[$id] = array();
01985 $rl = $this->getRootLine($id,$pathMP);
01986 $hitRoot = 0;
01987 $path = '';
01988 if (is_array($rl) && count($rl)) {
01989 reset($rl);
01990 while(list($k,$v)=each($rl)) {
01991
01992 if ($v['fe_group'] && ($v['uid']==$id || $v['extendToSubpages'])) {
01993 $this->fe_groups_required[$id][]=$v['fe_group'];
01994 }
01995
01996 if ($this->conf['search.']['detect_sys_domain_records']) {
01997 $sysDName = $this->getFirstSysDomainRecordForPage($v['uid']);
01998 if ($sysDName) {
01999 $this->domain_records[$id][] = $sysDName;
02000
02001 $path = $sysDName.$path;
02002 break;
02003 }
02004 }
02005
02006
02007 if ($v['uid']==$GLOBALS['TSFE']->config['rootLine'][0]['uid']) {
02008 break;
02009 }
02010 $path = '/'.$v['title'].$path;
02011 }
02012 }
02013
02014 $this->cache_path[$identStr] = $path;
02015
02016 if (is_array($this->conf['path_stdWrap.'])) {
02017 $this->cache_path[$identStr] = $this->cObj->stdWrap($this->cache_path[$identStr], $this->conf['path_stdWrap.']);
02018 }
02019 }
02020
02021 return $this->cache_path[$identStr];
02022 }
02023
02030 function getMenu($id) {
02031 if ($this->conf['show.']['LxALLtypes']) {
02032 $output = Array();
02033 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('title,uid', 'pages', 'pid='.intval($id).$this->cObj->enableFields('pages'), '', 'sorting');
02034 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
02035 $output[$row['uid']] = $GLOBALS['TSFE']->sys_page->getPageOverlay($row);
02036 }
02037 return $output;
02038 } else {
02039 return $GLOBALS['TSFE']->sys_page->getMenu($id);
02040 }
02041 }
02042
02049 function multiplePagesType($item_type) {
02050 return is_object($this->external_parsers[$item_type]) && $this->external_parsers[$item_type]->isMultiplePageExtension($item_type);
02051 }
02052
02059 function utf8_to_currentCharset($str) {
02060 return $GLOBALS['TSFE']->csConv($str,'utf-8');
02061 }
02062
02069 function &hookRequest($functionName) {
02070 global $TYPO3_CONF_VARS;
02071
02072
02073 if ($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['pi1_hooks'][$functionName]) {
02074 $hookObj = &t3lib_div::getUserObj($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['pi1_hooks'][$functionName]);
02075 if (method_exists ($hookObj, $functionName)) {
02076 $hookObj->pObj = &$this;
02077 return $hookObj;
02078 }
02079 }
02080 }
02081 }
02082
02083
02084 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/indexed_search/pi/class.tx_indexedsearch.php']) {
02085 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/indexed_search/pi/class.tx_indexedsearch.php']);
02086 }
02087 ?>