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
00108 require_once(PATH_tslib.'class.tslib_pibase.php');
00109 require_once(PATH_tslib.'class.tslib_search.php');
00110 require_once(t3lib_extMgm::extPath('indexed_search').'class.indexer.php');
00111
00112
00123 class tx_indexedsearch extends tslib_pibase {
00124 var $prefixId = 'tx_indexedsearch';
00125 var $scriptRelPath = 'pi/class.tx_indexedsearch.php';
00126 var $extKey = 'indexed_search';
00127
00128 var $join_pages = 0;
00129 var $defaultResultNumber = 10;
00130
00131 var $operator_translate_table = Array (
00132 Array ('+' , 'AND'),
00133 Array ('|' , 'OR'),
00134 Array ('-' , 'AND NOT'),
00135
00136 # Array ('AND' , 'AND'),
00137 # Array ('OR' , 'OR'),
00138 # Array ('NOT' , 'AND NOT'),
00139 );
00140
00141
00142 var $wholeSiteIdList = 0;
00143
00144
00145 var $sWArr = array();
00146 var $optValues = array();
00147 var $firstRow = Array();
00148
00149 var $cache_path = array();
00150 var $cache_rl = array();
00151 var $fe_groups_required = array();
00152 var $domain_records = array();
00153 var $wSelClauses = array();
00154 var $resultSections = array();
00155 var $external_parsers = array();
00156 var $iconFileNameCache = array();
00157 var $lexerObj;
00158 var $templateCode;
00159 var $hiddenFieldList = 'ext, type, defOp, media, order, group, lang, desc, results';
00160
00161
00169 function main($content, $conf) {
00170
00171
00172 $this->conf = $conf;
00173 $this->pi_loadLL();
00174 $this->pi_setPiVarDefaults();
00175
00176
00177 $this->indexerObj = t3lib_div::makeInstance('tx_indexedsearch_indexer');
00178
00179
00180 $this->initialize();
00181
00182
00183
00184 if (is_array($this->sWArr)) {
00185 $content = $this->doSearch($this->sWArr);
00186 }
00187
00188
00189 $content = $this->makeSearchForm($this->optValues).
00190 $this->printRules().
00191 $content;
00192
00193 return $this->pi_wrapInBaseClass($content);
00194 }
00195
00201 function initialize() {
00202 global $TYPO3_CONF_VARS;
00203
00204
00205 if (is_array($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['external_parsers'])) {
00206 foreach ($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['external_parsers'] as $extension => $_objRef) {
00207 $this->external_parsers[$extension] = &t3lib_div::getUserObj($_objRef);
00208
00209
00210 if (!$this->external_parsers[$extension]->softInit($extension)) {
00211 unset($this->external_parsers[$extension]);
00212 }
00213 }
00214 }
00215
00216
00217 $lexerObjRef = $TYPO3_CONF_VARS['EXTCONF']['indexed_search']['lexer'] ?
00218 $TYPO3_CONF_VARS['EXTCONF']['indexed_search']['lexer'] :
00219 'EXT:indexed_search/class.lexer.php:&tx_indexedsearch_lexer';
00220 $this->lexerObj = &t3lib_div::getUserObj($lexerObjRef);
00221
00222
00223 if ($this->piVars['_sections']) $this->piVars['sections'] = $this->piVars['_sections'];
00224
00225
00226 if ($this->piVars['_freeIndexUid']!=='_') $this->piVars['freeIndexUid'] = $this->piVars['_freeIndexUid'];
00227
00228
00229 if ($this->piVars['sword_prev_include'] && $this->piVars['sword_prev']) {
00230 $this->piVars['sword'] = trim($this->piVars['sword_prev']).' '.$this->piVars['sword'];
00231 }
00232
00233 $this->piVars['results'] = t3lib_div::intInRange($this->piVars['results'],1,100000,$this->defaultResultNumber);
00234
00235
00236 $this->optValues = Array(
00237 'type' => Array(
00238 '0' => $this->pi_getLL('opt_type_0'),
00239 '1' => $this->pi_getLL('opt_type_1'),
00240 '2' => $this->pi_getLL('opt_type_2'),
00241 '3' => $this->pi_getLL('opt_type_3'),
00242 '10' => $this->pi_getLL('opt_type_10'),
00243 '20' => $this->pi_getLL('opt_type_20'),
00244 ),
00245 'defOp' => Array(
00246 '0' => $this->pi_getLL('opt_defOp_0'),
00247 '1' => $this->pi_getLL('opt_defOp_1'),
00248 ),
00249 'sections' => Array(
00250 '0' => $this->pi_getLL('opt_sections_0'),
00251 '-1' => $this->pi_getLL('opt_sections_-1'),
00252 '-2' => $this->pi_getLL('opt_sections_-2'),
00253 '-3' => $this->pi_getLL('opt_sections_-3'),
00254
00255 ),
00256 'freeIndexUid' => Array(
00257 '-1' => $this->pi_getLL('opt_freeIndexUid_-1'),
00258 '-2' => $this->pi_getLL('opt_freeIndexUid_-2'),
00259 '0' => $this->pi_getLL('opt_freeIndexUid_0'),
00260 ),
00261 'media' => Array(
00262 '-1' => $this->pi_getLL('opt_media_-1'),
00263 '0' => $this->pi_getLL('opt_media_0'),
00264 '-2' => $this->pi_getLL('opt_media_-2'),
00265 ),
00266 'order' => Array(
00267 'rank_flag' => $this->pi_getLL('opt_order_rank_flag'),
00268 'rank_freq' => $this->pi_getLL('opt_order_rank_freq'),
00269 'rank_first' => $this->pi_getLL('opt_order_rank_first'),
00270 'rank_count' => $this->pi_getLL('opt_order_rank_count'),
00271 'mtime' => $this->pi_getLL('opt_order_mtime'),
00272 'title' => $this->pi_getLL('opt_order_title'),
00273 'crdate' => $this->pi_getLL('opt_order_crdate'),
00274 ),
00275 'group' => Array (
00276 'sections' => $this->pi_getLL('opt_group_sections'),
00277 'flat' => $this->pi_getLL('opt_group_flat'),
00278 ),
00279 'lang' => Array (
00280 -1 => $this->pi_getLL('opt_lang_-1'),
00281 0 => $this->pi_getLL('opt_lang_0'),
00282 ),
00283 'desc' => Array (
00284 '0' => $this->pi_getLL('opt_desc_0'),
00285 '1' => $this->pi_getLL('opt_desc_1'),
00286 ),
00287 'results' => Array (
00288 '10' => '10',
00289 '20' => '20',
00290 '50' => '50',
00291 '100' => '100',
00292 )
00293 );
00294
00295
00296 if ($this->conf['search.']['defaultFreeIndexUidList']) {
00297 $uidList = t3lib_div::intExplode(',', $this->conf['search.']['defaultFreeIndexUidList']);
00298 $indexCfgRecords = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,title','index_config','uid IN ('.implode(',',$uidList).')'.$this->cObj->enableFields('index_config'),'','','','uid');
00299
00300 foreach ($uidList as $uidValue) {
00301 if (is_array($indexCfgRecords[$uidValue])) {
00302 $this->optValues['freeIndexUid'][$uidValue] = $indexCfgRecords[$uidValue]['title'];
00303 }
00304 }
00305 }
00306
00307
00308
00309 if (strlen(trim($this->conf['search.']['mediaList']))) {
00310 $mediaList = implode(',', t3lib_div::trimExplode(',', $this->conf['search.']['mediaList'], 1));
00311 }
00312 foreach ($this->external_parsers as $extension => $obj) {
00313
00314 if ($mediaList && !t3lib_div::inList($mediaList, $extension)) { continue; }
00315
00316 if ($name = $obj->searchTypeMediaTitle($extension)) {
00317 $this->optValues['media'][$extension] = $this->pi_getLL('opt_sections_'.$extension,$name);
00318 }
00319 }
00320
00321
00322
00323 $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');
00324 $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');
00325 $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');
00326
00327
00328 $this->wholeSiteIdList = intval($GLOBALS['TSFE']->config['rootLine'][0]['uid']);
00329
00330
00331
00332 if ($this->conf['show.']['L1sections']) {
00333 $firstLevelMenu = $this->getMenu($this->wholeSiteIdList);
00334 while(list($kk,$mR) = each($firstLevelMenu)) {
00335 if ($mR['doktype']!=5) {
00336 $this->optValues['sections']['rl1_'.$mR['uid']] = trim($this->pi_getLL('opt_RL1').' '.$mR['title']);
00337 if ($this->conf['show.']['L2sections']) {
00338 $secondLevelMenu = $this->getMenu($mR['uid']);
00339 while(list($kk2,$mR2) = each($secondLevelMenu)) {
00340 if ($mR['doktype']!=5) {
00341 $this->optValues['sections']['rl2_'.$mR2['uid']] = trim($this->pi_getLL('opt_RL2').' '.$mR2['title']);
00342 } else unset($secondLevelMenu[$kk2]);
00343 }
00344 $this->optValues['sections']['rl2_'.implode(',',array_keys($secondLevelMenu))] = $this->pi_getLL('opt_RL2ALL');
00345 }
00346 } else unset($firstLevelMenu[$kk]);
00347 }
00348 $this->optValues['sections']['rl1_'.implode(',',array_keys($firstLevelMenu))] = $this->pi_getLL('opt_RL1ALL');
00349 }
00350
00351
00352
00353 if ($this->conf['search.']['rootPidList']) {
00354 $this->wholeSiteIdList = implode(',',t3lib_div::intExplode(',',$this->conf['search.']['rootPidList']));
00355 }
00356
00357
00358 $this->templateCode = $this->cObj->fileResource($this->conf['templateFile']);
00359
00360
00361 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_language', '1=1'.$this->cObj->enableFields('sys_language'));
00362 while($lR = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00363 $this->optValues['lang'][$lR['uid']] = $lR['title'];
00364 }
00365
00366
00367 if ($hookObj = &$this->hookRequest('initialize_postProc')) {
00368 $hookObj->initialize_postProc();
00369 }
00370
00371
00372
00373 foreach ($this->optValues as $kk => $vv) {
00374 if (!isset($this->piVars[$kk])) {
00375 reset($vv);
00376 $this->piVars[$kk] = key($vv);
00377 }
00378 }
00379
00380
00381 if (is_array($this->conf['blind.'])) {
00382 foreach ($this->conf['blind.'] as $kk => $vv) {
00383 if (is_array($vv)) {
00384 foreach ($vv as $kkk => $vvv) {
00385 if (!is_array($vvv) && $vvv && is_array($this->optValues[substr($kk,0,-1)])) {
00386 unset($this->optValues[substr($kk,0,-1)][$kkk]);
00387 }
00388 }
00389 } elseif ($vv) {
00390 unset($this->optValues[$kk]);
00391 }
00392 }
00393 }
00394
00395
00396 $this->sWArr = $this->getSearchWords($this->piVars['defOp']);
00397 }
00398
00414 function getSearchWords($defOp) {
00415
00416 $inSW = substr($this->piVars['sword'],0,200);
00417
00418
00419 $inSW = $GLOBALS['TSFE']->csConvObj->utf8_encode($inSW, $GLOBALS['TSFE']->metaCharset);
00420 $inSW = $GLOBALS['TSFE']->csConvObj->entities_to_utf8($inSW,TRUE);
00421
00422 if ($hookObj = &$this->hookRequest('getSearchWords')) {
00423 return $hookObj->getSearchWords_splitSWords($inSW, $defOp);
00424 } else {
00425
00426 if ($this->piVars['type']==20) {
00427 return array(array('sword'=>trim($inSW), 'oper'=>'AND'));
00428 } else {
00429 $search = t3lib_div::makeInstance('tslib_search');
00430 $search->default_operator = $defOp==1 ? 'OR' : 'AND';
00431 $search->operator_translate_table = $this->operator_translate_table;
00432 $search->register_and_explode_search_string($inSW);
00433
00434 if (is_array($search->sword_array)) {
00435 return $this->procSearchWordsByLexer($search->sword_array);
00436 }
00437 }
00438 }
00439 }
00440
00448 function procSearchWordsByLexer($SWArr) {
00449
00450
00451 $newSWArr = array();
00452
00453
00454 foreach ($SWArr as $wordDef) {
00455 if (!strstr($wordDef['sword'],' ')) {
00456
00457 $res = $this->lexerObj->split2Words($wordDef['sword']);
00458
00459
00460 foreach ($res as $word) {
00461 $newSWArr[] = array('sword'=>$word, 'oper'=>$wordDef['oper']);
00462 }
00463 } else {
00464 $newSWArr[] = $wordDef;
00465 }
00466 }
00467
00468
00469 return $newSWArr;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00492 function doSearch($sWArr) {
00493
00494
00495 $freeIndexUid = $this->piVars['freeIndexUid'];
00496 if ($freeIndexUid==-2) {
00497 $freeIndexUid = $this->conf['search.']['defaultFreeIndexUidList'];
00498 }
00499
00500 $indexCfgs = t3lib_div::intExplode(',',$freeIndexUid);
00501 $accumulatedContent = '';
00502
00503 foreach ($indexCfgs as $freeIndexUid) {
00504
00505 $pt1 = t3lib_div::milliseconds();
00506 if ($hookObj = &$this->hookRequest('getResultRows')) {
00507 $resData = $hookObj->getResultRows($sWArr,$freeIndexUid);
00508 } else {
00509 $resData = $this->getResultRows($sWArr,$freeIndexUid);
00510 }
00511
00512
00513 $pt2 = t3lib_div::milliseconds();
00514 if ($hookObj = &$this->hookRequest('getDisplayResults')) {
00515 $content = $hookObj->getDisplayResults($sWArr, $resData, $freeIndexUid);
00516 } else {
00517 $content = $this->getDisplayResults($sWArr, $resData, $freeIndexUid);
00518 }
00519
00520 $pt3 = t3lib_div::milliseconds();
00521
00522
00523 if (count($indexCfgs)>1) {
00524 if ($freeIndexUid>0) {
00525 list($indexCfgRec) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('title','index_config','uid='.intval($freeIndexUid).$this->cObj->enableFields('index_config'));
00526 $titleString = $indexCfgRec['title'];
00527 } else {
00528 $titleString = $this->pi_getLL('opt_freeIndexUid_header_'.$freeIndexUid);
00529 }
00530 $content = '<h1 class="tx-indexedsearch-category">'.htmlspecialchars($titleString).'</h1>'.$content;
00531 }
00532
00533 $accumulatedContent.=$content;
00534 }
00535
00536
00537 $this->writeSearchStat($sWArr,$resData['count'],array($pt1,$pt2,$pt3));
00538
00539
00540 return $accumulatedContent;
00541 }
00542
00550 function getResultRows($sWArr,$freeIndexUid=-1) {
00551
00552
00553 $GLOBALS['TT']->push('Searching result');
00554 $res = $this->getResultRows_SQLpointer($sWArr,$freeIndexUid);
00555 $GLOBALS['TT']->pull();
00556
00557
00558 if ($res) {
00559
00560 $count = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
00561 $pointer = t3lib_div::intInRange($this->piVars['pointer'], 0, floor($count/$this->piVars['results']));
00562
00563
00564 $c = 0;
00565 $grouping_phashes = array();
00566 $grouping_chashes = array();
00567 $firstRow = Array();
00568 $resultRows = Array();
00569
00570
00571
00572 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00573
00574
00575 if (!$c) {
00576 $firstRow = $row;
00577 }
00578
00579 $row['show_resume'] = $this->checkResume($row);
00580
00581 $phashGr = !in_array($row['phash_grouping'], $grouping_phashes);
00582 $chashGr = !in_array($row['contentHash'].'.'.$row['data_page_id'], $grouping_chashes);
00583 if ($phashGr && $chashGr) {
00584 if ($row['show_resume'] || $this->conf['show.']['forbiddenRecords']) {
00585 if (!$this->multiplePagesType($row['item_type'])) {
00586 $grouping_phashes[] = $row['phash_grouping'];
00587 }
00588 $grouping_chashes[] = $row['contentHash'].'.'.$row['data_page_id'];
00589
00590 $c++;
00591
00592
00593 if ($c > $pointer * $this->piVars['results']) {
00594 $row['result_number'] = $c;
00595 $resultRows[] = $row;
00596
00597 if (($c+1) > ($pointer+1)*$this->piVars['results']) break;
00598 }
00599 } else {
00600 $count--;
00601 }
00602 } else {
00603 $count--;
00604 }
00605 }
00606
00607 return array(
00608 'resultRows' => $resultRows,
00609 'firstRow' => $firstRow,
00610 'count' => $count
00611 );
00612 } else {
00613 return FALSE;
00614 }
00615 }
00616
00624 function getResultRows_SQLpointer($sWArr,$freeIndexUid=-1) {
00625
00626 $list = $this->getPhashList($sWArr);
00627
00628
00629 if ($list) {
00630
00631 $GLOBALS['TT']->push('execFinalQuery');
00632 $res = $this->execFinalQuery($list,$freeIndexUid);
00633 $GLOBALS['TT']->pull();
00634 return $res;
00635 } else {
00636 return FALSE;
00637 }
00638 }
00639
00648 function getDisplayResults($sWArr, $resData, $freeIndexUid=-1) {
00649
00650 if ($resData) {
00651 $GLOBALS['TT']->push('Display Final result');
00652
00653
00654 $this->firstRow = $resData['firstRow'];
00655
00656
00657 $rowcontent = '';
00658 $rowcontent.= $this->compileResult($resData['resultRows'], $freeIndexUid);
00659
00660
00661 if ($resData['count']) {
00662 $this->internal['res_count'] = $resData['count'];
00663 $this->internal['results_at_a_time'] = $this->piVars['results'];
00664 $this->internal['maxPages'] = t3lib_div::intInRange($this->conf['search.']['page_links'],1,100,10);
00665 $addString = ($resData['count']&&$this->piVars['group']=='sections'&&$freeIndexUid<=0 ? ' '.sprintf($this->pi_getLL(count($this->resultSections)>1?'inNsections':'inNsection'),count($this->resultSections)):'');
00666 $browseBox1 = $this->pi_list_browseresults(1,$addString,$this->printResultSectionLinks(),$freeIndexUid);
00667 $browseBox2 = $this->pi_list_browseresults(0,'','',$freeIndexUid);
00668 }
00669
00670
00671 if ($resData['count']) {
00672 $content = $browseBox1.$rowcontent.$browseBox2;
00673 } else {
00674 $content = '<p'.$this->pi_classParam('noresults').'>'.$this->pi_getLL('noResults','',1).'</p>';
00675 }
00676
00677 $GLOBALS['TT']->pull();
00678 } else {
00679 $content.='<p'.$this->pi_classParam('noresults').'>'.$this->pi_getLL('noResults','',1).'</p>';
00680 }
00681
00682
00683 $what = $this->tellUsWhatIsSeachedFor($sWArr).
00684 (substr($this->piVars['sections'],0,2)=='rl'?' '.$this->pi_getLL('inSection','',1).' "'.substr($this->getPathFromPageId(substr($this->piVars['sections'],4)),1).'"':'');
00685 $what = '<div'.$this->pi_classParam('whatis').'>'.$this->cObj->stdWrap($what, $this->conf['whatis_stdWrap.']).'</div>';
00686 $content = $what.$content;
00687
00688
00689 return $content;
00690 }
00691
00700 function compileResult($resultRows, $freeIndexUid=-1) {
00701 $content = '';
00702
00703
00704 $newResultRows = array();
00705 foreach ($resultRows as $row) {
00706 $id = md5($row['phash_grouping']);
00707 if (is_array($newResultRows[$id])) {
00708 if (!$newResultRows[$id]['show_resume'] && $row['show_resume']) {
00709
00710
00711 $subrows = $newResultRows[$id]['_sub'];
00712 unset($newResultRows[$id]['_sub']);
00713 $subrows[] = $newResultRows[$id];
00714
00715
00716 $newResultRows[$id] = $row;
00717 $newResultRows[$id]['_sub'] = $subrows;
00718 } else $newResultRows[$id]['_sub'][] = $row;
00719 } else {
00720 $newResultRows[$id] = $row;
00721 }
00722 }
00723 $resultRows = $newResultRows;
00724 $this->resultSections = array();
00725
00726 if ($freeIndexUid<=0) {
00727 switch($this->piVars['group']) {
00728 case 'sections':
00729
00730 $rl2flag = substr($this->piVars['sections'],0,2)=='rl';
00731 $sections = array();
00732 foreach ($resultRows as $row) {
00733 $id = $row['rl0'].'-'.$row['rl1'].($rl2flag?'-'.$row['rl2']:'');
00734 $sections[$id][] = $row;
00735 }
00736
00737 $this->resultSections = array();
00738
00739 foreach ($sections as $id => $resultRows) {
00740 $rlParts = explode('-',$id);
00741 $theId = $rlParts[2] ? $rlParts[2] : ($rlParts[1]?$rlParts[1]:$rlParts[0]);
00742 $theRLid = $rlParts[2] ? 'rl2_'.$rlParts[2]:($rlParts[1]?'rl1_'.$rlParts[1]:'0');
00743
00744 $sectionName = $this->getPathFromPageId($theId);
00745 if ($sectionName{0} == '/') $sectionName = substr($sectionName,1);
00746
00747 if (!trim($sectionName)) {
00748 $sectionTitleLinked = $this->pi_getLL('unnamedSection','',1).':';
00749 } else {
00750 $onclick = 'document.'.$this->prefixId.'[\''.$this->prefixId.'[_sections]\'].value=\''.$theRLid.'\';document.'.$this->prefixId.'.submit();return false;';
00751 $sectionTitleLinked = '<a href="#" onclick="'.htmlspecialchars($onclick).'">'.htmlspecialchars($sectionName).':</a>';
00752 }
00753 $this->resultSections[$id] = array($sectionName,count($resultRows));
00754
00755
00756 $content.= $this->makeSectionHeader($id,$sectionTitleLinked,count($resultRows));
00757
00758
00759 foreach ($resultRows as $row) {
00760 $content.= $this->printResultRow($row);
00761 }
00762 }
00763 break;
00764 default:
00765 foreach ($resultRows as $row) {
00766 $content.= $this->printResultRow($row);
00767 }
00768 break;
00769 }
00770 } else {
00771 foreach ($resultRows as $row) {
00772 $content.= $this->printResultRow($row);
00773 }
00774 }
00775
00776 return '<div'.$this->pi_classParam('res').'>'.$content.'</div>';
00777 }
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00802 function getPhashList($sWArr) {
00803
00804
00805 $c=0;
00806 $totalHashList = array();
00807 $this->wSelClauses = array();
00808
00809
00810 foreach ($sWArr as $k => $v) {
00811
00812 $sWord = $v['sword'];
00813 $theType = (string)$this->piVars['type'];
00814 if (strstr($sWord,' ')) $theType = 20;
00815
00816 $GLOBALS['TT']->push('SearchWord "'.$sWord.'" - $theType='.$theType);
00817
00818 $res = '';
00819 $wSel='';
00820
00821
00822 switch($theType) {
00823 case '1':
00824 $wSel = "IW.baseword LIKE '%".$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_words')."%'";
00825 $res = $this->execPHashListQuery($wSel,' AND is_stopword=0');
00826 break;
00827 case '2':
00828 $wSel = "IW.baseword LIKE '".$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_words')."%'";
00829 $res = $this->execPHashListQuery($wSel,' AND is_stopword=0');
00830 break;
00831 case '3':
00832 $wSel = "IW.baseword LIKE '%".$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_words')."'";
00833 $res = $this->execPHashListQuery($wSel,' AND is_stopword=0');
00834 break;
00835 case '10':
00836 $wSel = 'IW.metaphone = '.$this->indexerObj->metaphone($sWord);
00837 $res = $this->execPHashListQuery($wSel,' AND is_stopword=0');
00838 break;
00839 case '20':
00840 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00841 'ISEC.phash',
00842 'index_section ISEC, index_fulltext IFT',
00843 'IFT.fulltextdata LIKE \'%'.$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_fulltext').'%\' AND
00844 ISEC.phash = IFT.phash
00845 '.$this->sectionTableWhere(),
00846 'ISEC.phash'
00847 );
00848 $wSel = '1=1';
00849
00850 if ($this->piVars['type']==20) $this->piVars['order'] = 'mtime';
00851 break;
00852 default:
00853 $wSel = 'IW.wid = '.$hash = $this->indexerObj->md5inthash($sWord);
00854 $res = $this->execPHashListQuery($wSel,' AND is_stopword=0');
00855 break;
00856 }
00857
00858
00859 $this->wSelClauses[] = $wSel;
00860
00861
00862 if ($res) {
00863
00864
00865 $phashList = array();
00866 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00867 $phashList[] = $row['phash'];
00868 }
00869 $GLOBALS['TYPO3_DB']->sql_free_result($res);
00870
00871
00872 if ($c) {
00873 switch($v['oper']) {
00874 case 'OR':
00875 $totalHashList = array_unique(array_merge($phashList,$totalHashList));
00876 break;
00877 case 'AND NOT':
00878 $totalHashList = array_diff($totalHashList,$phashList);
00879 break;
00880 default:
00881 $totalHashList = array_intersect($totalHashList,$phashList);
00882 break;
00883 }
00884 } else {
00885 $totalHashList = $phashList;
00886 }
00887 }
00888
00889 $GLOBALS['TT']->pull();
00890 $c++;
00891 }
00892
00893 return implode(',',$totalHashList);
00894 }
00895
00903 function execPHashListQuery($wordSel,$plusQ='') {
00904 return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00905 'IR.phash',
00906 'index_words IW,
00907 index_rel IR,
00908 index_section ISEC',
00909 $wordSel.'
00910 AND IW.wid=IR.wid
00911 AND ISEC.phash = IR.phash
00912 '.$this->sectionTableWhere().'
00913 '.$plusQ,
00914 'IR.phash'
00915 );
00916 }
00917
00923 function sectionTableWhere() {
00924 $out = $this->wholeSiteIdList<0 ? '' : 'AND ISEC.rl0 IN ('.$this->wholeSiteIdList.')';
00925
00926 $match = '';
00927 if (substr($this->piVars['sections'],0,4)=='rl1_') {
00928 $list = implode(',',t3lib_div::intExplode(',',substr($this->piVars['sections'],4)));
00929 $out.= 'AND ISEC.rl1 IN ('.$list.')';
00930 $match = TRUE;
00931 } elseif (substr($this->piVars['sections'],0,4)=='rl2_') {
00932 $list = implode(',',t3lib_div::intExplode(',',substr($this->piVars['sections'],4)));
00933 $out.= 'AND ISEC.rl2 IN ('.$list.')';
00934 $match = TRUE;
00935 } elseif (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['addRootLineFields'])) {
00936
00937 foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['addRootLineFields'] as $fieldName => $rootLineLevel) {
00938 if (substr($this->piVars['sections'],0,strlen($fieldName)+1)==$fieldName.'_') {
00939 $list = implode(',',t3lib_div::intExplode(',',substr($this->piVars['sections'],strlen($fieldName)+1)));
00940 $out.= 'AND ISEC.'.$fieldName.' IN ('.$list.')';
00941 $match = TRUE;
00942 break;
00943 }
00944 }
00945 }
00946
00947
00948 if (!$match) {
00949 switch((string)$this->piVars['sections']) {
00950 case '-1':
00951 $out.= ' AND ISEC.page_id='.$GLOBALS['TSFE']->id;
00952 break;
00953 case '-2':
00954 $out.= ' AND ISEC.rl2=0';
00955 break;
00956 case '-3':
00957 $out.= ' AND ISEC.rl2>0';
00958 break;
00959 }
00960 }
00961
00962 return $out;
00963 }
00964
00970 function mediaTypeWhere() {
00971
00972 switch((string)$this->piVars['media']) {
00973 case '0':
00974 $out = 'AND IP.item_type='.$GLOBALS['TYPO3_DB']->fullQuoteStr('0', 'index_phash');;
00975 break;
00976 case '-2':
00977 $out = 'AND IP.item_type!='.$GLOBALS['TYPO3_DB']->fullQuoteStr('0', 'index_phash');;
00978 break;
00979 case '-1':
00980 $out='';
00981 break;
00982 default:
00983 $out = 'AND IP.item_type='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->piVars['media'], 'index_phash');
00984 break;
00985 }
00986
00987 return $out;
00988 }
00989
00995 function languageWhere() {
00996 if ($this->piVars['lang']>=0) {
00997 return 'AND IP.sys_language_uid='.intval($this->piVars['lang']);
00998 }
00999 }
01000
01007 function freeIndexUidWhere($freeIndexUid) {
01008
01009 if ($freeIndexUid>=0) {
01010
01011
01012 list($indexCfgRec) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('indexcfgs','index_config','type=5 AND uid='.intval($freeIndexUid).$this->cObj->enableFields('index_config'));
01013 if (is_array($indexCfgRec)) {
01014 $refs = t3lib_div::trimExplode(',',$indexCfgRec['indexcfgs']);
01015 $list = array(-99);
01016 foreach ($refs as $ref) {
01017 list($table,$uid) = t3lib_div::revExplode('_',$ref,2);
01018 switch ($table) {
01019 case 'index_config':
01020 list($idxRec) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid','index_config','uid='.intval($uid).$this->cObj->enableFields('index_config'));
01021 if ($idxRec) $list[] = $uid;
01022 break;
01023 case 'pages':
01024 $indexCfgRecordsFromPid = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid','index_config','pid='.intval($uid).$this->cObj->enableFields('index_config'));
01025 foreach ($indexCfgRecordsFromPid as $idxRec) {
01026 $list[] = $idxRec['uid'];
01027 }
01028 break;
01029 }
01030 }
01031
01032 $list = array_unique($list);
01033 } else {
01034 $list = array(intval($freeIndexUid));
01035 }
01036
01037 return ' AND IP.freeIndexUid IN ('.implode(',',$list).')';
01038 }
01039 }
01040
01048 function execFinalQuery($list,$freeIndexUid=-1) {
01049
01050
01051 $page_join = '';
01052 $page_where = '';
01053
01054
01055 $freeIndexUidClause = $this->freeIndexUidWhere($freeIndexUid);
01056
01057
01058 if ($hookObj = &$this->hookRequest('execFinalQuery_idList')) {
01059 $page_where = $hookObj->execFinalQuery_idList($list);
01060 } elseif ($this->join_pages) {
01061 $page_join = ',
01062 pages';
01063 $page_where = 'pages.uid = ISEC.page_id
01064 '.$this->cObj->enableFields('pages').'
01065 AND pages.no_search=0
01066 AND pages.doktype<200
01067 ';
01068 } elseif ($this->wholeSiteIdList>=0) {
01069 $siteIdNumbers = t3lib_div::intExplode(',',$this->wholeSiteIdList);
01070 $id_list=array();
01071 while(list(,$rootId)=each($siteIdNumbers)) {
01072 $id_list[] = $this->cObj->getTreeList($rootId,9999,0,0,'','').$rootId;
01073 }
01074 $page_where = 'ISEC.page_id IN ('.implode(',',$id_list).')';
01075 } else {
01076 $page_where = ' 1=1 ';
01077 }
01078
01079
01080
01081 if (substr($this->piVars['order'],0,5)=='rank_') {
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111 switch($this->piVars['order']) {
01112 case 'rank_flag':
01113
01114 $grsel = 'MAX(IR.flags) AS order_val1, SUM(IR.freq) AS order_val2';
01115 $orderBy = 'order_val1'.$this->isDescending().',order_val2'.$this->isDescending();
01116 break;
01117 case 'rank_first':
01118 $grsel = 'AVG(IR.first) AS order_val';
01119 $orderBy = 'order_val'.$this->isDescending(1);
01120 break;
01121 case 'rank_count':
01122 $grsel = 'SUM(IR.count) AS order_val';
01123 $orderBy = 'order_val'.$this->isDescending();
01124 break;
01125 default:
01126 $grsel = 'SUM(IR.freq) AS order_val';
01127 $orderBy = 'order_val'.$this->isDescending();
01128 break;
01129 }
01130
01131
01132 $wordSel='('.implode(' OR ',$this->wSelClauses).') AND ';
01133
01134 return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
01135 'ISEC.*, IP.*, '
01136 .$grsel,
01137 'index_words IW,
01138 index_rel IR,
01139 index_section ISEC,
01140 index_phash IP'.
01141 $page_join,
01142 $wordSel.'
01143 IP.phash IN ('.$list.') '.
01144 $this->mediaTypeWhere().' '.
01145 $this->languageWhere().
01146 $freeIndexUidClause.'
01147 AND IW.wid=IR.wid
01148 AND ISEC.phash = IR.phash
01149 AND IP.phash = IR.phash
01150 AND '.$page_where,
01151 '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',
01152 $orderBy
01153 );
01154 } else {
01155
01156 $orderBy = '';
01157 switch((string)$this->piVars['order']) {
01158 case 'title':
01159 $orderBy = 'IP.item_title'.$this->isDescending();
01160 break;
01161 case 'crdate':
01162 $orderBy = 'IP.item_crdate'.$this->isDescending();
01163 break;
01164 case 'mtime':
01165 $orderBy = 'IP.item_mtime'.$this->isDescending();
01166 break;
01167 }
01168
01169 return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
01170 'ISEC.*, IP.*',
01171 'index_phash IP,index_section ISEC'.$page_join,
01172 'IP.phash IN ('.$list.') '.
01173 $this->mediaTypeWhere().' '.
01174 $this->languageWhere().
01175 $freeIndexUidClause.'
01176 AND IP.phash = ISEC.phash
01177 AND '.$page_where,
01178 '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',
01179 $orderBy
01180 );
01181 }
01182 }
01183
01191 function checkResume($row) {
01192
01193
01194
01195
01196 if ($row['freeIndexUid']) {
01197 return TRUE;
01198 }
01199
01200
01201 if ($row['item_type']) {
01202
01203
01204
01205
01206 $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'));
01207 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
01208 #debug("Look up for external media '".$row['data_filename']."': phash:".$row['phash_t3'].' YES - ('.$GLOBALS['TSFE']->gr_list.")!",1);
01209 return TRUE;
01210 } else {
01211 #debug("Look up for external media '".$row['data_filename']."': phash:".$row['phash_t3'].' NO - ('.$GLOBALS['TSFE']->gr_list.")!",1);
01212 return FALSE;
01213 }
01214 } else {
01215 if (strcmp($row['gr_list'],$GLOBALS['TSFE']->gr_list)) {
01216
01217 $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'));
01218 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
01219 #debug('Checking on it ...'.$row['item_title'].'/'.$row['phash'].' - YES ('.$GLOBALS['TSFE']->gr_list.")",1);
01220 return TRUE;
01221 } else {
01222 #debug('Checking on it ...'.$row['item_title'].'/'.$row['phash']." - NOPE",1);
01223 return FALSE;
01224 }
01225 } else {
01226 #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);
01227 return TRUE;
01228 }