"TYPO3 4.0.1: typo3_src-4.0.1/typo3/sysext/indexed_search/pi/class.tx_indexedsearch.php Source File", "datetime" => "Sat Dec 2 19:22:33 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>

class.tx_indexedsearch.php

00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2001-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
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';        // Same as class name
00125         var $scriptRelPath = 'pi/class.tx_indexedsearch.php';    // Path to this script relative to the extension dir.
00126         var $extKey = 'indexed_search';    // The extension key.
00127 
00128         var $join_pages = 0;    // See document for info about this flag...
00129         var $defaultResultNumber = 10;
00130 
00131         var $operator_translate_table = Array (         // case-sensitive. Defines the words, which will be operators between words
00132                 Array ('+' , 'AND'),
00133                 Array ('|' , 'OR'),
00134                 Array ('-' , 'AND NOT'),
00135                         // english
00136 #               Array ('AND' , 'AND'),
00137 #               Array ('OR' , 'OR'),
00138 #               Array ('NOT' , 'AND NOT'),
00139         );
00140 
00141                 // Internal variable
00142         var $wholeSiteIdList = 0;               // Root-page PIDs to search in (rl0 field where clause, see initialize() function)
00143 
00144                 // Internals:
00145         var $sWArr = array();                   // Search Words and operators
00146         var $optValues = array();               // Selector box values for search configuration form
00147         var $firstRow = Array();                // Will hold the first row in result - used to calculate relative hit-ratings.
00148 
00149         var $cache_path = array();              // Caching of page path
00150         var $cache_rl = array();                // Caching of root line data
00151         var $fe_groups_required = array();      // Required fe_groups memberships for display of a result.
00152         var $domain_records = array();          // Domain records (?)
00153         var $wSelClauses = array();             // Select clauses for individual words
00154         var $resultSections = array();          // Page tree sections for search result.
00155         var $external_parsers = array();        // External parser objects
00156         var $iconFileNameCache = array();       // Storage of icons....
00157         var $lexerObj;                          // Lexer object
00158         var $templateCode;                      // Will hold the content of $conf['templateFile']
00159         var $hiddenFieldList = 'ext, type, defOp, media, order, group, lang, desc, results';
00160 
00161 
00169         function main($content, $conf)    {
00170 
00171                         // Initialize:
00172                 $this->conf = $conf;
00173                 $this->pi_loadLL();
00174                 $this->pi_setPiVarDefaults();
00175 
00176                         // Initialize the indexer-class - just to use a few function (for making hashes)
00177                 $this->indexerObj = t3lib_div::makeInstance('tx_indexedsearch_indexer');
00178 
00179                         // Initialize:
00180                 $this->initialize();
00181 
00182                         // Do search:
00183                         // If there were any search words entered...
00184                 if (is_array($this->sWArr))     {
00185                         $content = $this->doSearch($this->sWArr);
00186                 }
00187 
00188                         // Finally compile all the content, form, messages and results:
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                         // Initialize external document parsers for icon display and other soft operations
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                                         // Init parser and if it returns false, unset its entry again:
00210                                 if (!$this->external_parsers[$extension]->softInit($extension)) {
00211                                         unset($this->external_parsers[$extension]);
00212                                 }
00213                         }
00214                 }
00215 
00216                         // Init lexer (used to post-processing of search words)
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                         // If "_sections" is set, this value overrides any existing value.
00223                 if ($this->piVars['_sections'])         $this->piVars['sections'] = $this->piVars['_sections'];
00224 
00225                         // If "_sections" is set, this value overrides any existing value.
00226                 if ($this->piVars['_freeIndexUid']!=='_')               $this->piVars['freeIndexUid'] = $this->piVars['_freeIndexUid'];
00227 
00228                         // Add previous search words to current
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                         // Selector-box values defined here:
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                                 // Here values like "rl1_" and "rl2_" + a rootlevel 1/2 id can be added to perform searches in rootlevel 1+2 specifically. The id-values can even be commaseparated. Eg. "rl1_1,2" would search for stuff inside pages on menu-level 1 which has the uid's 1 and 2.
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                         // Free Index Uid:
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                         // Add media to search in:
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                                 // Skip unwanted extensions
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                         // Add operators for various languages
00322                         // Converts the operators to UTF-8 and lowercase
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                         // This is the id of the site root. This value may be a commalist of integer (prepared for this)
00328                 $this->wholeSiteIdList = intval($GLOBALS['TSFE']->config['rootLine'][0]['uid']);
00329 
00330                         // Creating levels for section menu:
00331                         // This selects the first and secondary menus for the "sections" selector - so we can search in sections and sub sections.
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                         // Setting the list of root PIDs for the search. Notice, these page IDs MUST have a TypoScript template with root flag on them! Basically this list is used to select on the "rl0" field and page ids are registered as "rl0" only if a TypoScript template record with root flag is there.
00352                         // This happens AFTER the use of $this->wholeSiteIdList above because the above will then fetch the menu for the CURRENT site - regardless of this kind of searching here. Thus a general search will lookup in the WHOLE database while a specific section search will take the current sections...
00353                 if ($this->conf['search.']['rootPidList'])      {
00354                         $this->wholeSiteIdList = implode(',',t3lib_div::intExplode(',',$this->conf['search.']['rootPidList']));
00355                 }
00356 
00357                         // Load the template
00358                 $this->templateCode = $this->cObj->fileResource($this->conf['templateFile']);
00359 
00360                         // Add search languages:
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                         // Calling hook for modification of initialized content
00367                 if ($hookObj = &$this->hookRequest('initialize_postProc'))      {
00368                         $hookObj->initialize_postProc();
00369                 }
00370 
00371                         // Default values set:
00372                         // Setting first values in optValues as default values IF there is not corresponding piVar value set already.
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                         // Blind selectors:
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) {        // If value is not set, unset the option array.
00390                                         unset($this->optValues[$kk]);
00391                                 }
00392                         }
00393                 }
00394 
00395                         // This gets the search-words into the $sWArr:
00396                 $this->sWArr = $this->getSearchWords($this->piVars['defOp']);
00397         }
00398 
00414         function getSearchWords($defOp) {
00415                         // Shorten search-word string to max 200 bytes (does NOT take multibyte charsets into account - but never mind, shortening the string here is only a run-away feature!)
00416                 $inSW = substr($this->piVars['sword'],0,200);
00417 
00418                         // Convert to UTF-8 + conv. entities (was also converted during indexing!)
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                         // Init output variable:
00451                 $newSWArr = array();
00452 
00453                         // Traverse the search word array:
00454                 foreach ($SWArr as $wordDef)    {
00455                         if (!strstr($wordDef['sword'],' '))     {       // No space in word (otherwise it might be a sentense in quotes like "there is").
00456                                         // Split the search word by lexer:
00457                                 $res = $this->lexerObj->split2Words($wordDef['sword']);
00458 
00459                                         // Traverse lexer result and add all words again:
00460                                 foreach ($res as $word) {
00461                                         $newSWArr[] = array('sword'=>$word, 'oper'=>$wordDef['oper']);
00462                                 }
00463                         } else {
00464                                 $newSWArr[] = $wordDef;
00465                         }
00466                 }
00467 
00468                         // Return result:
00469                 return $newSWArr;
00470         }
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480         /*****************************
00481          *
00482          * Main functions
00483          *
00484          *****************************/
00485 
00492         function doSearch($sWArr)       {
00493 
00494                         // Find free index uid:
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                                 // Get result rows:
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                                 // Display search results:
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                                 // Create header if we are searching more than one indexing configuration:
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                         // Write search statistics
00537                 $this->writeSearchStat($sWArr,$resData['count'],array($pt1,$pt2,$pt3));
00538 
00539                         // Return content:
00540                 return $accumulatedContent;
00541         }
00542 
00550         function getResultRows($sWArr,$freeIndexUid=-1) {
00551 
00552                         // Getting SQL result pointer:
00553                         $GLOBALS['TT']->push('Searching result');
00554                 $res = $this->getResultRows_SQLpointer($sWArr,$freeIndexUid);
00555                         $GLOBALS['TT']->pull();
00556 
00557                         // Organize and process result:
00558                 if ($res)       {
00559 
00560                         $count = $GLOBALS['TYPO3_DB']->sql_num_rows($res);      // Total search-result count
00561                         $pointer = t3lib_div::intInRange($this->piVars['pointer'], 0, floor($count/$this->piVars['results']));  // The pointer is set to the result page that is currently being viewed
00562 
00563                                 // Initialize result accumulation variables:
00564                         $c = 0; // Result pointer: Counts up the position in the current search-result
00565                         $grouping_phashes = array();    // Used to filter out duplicates.
00566                         $grouping_chashes = array();    // Used to filter out duplicates BASED ON cHash.
00567                         $firstRow = Array();    // Will hold the first row in result - used to calculate relative hit-ratings.
00568                         $resultRows = Array();  // Will hold the results rows for display.
00569 
00570                                 // Now, traverse result and put the rows to be displayed into an array
00571                                 // Each row should contain the fields from 'ISEC.*, IP.*' combined + artificial fields "show_resume" (boolean) and "result_number" (counter)
00572                         while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))       {
00573 
00574                                         // Set first row:
00575                                 if (!$c)        {
00576                                         $firstRow = $row;
00577                                 }
00578 
00579                                 $row['show_resume'] = $this->checkResume($row); // Tells whether we can link directly to a document or not (depends on possible right problems)
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'])    {       // Only if the resume may be shown are we going to filter out duplicates...
00585                                                 if (!$this->multiplePagesType($row['item_type']))       {       // Only on documents which are not multiple pages documents
00586                                                         $grouping_phashes[] = $row['phash_grouping'];
00587                                                 }
00588                                                 $grouping_chashes[] = $row['contentHash'].'.'.$row['data_page_id'];
00589 
00590                                                 $c++;   // Increase the result pointer
00591 
00592                                                         // All rows for display is put into resultRows[]
00593                                                 if ($c > $pointer * $this->piVars['results'])   {
00594                                                         $row['result_number'] = $c;
00595                                                         $resultRows[] = $row;
00596                                                                 // This may lead to a problem: If the result check is not stopped here, the search will take longer. However the result counter will not filter out grouped cHashes/pHashes that were not processed yet.
00597                                                         if (($c+1) > ($pointer+1)*$this->piVars['results'])     break;
00598                                                 }
00599                                         } else {
00600                                                 $count--;       // Skip this row if the user cannot view it (missing permission)
00601                                         }
00602                                 } else {
00603                                         $count--;       // For each time a phash_grouping document is found (which is thus not displayed) the search-result count is reduced, so that it matches the number of rows displayed.
00604                                 }
00605                         }
00606 
00607                         return array(
00608                                                 'resultRows' => $resultRows,
00609                                                 'firstRow' => $firstRow,
00610                                                 'count' => $count
00611                                         );
00612                 } else {        // No results found:
00613                         return FALSE;
00614                 }
00615         }
00616 
00624         function getResultRows_SQLpointer($sWArr,$freeIndexUid=-1)      {
00625                                 // This SEARCHES for the searchwords in $sWArr AND returns a COMPLETE list of phash-integers of the matches.
00626                 $list = $this->getPhashList($sWArr);
00627 
00628                         // Perform SQL Search / collection of result rows array:
00629                 if ($list)      {
00630                                 // Do the search:
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                         // Perform display of result rows array:
00650                 if ($resData)   {
00651                         $GLOBALS['TT']->push('Display Final result');
00652 
00653                                 // Set first selected row (for calculation of ranking later)
00654                         $this->firstRow = $resData['firstRow'];
00655 
00656                                 // Result display here:
00657                         $rowcontent = '';
00658                         $rowcontent.= $this->compileResult($resData['resultRows'], $freeIndexUid);
00659 
00660                                 // Browsing box:
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                                 // Browsing nav, bottom.
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                         // Print a message telling which words we searched for, and in which sections etc.
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').'><p>'.$what.'</p></div>';
00686                 $content = $what.$content;
00687 
00688                         // Return content:
00689                 return $content;
00690         }
00691 
00700         function compileResult($resultRows, $freeIndexUid=-1)   {
00701                 $content = '';
00702 
00703                         // Transfer result rows to new variable, performing some mapping of sub-results etc.
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']) {       // swapping:
00709 
00710                                                 // Remove old
00711                                         $subrows = $newResultRows[$id]['_sub'];
00712                                         unset($newResultRows[$id]['_sub']);
00713                                         $subrows[] = $newResultRows[$id];
00714 
00715                                                 // Insert new:
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                                                         // Add content header:
00756                                                 $content.= $this->makeSectionHeader($id,$sectionTitleLinked,count($resultRows));
00757 
00758                                                         // Render result rows:
00759                                                 foreach ($resultRows as $row)   {
00760                                                         $content.= $this->printResultRow($row);
00761                                                 }
00762                                         }
00763                                 break;
00764                                 default:        // flat:
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          *      Searching functions (SQL)
00792          *
00793          ***********************************/
00794 
00802         function getPhashList($sWArr)   {
00803 
00804                         // Initialize variables:
00805                 $c=0;
00806                 $totalHashList = array();       // This array accumulates the phash-values
00807                 $this->wSelClauses = array();
00808 
00809                         // Traverse searchwords; for each, select all phash integers and merge/diff/intersect them with previous word (based on operator)
00810                 foreach ($sWArr as $k => $v)    {
00811                                 // Making the query for a single search word based on the search-type
00812                         $sWord = $v['sword'];   // $GLOBALS['TSFE']->csConvObj->conv_case('utf-8',$v['sword'],'toLower');       // lower-case all of them...
00813                         $theType = (string)$this->piVars['type'];
00814                         if (strstr($sWord,' ')) $theType = 20;  // If there are spaces in the search-word, make a full text search instead.
00815 
00816                         $GLOBALS['TT']->push('SearchWord "'.$sWord.'" - $theType='.$theType);
00817 
00818                         $res = '';
00819                         $wSel='';
00820 
00821                                 // Perform search for word:
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';               // If there is a fulltext search for a sentence there is a likeliness that sorting cannot be done by the rankings from the rel-table (because no relations will exist for the sentence in the word-table). So therefore mtime is used instaed. It is not required, but otherwise some hits may be left out.
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                                 // Accumulate the word-select clauses
00859                         $this->wSelClauses[] = $wSel;
00860 
00861                                 // If there was a query to do, then select all phash-integers which resulted from this.
00862                         if ($res)       {
00863 
00864                                         // Get phash list by searching for it:
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                                         // Here the phash list are merged with the existing result based on whether we are dealing with OR, NOT or AND operations.
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:        // AND...
00881                                                         $totalHashList = array_intersect($totalHashList,$phashList);
00882                                                 break;
00883                                         }
00884                                 } else {
00885                                         $totalHashList = $phashList;    // First search
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                                 // Traversing user configured fields to see if any of those are used to limit search to a section:
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                         // If no match above, test the static types:
00948                 if (!$match)    {
00949                         switch((string)$this->piVars['sections'])       {
00950                                 case '-1':              // '-1' => 'Only this page',
00951                                         $out.= ' AND ISEC.page_id='.$GLOBALS['TSFE']->id;
00952                                 break;
00953                                 case '-2':              // '-2' => 'Top + level 1',
00954                                         $out.= ' AND ISEC.rl2=0';
00955                                 break;
00956                                 case '-3':              // '-3' => 'Level 2 and out',
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':               // '0' => 'Kun TYPO3 sider',
00974                                 $out = 'AND IP.item_type='.$GLOBALS['TYPO3_DB']->fullQuoteStr('0', 'index_phash');;
00975                         break;
00976                         case '-2':              // All external documents
00977                                 $out = 'AND IP.item_type!='.$GLOBALS['TYPO3_DB']->fullQuoteStr('0', 'index_phash');;
00978                         break;
00979                         case '-1':      // All content
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)   {       // -1 is the same as ALL language.
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                                 // First, look if the freeIndexUid is a meta configuration:
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);     // Default value to protect against empty array.
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                         // Setting up methods of filtering results based on page types, access, etc.
01051                 $page_join = '';
01052                 $page_where = '';
01053 
01054                         // Indexing configuration clause:
01055                 $freeIndexUidClause = $this->freeIndexUidWhere($freeIndexUid);
01056 
01057                         // Calling hook for alternative creation of page ID list
01058                 if ($hookObj = &$this->hookRequest('execFinalQuery_idList'))    {
01059                         $page_where = $hookObj->execFinalQuery_idList($list);
01060                 } elseif ($this->join_pages)    {       // Alternative to getting all page ids by ->getTreeList() where "excludeSubpages" is NOT respected.
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) {  // Collecting all pages IDs in which to search; filtering out ALL pages that are not accessible due to enableFields. Does NOT look for "no_search" field!
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 {        // Disable everything... (select all)
01076                         $page_where = ' 1=1 ';
01077                 }
01078 
01079 
01080                         // If any of the ranking sortings are selected, we must make a join with the word/rel-table again, because we need to calculate ranking based on all search-words found.
01081                 if (substr($this->piVars['order'],0,5)=='rank_')        {
01082                                 /*
01083                                          OK there were some fancy calculations promoted by Graeme Merrall:
01084 
01085                                         "However, regarding relevance you probably want to look at something like
01086                                         Salton's formula which is a good easy way to measure relevance.
01087                                         Oracle Intermedia uses this and it's pretty simple:
01088                                         Score can be between 0 and 100, but the top-scoring document in the query
01089                                         will not necessarily have a score of 100 -- scoring is relative, not
01090                                         absolute. This means that scores are not comparable across indexes, or even
01091                                         across different queries on the same index. Score for each document is
01092                                         computed using the standard Salton formula:
01093 
01094                                             3f(1+log(N/n))
01095 
01096                                         Where f is the frequency of the search term in the document, N is the total
01097                                         number of rows in the table, and n is the number of rows which contain the
01098                                         search term. This is converted into an integer in the range 0 - 100.
01099 
01100                                         There's a good doc on it at
01101                                         http://ls6-www.informatik.uni-dortmund.de/bib/fulltext/ir/Pfeifer:97/
01102                                         although it may be a little complex for what you require so just pick the
01103                                         relevant parts out.
01104                                         "
01105 
01106                                         However I chose not to go with this for several reasons.
01107                                         I do not claim that my ways of calculating importance here is the best.
01108                                         ANY (better) suggestion for ranking calculation is accepted! (as long as they are shipped with tested code in exchange for this.)
01109                                 */
01110 
01111                         switch($this->piVars['order'])  {
01112                                 case 'rank_flag':       // This gives priority to word-position (max-value) so that words in title, keywords, description counts more than in content.
01113                                                                         // The ordering is refined with the frequency sum as well.
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':      // Results in average position of search words on page. Must be inversely sorted (low numbers are closer to top)
01118                                         $grsel = 'AVG(IR.first) AS order_val';
01119                                         $orderBy = 'order_val'.$this->isDescending(1);
01120                                 break;
01121                                 case 'rank_count':      // Number of words found
01122                                         $grsel = 'SUM(IR.count) AS order_val';
01123                                         $orderBy = 'order_val'.$this->isDescending();
01124                                 break;
01125                                 default:        // Frequency sum. I'm not sure if this is the best way to do it (make a sum...). Or should it be the average?
01126                                         $grsel = 'SUM(IR.freq) AS order_val';
01127                                         $orderBy = 'order_val'.$this->isDescending();
01128                                 break;
01129                         }
01130 
01131                                 // So, words are imploded into an OR statement (no "sentence search" should be done here - may deselect results)
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',
01152                                                 $orderBy
01153                                         );
01154                 } else {        // Otherwise, if sorting are done with the pages table or other fields, there is no need for joining with the rel/word tables:
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',
01179                                                 $orderBy
01180                                         );
01181                 }
01182         }
01183 
01191         function checkResume($row)      {
01192 
01193                         // If the record is indexed by an indexing configuration, just show it.
01194                         // At least this is needed for external URLs and files.
01195                         // For records we might need to extend this - for instance block display if record is access restricted.
01196                 if ($row['freeIndexUid'])       {
01197                         return TRUE;
01198                 }
01199 
01200                         // Evaluate regularly indexed pages based on item_type:
01201                 if ($row['item_type'])  {       // External media:
01202                                 // For external media we will check the access of the parent page on which the media was linked from.
01203                                 // "phash_t3" is the phash of the parent TYPO3 page row which initiated the indexing of the documents in this section.
01204                                 // So, selecting for the grlist records belonging to the parent phash-row where the current users gr_list exists will help us to know.
01205                                 // If this is NOT found, there is still a theoretical possibility that another user accessible page would display a link, so maybe the resume of such a document here may be unjustified hidden. But better safe than sorry.
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 {        // Ordinary TYPO3 pages:
01215                         if (strcmp($row['gr_list'],$GLOBALS['TSFE']->gr_list))  {
01216                                         // Selecting for the grlist records belonging to the phash-row where the current users gr_list exists. If it is found it is proof that this user has direct access to the phash-rows content although he did not himself initiate the indexing...
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                         }
01229                 }
01230         }
01231 
01238         function isDescending($inverse=FALSE)   {
01239                 $desc = $this->piVars['desc'];
01240                 if ($inverse)   $desc=!$desc;
01241                 return !$desc ? ' DESC':'';
01242         }
01243 
01252         function writeSearchStat($sWArr,$count,$pt)     {
01253                 $insertFields = array(
01254                         'searchstring' => $this->piVars['sword'],
01255                         'searchoptions' => serialize(array($this->piVars,$sWArr,$pt)),
01256                         'feuser_id' => intval($this->fe_user->user['uid']),                     // fe_user id, integer
01257                         'cookie' => $this->fe_user->id,                                         // cookie as set or retrieve. If people has cookies disabled this will vary all the time...
01258                         'IP' => t3lib_div::getIndpEnv('REMOTE_ADDR'),           // Remote IP address
01259                         'hits' => intval($count),                                                       // Number of hits on the search.
01260                         'tstamp' => $GLOBALS['EXEC_TIME']                                       // Time stamp
01261                 );
01262 
01263                 $GLOBALS['TYPO3_DB']->exec_INSERTquery('index_stat_search', $insertFields);
01264                 $newId = $GLOBALS['TYPO3_DB']->sql_insert_id();
01265 
01266                 if ($newId)     {
01267                         foreach ($sWArr as $val)        {
01268                                 $insertFields = array(
01269                                         'word' => $val['sword'],                // $GLOBALS['TSFE']->csConvObj->conv_case('utf-8', $val['sword'], 'toLower'),
01270                                         'index_stat_search_id' => $newId,
01271                                         'tstamp' => $GLOBALS['EXEC_TIME'],              // Time stamp
01272                                         'pageid' => $GLOBALS['TSFE']->id        //search page id for indexed search stats
01273                                 );
01274 
01275                                 $GLOBALS['TYPO3_DB']->exec_INSERTquery('index_stat_word', $insertFields);
01276                         }
01277                 }
01278         }
01279 
01280 
01281 
01282 
01283 
01284 
01285 
01286 
01287 
01288 
01289 
01290 
01291 
01292         /***********************************
01293          *
01294          * HTML output functions
01295          *
01296          ***********************************/
01297 
01304         function makeSearchForm($optValues)     {
01305                 $html = $this->cObj->getSubpart($this->templateCode, '###SEARCH_FORM###');
01306 
01307                         // Multilangual text
01308                 $substituteArray = array('searchFor', 'extResume', 'atATime', 'orderBy', 'fromSection', 'searchIn', 'match', 'style', 'freeIndexUid');
01309                 foreach ($substituteArray as $marker)   {
01310                         $markerArray['###FORM_'.strtoupper($marker).'###'] = $this->pi_getLL('form_'.$marker,'',1);
01311                 }
01312 
01313                 $markerArray['###FORM_SUBMIT###'] = $this->pi_getLL('submit_button_label','',1);
01314 
01315                         // Adding search field value
01316                 $markerArray['###SWORD_VALUE###'] = htmlspecialchars($this->piVars['sword']);
01317 
01318                         // Additonal keyword => "Add to current search words"
01319                 if ($this->conf['show.']['clearSearchBox'] && $this->conf['show.']['clearSearchBox.']['enableSubSearchCheckBox'])       {
01320                         $markerArray['###SWORD_PREV_VALUE###'] = htmlspecialchars($this->conf['show.']['clearSearchBox'] ? '' : $this->piVars['sword']);
01321                         $markerArray['###SWORD_PREV_INCLUDE_CHECKED###'] = $this->piVars['sword_prev_include'] ? ' checked="checked"':'';
01322                         $markerArray['###ADD_TO_CURRENT_SEARCH###'] = $this->pi_getLL('makerating_addToCurrentSearch','',1);
01323                 } else {
01324                         $html = $this->cObj->substituteSubpart($html, '###ADDITONAL_KEYWORD###', '');
01325                 }
01326 
01327                 $markerArray['###ACTION_URL###'] = $this->pi_getPageLink($GLOBALS['TSFE']->id, $GLOBALS['TSFE']->sPre);
01328 
01329                 $hiddenFieldCode = $this->cObj->getSubpart($this->templateCode, '###HIDDEN_FIELDS###');
01330                 $hiddenFieldCode = preg_replace('/^\n\t(.+)/ms', '$1', $hiddenFieldCode);               // Remove first newline and tab (cosmetical issue)
01331                 $hiddenFieldArr = array();
01332 
01333                 foreach (t3lib_div::trimExplode(',',$this->hiddenFieldList) as $fieldName)      {
01334                         $hiddenFieldMarkerArray = array();
01335                         $hiddenFieldMarkerArray['###HIDDEN_FIELDNAME###'] = $this->prefixId.'['.$fieldName.']';
01336                         $hiddenFieldMarkerArray['###HIDDEN_VALUE###'] = (string)$this->piVars[$fieldName];
01337 
01338                         $hiddenFieldArr[$fieldName] = $this->cObj->substituteMarkerArrayCached($hiddenFieldCode, $hiddenFieldMarkerArray, array(), array());
01339                 }
01340 
01341                         // Extended search
01342                 if ($this->piVars['ext'])       {
01343 
01344                                 // Search for
01345                         if ((!is_array($optValues['type']) && !is_array($optValues['defOp'])) || ($this->conf['blind.']['type'] && $this->conf['blind.']['defOp']))     {
01346                                 $html = $this->cObj->substituteSubpart($html, '###SELECT_SEARCH_FOR###', '');
01347                         } else {
01348                                 if (is_array($optValues['type']) && !$this->conf['blind.']['type'])     {
01349                                         unset($hiddenFieldArr['type']);
01350                                         $markerArray['###SELECTBOX_TYPE_VALUES###'] = $this->renderSelectBoxValues($this->piVars['type'],$optValues['type']);
01351                                 } else {
01352                                         $html = $this->cObj->substituteSubpart($html, '###SELECT_SEARCH_TYPE###', '');
01353                                 }
01354 
01355                                 if (is_array($optValues['defOp']) || !$this->conf['blind.']['defOp'])   {
01356                                         $markerArray['###SELECTBOX_DEFOP_VALUES###'] = $this->renderSelectBoxValues($this->piVars['defOp'],$optValues['defOp']);
01357                                 } else {
01358                                         $html = $this->cObj->substituteSubpart($html, '###SELECT_SEARCH_DEFOP###', '');
01359                                 }
01360                         }
01361 
01362                                 // Search in
01363                         if ((!is_array($optValues['media']) && !is_array($optValues['lang'])) || ($this->conf['blind.']['media'] && $this->conf['blind.']['lang']))     {
01364                                 $html = $this->cObj->substituteSubpart($html, '###SELECT_SEARCH_IN###', '');
01365                         } else {
01366                                 if (is_array($optValues['media']) && !$this->conf['blind.']['media'])   {
01367                                         unset($hiddenFieldArr['media']);
01368                                         $markerArray['###SELECTBOX_MEDIA_VALUES###'] = $this->renderSelectBoxValues($this->piVars['media'],$optValues['media']);
01369                                 } else {
01370                                         $html = $this->cObj->substituteSubpart($html, '###SELECT_SEARCH_MEDIA###', '');
01371                                 }
01372 
01373                                 if (is_array($optValues['lang']) || !$this->conf['blind.']['lang'])     {
01374                                         unset($hiddenFieldArr['lang']);
01375                                         $markerArray['###SELECTBOX_LANG_VALUES###'] = $this->renderSelectBoxValues($this->piVars['lang'],$optValues['lang']);
01376                                 } else {
01377                                         $html = $this->cObj->substituteSubpart($html, '###SELECT_SEARCH_LANG###', '');
01378                                 }
01379                         }
01380 
01381                                 // Sections
01382                         if (!is_array($optValues['sections']) || $this->conf['blind.']['sections'])     {
01383                                 $html = $this->cObj->substituteSubpart($html, '###SELECT_SECTION###', '');
01384                         } else {
01385                                 $markerArray['###SELECTBOX_SECTIONS_VALUES###'] = $this->renderSelectBoxValues($this->piVars['sections'],$optValues['sections']);
01386                         }
01387 
01388                                 // Free Indexing Configurations:
01389                         if (!is_array($optValues['freeIndexUid']) || $this->conf['blind.']['freeIndexUid'])     {
01390                                 $html = $this->cObj->substituteSubpart($html, '###SELECT_FREEINDEXUID###', '');
01391                         } else {
01392                                 $markerArray['###SELECTBOX_FREEINDEXUIDS_VALUES###'] = $this->renderSelectBoxValues($this->piVars['freeIndexUid'],$optValues['freeIndexUid']);
01393                         }
01394 
01395                                 // Sorting
01396                         if (!is_array($optValues['order']) || !is_array($optValues['desc']) || $this->conf['blind.']['order'])  {
01397                                 $html = $this->cObj->substituteSubpart($html, '###SELECT_ORDER###', '');
01398                         } else {
01399                                 unset($hiddenFieldArr['order']);
01400                                 unset($hiddenFieldArr['desc']);
01401                                 unset($hiddenFieldArr['results']);
01402                                 $markerArray['###SELECTBOX_ORDER_VALUES###'] = $this->renderSelectBoxValues($this->piVars['order'],$optValues['order']);
01403                                 $markerArray['###SELECTBOX_DESC_VALUES###'] = $this->renderSelectBoxValues($this->piVars['desc'],$optValues['desc']);
01404                                 $markerArray['###SELECTBOX_RESULTS_VALUES###'] = $this->renderSelectBoxValues($this->piVars['results'],$optValues['results']);
01405                         }
01406 
01407                                 // Limits
01408                         if (!is_array($optValues['results']) || !is_array($optValues['results']) || $this->conf['blind.']['results'])   {
01409                                 $html = $this->cObj->substituteSubpart($html, '###SELECT_RESULTS###', '');
01410                         } else {
01411                                 $markerArray['###SELECTBOX_RESULTS_VALUES###'] = $this->renderSelectBoxValues($this->piVars['results'],$optValues['results']);
01412                         }
01413 
01414                                 // Grouping
01415                         if (!is_array($optValues['group']) || $this->conf['blind.']['group'])   {
01416                                 $html = $this->cObj->substituteSubpart($html, '###SELECT_GROUP###', '');
01417                         } else {
01418                                 unset($hiddenFieldArr['group']);
01419                                 $markerArray['###SELECTBOX_GROUP_VALUES###'] = $this->renderSelectBoxValues($this->piVars['group'],$optValues['group']);
01420                         }
01421 
01422                         if ($this->conf['blind.']['extResume']) {
01423                                 $html = $this->cObj->substituteSubpart($html, '###SELECT_EXTRESUME###', '');
01424                         } else {
01425                                 $markerArray['###EXT_RESUME_CHECKED###'] = $this->piVars['extResume'] ? ' checked="checked"' : '';
01426                         }
01427 
01428                 } else {        // Extended search
01429                         $html = $this->cObj->substituteSubpart($html, '###SEARCH_FORM_EXTENDED###', '');
01430                 }
01431 
01432                 if($this->conf['show.']['advancedSearchLink'])  {
01433                         $linkToOtherMode = ($this->piVars['ext'] ?
01434                                 $this->pi_getPageLink($GLOBALS['TSFE']->id,$GLOBALS['TSFE']->sPre,array($this->prefixId.'[ext]'=>0)) :
01435                                 $this->pi_getPageLink($GLOBALS['TSFE']->id,$GLOBALS['TSFE']->sPre,array($this->prefixId.'[ext]'=>1))
01436                         );
01437 
01438                         $markerArray['###LINKTOOTHERMODE###'] = '<a href="'.htmlspecialchars($linkToOtherMode).'">'.$this->pi_getLL($this->piVars['ext']?'link_regularSearch':'link_advancedSearch', '', 1).'</a>';
01439                 } else {
01440                         $markerArray['###LINKTOOTHERMODE###'] = '';
01441                 }
01442 
01443                         // Write all hidden fields
01444                 $html = $this->cObj->substituteSubpart($html, '###HIDDEN_FIELDS###', implode('',$hiddenFieldArr));
01445 
01446                 $substitutedContent = $this->cObj->substituteMarkerArrayCached($html, $markerArray, array(), array());
01447 
01448                 return $substitutedContent;
01449         }
01450 
01458         function renderSelectBoxValues($value,$optValues)       {
01459                 if (is_array($optValues))       {
01460                         $opt=array();
01461                         $isSelFlag=0;
01462                         foreach ($optValues as $k=>$v)  {
01463                                 $sel = (!strcmp($k,$value) ? ' selected="selected"' : '');
01464                                 if ($sel)       { $isSelFlag++; }
01465                                 $opt[]='<option value="'.htmlspecialchars($k).'"'.$sel.'>'.htmlspecialchars($v).'</option>';
01466                         }
01467 
01468                         return implode('',$opt);
01469                 }
01470         }
01471 
01477         function printRules()   {
01478                 if ($this->conf['show.']['rules'])      {
01479 
01480                         $html = $this->cObj->getSubpart($this->templateCode, '###RULES###');
01481 
01482                         $markerArray['###RULES_HEADER###'] = $this->pi_getLL('rules_header','',1);
01483                         $markerArray['###RULES_TEXT###'] = nl2br(trim($this->pi_getLL('rules_text','',1)));
01484 
01485                         $substitutedContent = $this->cObj->substituteMarkerArrayCached($html, $markerArray, array(), array());
01486 
01487                         return '<div'.$this->pi_classParam('rules').'>'.$this->cObj->stdWrap($substitutedContent, $this->conf['rules_stdWrap.']).'</div>';
01488                 }
01489         }
01490 
01496         function printResultSectionLinks()      {
01497                 if (count($this->resultSections))       {
01498                         $lines = array();
01499 
01500                         $html = $this->cObj->getSubpart($this->templateCode, '###RESULT_SECTION_LINKS###');
01501                         $item = $this->cObj->getSubpart($this->templateCode, '###RESULT_SECTION_LINKS_LINK###');
01502 
01503                         foreach ($this->resultSections as $id => $dat)  {
01504                                 $markerArray = array();
01505 
01506                                 $aBegin = '<a href="'.htmlspecialchars($GLOBALS['TSFE']->anchorPrefix.'#anchor_'.md5($id)).'">';
01507                                 $aContent = htmlspecialchars(trim($dat[0]) ? trim($dat[0]) : $this->pi_getLL('unnamedSection')).
01508                                                 ' ('.$dat[1].' '.$this->pi_getLL($dat[1]>1 ? 'word_pages' : 'word_page','',1).')';
01509                                 $aEnd = '</a>';
01510 
01511                                 $markerArray['###LINK###'] = $aBegin . $aContent . $aEnd;
01512 
01513                                 $links[] = $this->cObj->substituteMarkerArrayCached($item, $markerArray, array(), array());
01514                         }
01515 
01516                         $html = $this->cObj->substituteMarkerArrayCached($html, array('###LINKS###' => implode('',$links)), array(), array());
01517 
01518                         return '<div'.$this->pi_classParam('sectionlinks').'>'.$this->cObj->stdWrap($html, $this->conf['sectionlinks_stdWrap.']).'</div>';
01519                 }
01520         }
01521 
01530         function makeSectionHeader($id, $sectionTitleLinked, $countResultRows)  {
01531 
01532                 $html = $this->cObj->getSubpart($this->templateCode, '###SECTION_HEADER###');
01533 
01534                 $markerArray['###ANCHOR_URL###'] = 'anchor_'.md5($id);
01535                 $markerArray['###SECTION_TITLE###'] = $sectionTitleLinked;
01536                 $markerArray['###RESULT_COUNT###'] = $countResultRows;
01537                 $markerArray['###RESULT_NAME###'] = $this->pi_getLL('word_page'.($countResultRows>1 ? 's' : ''));
01538 
01539                 $substitutedContent = $this->cObj->substituteMarkerArrayCached($html, $markerArray, array(), array());
01540 
01541                 return $substitutedContent;
01542         }
01543 
01551         function printResultRow($row, $headerOnly=0)    {
01552 
01553                         // Get template content:
01554                 $tmplContent = $this->prepareResultRowTemplateData($row, $headerOnly);
01555 
01556                 if ($hookObj = &$this->hookRequest('printResultRow'))   {
01557                         return $hookObj->printResultRow($row, $headerOnly, $tmplContent);
01558                 } else {
01559 
01560                         $html = $this->cObj->getSubpart($this->templateCode, '###RESULT_OUTPUT###');
01561 
01562                         if (!is_array($row['_sub']))    {
01563                                 $html = $this->cObj->substituteSubpart($html, '###ROW_SUB###', '');
01564                         }
01565 
01566                         if (!$headerOnly)       {
01567                                 $html = $this->cObj->substituteSubpart($html, '###ROW_SHORT###', '');
01568 
01569                         } elseif ($headerOnly==1) {
01570                                 $html = $this->cObj->substituteSubpart($html, '###ROW_LONG###', '');
01571                         } elseif ($headerOnly==2) {
01572                                 $html = $this->cObj->substituteSubpart($html, '###ROW_SHORT###', '');
01573                                 $html = $this->cObj->substituteSubpart($html, '###ROW_LONG###', '');
01574                         }
01575 
01576                         if (is_array($tmplContent))     {
01577                                 foreach ($tmplContent AS $k => $v)      {
01578                                         $markerArray['###'.strtoupper($k).'###'] = $v;
01579                                 }
01580                         }
01581 
01582                                 // Description text
01583                         $markerArray['###TEXT_ITEM_SIZE###'] = $this->pi_getLL('res_size','',1);
01584                         $markerArray['###TEXT_ITEM_CRDATE###'] = $this->pi_getLL('res_created','',1);
01585                         $markerArray['###TEXT_ITEM_MTIME###'] = $this->pi_getLL('res_modified','',1);
01586                         $markerArray['###TEXT_ITEM_PATH###'] = $this->pi_getLL('res_path','',1);
01587 
01588                         $html = $this->cObj->substituteMarkerArrayCached($html, $markerArray, array(), array());
01589 
01590                                 // If there are subrows (eg. subpages in a PDF-file or if a duplicate page is selected due to user-login (phash_grouping))
01591                         if (is_array($row['_sub']))     {
01592                                 if ($this->multiplePagesType($row['item_type']))        {
01593 
01594                                         $html = str_replace('###TEXT_ROW_SUB###', $this->pi_getLL('res_otherMatching','',1), $html);
01595 
01596                                         foreach ($row['_sub'] as $subRow)       {
01597                                                 $html .= $this->printResultRow($subRow,1);
01598                                         }
01599                                 } else {
01600 
01601                                         $markerArray['###TEXT_ROW_SUB###'] = $this->pi_getLL('res_otherMatching','',1);
01602 
01603                                         $html = str_replace('###TEXT_ROW_SUB###', $this->pi_getLL('res_otherPageAsWell','',1), $html);
01604                                 }
01605                         }
01606 
01607                         return $html;
01608                 }
01609         }
01610 
01620         function pi_list_browseresults($showResultCount=1,$addString='',$addPart='',$freeIndexUid=-1)   {
01621 
01622                         // Initializing variables:
01623                 $pointer=$this->piVars['pointer'];
01624                 $count=$this->internal['res_count'];
01625                 $results_at_a_time = t3lib_div::intInRange($this->internal['results_at_a_time'],1,1000);
01626                 $maxPages = t3lib_div::intInRange($this->internal['maxPages'],1,100);
01627                 $pageCount = ceil($count/$results_at_a_time);
01628                 $sTables = '';
01629 
01630                 if ($pageCount > 1)     {       // only show the result browser if more than one page is needed
01631                         $pointer=intval($pointer);
01632                         $links=array();
01633 
01634                                 // Make browse-table/links:
01635                         if ($pointer>0) {       // all pages after the 1st one
01636                                 $links[]='<li>'.$this->makePointerSelector_link($this->pi_getLL('pi_list_browseresults_prev','< Previous',1),$pointer-1,$freeIndexUid).'</li>';
01637                         }
01638 
01639                         for($a=0;$a<$pageCount;$a++)    {
01640                                 $min = max(0, $pointer+1-ceil($maxPages/2));
01641                                 $max = $min+$maxPages;
01642                                 if($max>$pageCount)     {
01643                                         $min = $min - ($max-$pageCount);
01644                                 }
01645 
01646                                 if($a >= $min && $a < $max)     {
01647                                         if($a==$pointer)        {
01648                                                 $links[]='<li'.$this->pi_classParam('browselist-currentPage').'><strong>'.$this->makePointerSelector_link(trim($this->pi_getLL('pi_list_browseresults_page','Page',1).' '.($a+1)),$a,$freeIndexUid).'</strong></li>';
01649                                         } else {
01650                                                 $links[]='<li>'.$this->makePointerSelector_link(trim($this->pi_getLL('pi_list_browseresults_page','Page',1).' '.($a+1)),$a,$freeIndexUid).'</li>';
01651                                         }
01652                                 }
01653                         }
01654                         if ($pointer+1 < $pageCount)    {
01655                                 $links[]='<li>'.$this->makePointerSelector_link($this->pi_getLL('pi_list_browseresults_next','Next >',1),$pointer+1,$freeIndexUid).'</li>';
01656                         }
01657                 }
01658 
01659                 $pR1 = $pointer*$results_at_a_time+1;
01660                 $pR2 = $pointer*$results_at_a_time+$results_at_a_time;
01661                 if(is_array($links))    {
01662                         $addPart .= '
01663                 <ul class="browsebox">
01664                         '.implode('',$links).'
01665                 </ul>';
01666                 }
01667 
01668                 $label = $this->pi_getLL('pi_list_browseresults_display','Displaying results ###TAG_BEGIN###%s to %s###TAG_END### out of ###TAG_BEGIN###%s###TAG_END###');
01669                 $label = str_replace('###TAG_BEGIN###','<strong>',$label);
01670                 $label = str_replace('###TAG_END###','</strong>',$label);
01671 
01672                 $sTables = '<div'.$this->pi_classParam('browsebox').'>'.
01673                         ($showResultCount ? '<p>'.sprintf(
01674                                 $label,
01675                                 $pR1,
01676                                 min(array($this->internal['res_count'],$pR2)),
01677                                 $this->internal['res_count']
01678                                 ).$addString.'</p>':''
01679                         ).$addPart.'</div>';
01680 
01681                 return $sTables;
01682         }
01683 
01684 
01685 
01686 
01687 
01688 
01689 
01690 
01691 
01692 
01693 
01694 
01695         /***********************************
01696          *
01697          * Support functions for HTML output (with a minimum of fixed markup)
01698          *
01699          ***********************************/
01700 
01708         function prepareResultRowTemplateData($row, $headerOnly)        {
01709 
01710                         // Initialize:
01711                 $specRowConf = $this->getSpecialConfigForRow($row);
01712                 $CSSsuffix = $specRowConf['CSSsuffix']?'-'.$specRowConf['CSSsuffix']:'';
01713 
01714                         // If external media, link to the media-file instead.
01715                 if ($row['item_type'])  {               // External media
01716                         if ($row['show_resume'])        {       // Can link directly.
01717                                 $title = '<a href="'.htmlspecialchars($row['data_filename']).'">'.htmlspecialchars($this->makeTitle($row)).'</a>';
01718                         } else {        // Suspicious, so linking to page instead...
01719                                 $copy_row = $row;
01720                                 unset($copy_row['cHashParams']);
01721                                 $title = $this->linkPage($row['page_id'],htmlspecialchars($this->makeTitle($row)),$copy_row);
01722                         }
01723                 } else {        // Else the page:
01724 
01725                                 // Prepare search words for markup in content:
01726                         if ($this->conf['forwardSearchWordsInResultLink'])      {
01727                                 $markUpSwParams = array('no_cache' => 1);
01728                                 foreach ($this->sWArr as $d)    {
01729                                         $markUpSwParams['sword_list'][] = $d['sword'];
01730                                 }
01731                         } else {
01732                                 $markUpSwParams = array();
01733                         }
01734                         $title = $this->linkPage($row['data_page_id'],htmlspecialchars($this->makeTitle($row)),$row,$markUpSwParams);
01735                 }
01736 
01737                 $tmplContent = array();
01738                 $tmplContent['title'] = $title;
01739                 $tmplContent['result_number'] = $this->conf['show.']['resultNumber'] ? $row['result_number'].': ' : '&nbsp;';
01740                 $tmplContent['icon'] = $this->makeItemTypeIcon($row['item_type'],'',$specRowConf);
01741                 $tmplContent['rating'] = $this->makeRating($row);
01742                 $tmplContent['description'] = $this->makeDescription($row,$this->piVars['extResume'] && !$headerOnly?0:1);
01743                 $tmplContent = $this->makeInfo($row,$tmplContent);
01744                 $tmplContent['access'] = $this->makeAccessIndication($row['page_id']);
01745                 $tmplContent['language'] = $this->makeLanguageIndication($row);
01746                 $tmplContent['CSSsuffix'] = $CSSsuffix;
01747 
01748                         // Post processing with hook.
01749                 if ($hookObj = &$this->hookRequest('prepareResultRowTemplateData_postProc'))    {
01750                         $tmplContent = $hookObj->prepareResultRowTemplateData_postProc($tmplContent, $row, $headerOnly);
01751                 }
01752 
01753                 return $tmplContent;
01754         }
01755 
01762         function tellUsWhatIsSeachedFor($sWArr) {
01763 
01764                         // Init:
01765                 $searchingFor = '';
01766                 $c=0;
01767 
01768                         // Traverse search words:
01769                 foreach ($sWArr as $k => $v)    {
01770                         if ($c) {
01771                                 switch($v['oper'])      {
01772                                         case 'OR':
01773                                                 $searchingFor.= ' '.$this->pi_getLL('searchFor_or','',1).' '.$this->wrapSW($this->utf8_to_currentCharset($v['sword']));
01774                                         break;
01775                                         case 'AND NOT':
01776                                                 $searchingFor.= ' '.$this->pi_getLL('searchFor_butNot','',1).' '.$this->wrapSW($this->utf8_to_currentCharset($v['sword']));
01777                                         break;
01778                                         default:        // AND...
01779                                                 $searchingFor.= ' '.$this->pi_getLL('searchFor_and','',1).' '.$this->wrapSW($this->utf8_to_currentCharset($v['sword']));
01780                                         break;
01781                                 }
01782                         } else {
01783                                 $searchingFor = $this->pi_getLL('searchFor','',1).' '.$this->wrapSW($this->utf8_to_currentCharset($v['sword']));
01784                         }
01785                         $c++;
01786                 }
01787                 return $searchingFor;
01788         }
01789 
01796         function wrapSW($str)   {
01797                 return '"<span'.$this->pi_classParam('sw').'>'.htmlspecialchars($str).'</span>"';
01798         }
01799 
01808         function renderSelectBox($name,$value,$optValues)       {
01809                 if (is_array($optValues))       {
01810                         $opt = array();
01811                         $isSelFlag = 0;
01812 
01813                         foreach ($optValues as $k => $v)        {
01814                                 $sel = (!strcmp($k,$value) ? ' selected="selected"' : '');
01815                                 if ($sel)       $isSelFlag++;
01816                                 $opt[] = '<option value="'.htmlspecialchars($k).'"'.$sel.'>'.htmlspecialchars($v).'</option>';
01817                         }
01818 
01819                         return '<select name="'.$name.'">'.implode('',$opt).'</select>';
01820                 }
01821         }
01822 
01832         function makePointerSelector_link($str,$p,$freeIndexUid)        {
01833                 $onclick = 'document.'.$this->prefixId.'[\''.$this->prefixId.'[pointer]\'].value=\''.$p.'\';'.
01834                                         'document.'.$this->prefixId.'[\''.$this->prefixId.'[_freeIndexUid]\'].value=\''.rawurlencode($freeIndexUid).'\';'.
01835                                         'document.'.$this->prefixId.'.submit();return false;';
01836                 return '<a href="#" onclick="'.htmlspecialchars($onclick).'">'.$str.'</a>';
01837         }
01838 
01847         function makeItemTypeIcon($it,$alt='',$specRowConf)     {
01848                 if (!isset($this->iconFileNameCache[$it]))      {
01849                         $this->iconFileNameCache[$it] = '';
01850 
01851                                 // If TypoScript is used to render the icon:
01852                         if (is_array($this->conf['iconRendering.']))    {
01853                                 $this->cObj->setCurrentVal($it);
01854                                 $this->iconFileNameCache[$it] = $this->cObj->cObjGetSingle($this->conf['iconRendering'],$this->conf['iconRendering.']);
01855                         } else { // ... otherwise, get flag from sys_language record:
01856 
01857                                         // Default creation / finding of icon:
01858                                 $icon = '';
01859                                 if ($it==='0')  {
01860                                         if (is_array($specRowConf['pageIcon.']))        {
01861                                                 $this->iconFileNameCache[$it] = $this->cObj->IMAGE($specRowConf['pageIcon.']);
01862                                         } else {
01863                                                 $icon = 'EXT:indexed_search/pi/res/pages.gif';
01864                                         }
01865                                 } elseif ($this->external_parsers[$it]) {
01866                                         $icon = $this->external_parsers[$it]->getIcon($it);
01867                                 }
01868 
01869                                 if ($icon)      {
01870                                         $fullPath = t3lib_div::getFileAbsFileName($icon);
01871 
01872                                         if ($fullPath)  {
01873                                                 $info = @getimagesize($fullPath);
01874                                                 $iconPath = substr($fullPath,strlen(PATH_site));
01875                                                 $this->iconFileNameCache[$it] = is_array($info) ? '<img src="'.$iconPath.'" '.$info[3].' title="'.htmlspecialchars($alt).'" alt="" />' : '';
01876                                         }
01877                                 }
01878                         }
01879                 }
01880                 return $this->iconFileNameCache[$it];
01881         }
01882 
01889         function makeRating($row)       {
01890 
01891                 switch((string)$this->piVars['order'])  {
01892                         case 'rank_count':              // Number of occurencies on page
01893                                 return $row['order_val'].' '.$this->pi_getLL('maketitle_matches');
01894                         break;
01895                         case 'rank_first':      // Close to top of page
01896                                 return ceil(t3lib_div::intInRange(255-$row['order_val'],1,255)/255*100).'%';
01897                         break;
01898                         case 'rank_flag':       // Based on priority assigned to <title> / <meta-keywords> / <meta-description> / <body>
01899                                 if ($this->firstRow['order_val2'])      {
01900                                         $base = $row['order_val1']*256; // (3 MSB bit, 224 is highest value of order_val1 currently)
01901                                         $freqNumber = $row['order_val2']/$this->firstRow['order_val2']*pow(2,12);       // 15-3 MSB = 12
01902                                         $total = t3lib_div::intInRange($base+$freqNumber,0,32767);
01903                                         #debug($total);
01904                                         return ceil(log($total)/log(32767)*100).'%';
01905                                 }
01906                         break;
01907                         case 'rank_freq':       // Based on frequency
01908                                 $max = 10000;
01909                                 $total = t3lib_div::intInRange($row['order_val'],0,$max);
01910 #                               debug($total);
01911                                 return ceil(log($total)/log($max)*100).'%';
01912                         break;
01913                         case 'crdate':  // Based on creation date
01914                                 return $this->cObj->calcAge(time()-$row['item_crdate'],0); // ,$conf['age']
01915                         break;
01916                         case 'mtime':   // Based on modification time
01917                                 return $this->cObj->calcAge(time()-$row['item_mtime'],0); // ,$conf['age']
01918                         break;
01919                         default:        // fx. title
01920                                 return '&nbsp;';
01921                         break;
01922                 }
01923         }
01924 
01933         function makeDescription($row,$noMarkup=0,$lgd=180)     {
01934                 if ($row['show_resume'])        {
01935                         if (!$noMarkup) {
01936                                 $markedSW = '';
01937                                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'index_fulltext', 'phash='.intval($row['phash']));
01938                                 if ($ftdrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {
01939                                                 // Cut HTTP references after some length
01940                                         $content = preg_replace('/(http:\/\/[^ ]{60})([^ ]+)/i', '$1...', $ftdrow['fulltextdata']);
01941                                         $markedSW = $this->markupSWpartsOfString($content);
01942                                 }
01943                                 $GLOBALS['TYPO3_DB']->sql_free_result($res);
01944                         }
01945 
01946                         if (!trim($markedSW))   {
01947                                 $outputStr = $GLOBALS['TSFE']->csConvObj->crop('utf-8',$row['item_description'],$lgd);
01948                                 $outputStr = htmlspecialchars($outputStr);
01949                         }
01950                         $output = $this->utf8_to_currentCharset($outputStr ? $outputStr : $markedSW);
01951                 } else {
01952                         $output = '<span class="noResume">'.$this->pi_getLL('res_noResume','',1).'</span>';
01953                 }
01954 
01955                 return $output;
01956         }
01957 
01964         function markupSWpartsOfString($str)    {
01965 
01966                         // Init:
01967                 $str = str_replace('&nbsp;',' ',t3lib_parsehtml::bidir_htmlspecialchars($str,-1));
01968                 $str = preg_replace('/\s\s+/',' ',$str);
01969                 $swForReg = array();
01970 
01971                         // Prepare search words for regex:
01972                 foreach ($this->sWArr as $d)    {
01973                         $swForReg[] = quotemeta($d['sword']);
01974                 }
01975                 $regExString = '('.implode('|',$swForReg).')';
01976 
01977                         // Split and combine:
01978                 $parts = preg_split('/'.$regExString.'/i', ' '.$str.' ', 20000, PREG_SPLIT_DELIM_CAPTURE);
01979 #debug($parts,$regExString);
01980                         // Constants:
01981                 $summaryMax = 300;
01982                 $postPreLgd = 60;
01983                 $postPreLgd_offset = 5;
01984                 $divider = ' ... ';
01985 
01986                 $occurencies = (count($parts)-1)/2;
01987                 if ($occurencies)       {
01988                         $postPreLgd = t3lib_div::intInRange($summaryMax/$occurencies,$postPreLgd,$summaryMax/2);
01989                 }
01990 
01991                         // Variable:
01992                 $summaryLgd = 0;
01993                 $output = array();
01994 
01995                         // Shorten in-between strings:
01996                 foreach ($parts as $k => $strP) {
01997                         if (($k%2)==0)  {
01998 
01999                                         // Find length of the summary part:
02000                                 $strLen = $GLOBALS['TSFE']->csConvObj->strlen('utf-8', $parts[$k]);
02001                                 $output[$k] = $parts[$k];
02002 
02003                                         // Possibly shorten string:
02004                                 if (!$k)        {       // First entry at all (only cropped on the frontside)
02005                                         if ($strLen > $postPreLgd)      {
02006                                                 $output[$k] = $divider.ereg_replace('^[^[:space:]]+[[:space:]]','',$GLOBALS['TSFE']->csConvObj->crop('utf-8',$parts[$k],-($postPreLgd-$postPreLgd_offset)));
02007                                         }
02008                                 } elseif ($summaryLgd > $summaryMax || !isset($parts[$k+1])) {  // In case summary length is exceed OR if there are no more entries at all:
02009                                         if ($strLen > $postPreLgd)      {
02010                                                 $output[$k] = ereg_replace('[[:space:]][^[:space:]]+$','',$GLOBALS['TSFE']->csConvObj->crop('utf-8',$parts[$k],$postPreLgd-$postPreLgd_offset)).$divider;
02011                                         }
02012                                 } else {        // In-between search words:
02013                                         if ($strLen > $postPreLgd*2)    {
02014                                                 $output[$k] = ereg_replace('[[:space:]][^[:space:]]+$','',$GLOBALS['TSFE']->csConvObj->crop('utf-8',$parts[$k],$postPreLgd-$postPreLgd_offset)).
02015                                                                                 $divider.
02016                                                                                 ereg_replace('^[^[:space:]]+[[:space:]]','',$GLOBALS['TSFE']->csConvObj->crop('utf-8',$parts[$k],-($postPreLgd-$postPreLgd_offset)));
02017                                         }
02018                                 }
02019                                 $summaryLgd+= $GLOBALS['TSFE']->csConvObj->strlen('utf-8', $output[$k]);;
02020 
02021                                         // Protect output:
02022                                 $output[$k] = htmlspecialchars($output[$k]);
02023 
02024                                         // If summary lgd is exceed, break the process:
02025                                 if ($summaryLgd > $summaryMax)  {
02026                                         break;
02027                                 }
02028                         } else {
02029                                 $summaryLgd+= $GLOBALS['TSFE']->csConvObj->strlen('utf-8',$strP);
02030                                 $output[$k] = '<strong class="tx-indexedsearch-redMarkup">'.htmlspecialchars($parts[$k]).'</strong>';
02031                         }
02032                 }
02033 
02034                         // Return result:
02035                 return implode('',$output);
02036         }
02037 
02044         function makeTitle($row)        {
02045                 $add = '';
02046 
02047                 if ($this->multiplePagesType($row['item_type']))        {
02048                         $dat = unserialize($row['cHashParams']);
02049 
02050                         $pp = explode('-',$dat['key']);
02051                         if ($pp[0]!=$pp[1])     {
02052                                 $add=', '.$this->pi_getLL('word_pages').' '.$dat['key'];
02053                         } else $add=', '.$this->pi_getLL('word_page').' '.$pp[0];
02054                 }
02055 
02056                 $outputString = $GLOBALS['TSFE']->csConvObj->crop('utf-8',$row['item_title'],50,'...');
02057 
02058                 return $this->utf8_to_currentCharset($outputString).$add;
02059         }
02060 
02068         function makeInfo($row,$tmplArray)      {
02069                 $tmplArray['size'] = t3lib_div::formatSize($row['item_size']);
02070                 $tmplArray['created'] = date('d-m-y',$row['item_crdate']);
02071                 $tmplArray['modified'] = date('d-m-y H:i',$row['item_mtime']);
02072 
02073                 $pathId = $row['data_page_id']?$row['data_page_id']:$row['page_id'];
02074                 $pathMP = $row['data_page_id']?$row['data_page_mp']:'';
02075 
02076                 $pI = parse_url($row['data_filename']);
02077                 if ($pI['scheme'])      {
02078                         $tmplArray['path'] = '<a href="'.htmlspecialchars($row['data_filename']).'">'.htmlspecialchars($row['data_filename']).'</a>';
02079                 } else {
02080                         $pathStr = htmlspecialchars($this->getPathFromPageId($pathId,$pathMP));
02081                         $tmplArray['path'] = $this->linkPage($pathId,$pathStr,array(
02082                                 'data_page_type' => $row['data_page_type'],
02083                                 'data_page_mp' => $pathMP,
02084                                 'sys_language_uid' => $row['sys_language_uid'],
02085                         ));
02086                 }
02087 
02088                 return $tmplArray;
02089         }
02090 
02097         function getSpecialConfigForRow($row)   {
02098                 $pathId = $row['data_page_id'] ? $row['data_page_id'] : $row['page_id'];
02099                 $pathMP = $row['data_page_id'] ? $row['data_page_mp'] : '';
02100 
02101                 $rl = $this->getRootLine($pathId,$pathMP);
02102                 $specConf = $this->conf['specConfs.']['0.'];
02103                 if (is_array($rl))      {
02104                         foreach ($rl as $dat)   {
02105                                 if (is_array($this->conf['specConfs.'][$dat['uid'].'.']))       {
02106                                         $specConf = $this->conf['specConfs.'][$dat['uid'].'.'];
02107                                         break;
02108                                 }
02109                         }
02110                 }
02111 
02112                 return $specConf;
02113         }
02114 
02121         function makeLanguageIndication($row)   {
02122 
02123                         // If search result is a TYPO3 page:
02124                 if ((string)$row['item_type']==='0')    {
02125 
02126                                 // If TypoScript is used to render the flag:
02127                         if (is_array($this->conf['flagRendering.']))    {
02128                                 $this->cObj->setCurrentVal($row['sys_language_uid']);
02129                                 return $this->cObj->cObjGetSingle($this->conf['flagRendering'],$this->conf['flagRendering.']);
02130                         } else { // ... otherwise, get flag from sys_language record:
02131 
02132                                         // Get sys_language record
02133                                 $rowDat = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_language', 'uid='.intval($row['sys_language_uid']).' '.$this->cObj->enableFields('sys_language'));
02134 
02135                                         // Flag code:
02136                                 $flag = $rowDat[0]['flag'];
02137                                 if ($flag)      {
02138 
02139 // FIXME not all flags from typo3/gfx/flags are available in media/flags/
02140                                         $file = substr(PATH_tslib,strlen(PATH_site)).'media/flags/flag_'.$flag;
02141                                         $imgInfo = @getimagesize(PATH_site.$file);
02142 
02143 // original
02144 #                                       $file = TYPO3_mainDir.'gfx/flags/'.$flag;
02145 #                                       $imgInfo = @getimagesize(PATH_site.$file);
02146 
02147                                         if (is_array($imgInfo)) {
02148                                                 $output = '<img src="'.$file.'" '.$imgInfo[3].' title="'.htmlspecialchars($rowDat[0]['title']).'" alt="'.htmlspecialchars($rowDat[0]['title']).'" />';
02149                                                 return $output;
02150                                         }
02151                                 }
02152                         }
02153                 }
02154                 return '&nbsp;';
02155         }
02156 
02164         function makeAccessIndication($id)      {
02165                 if (is_array($this->fe_groups_required[$id]) && count($this->fe_groups_required[$id]))  {
02166                         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="" />';
02167                 }
02168         }
02169 
02179         function linkPage($id,$str,$row=array(),$markUpSwParams=array())        {
02180 
02181                         // Parameters for link:
02182                 $urlParameters = (array)unserialize($row['cHashParams']);
02183 
02184                         // Add &type and &MP variable:
02185                 if ($row['data_page_type']) $urlParameters['type'] = $row['data_page_type'];
02186                 if ($row['data_page_mp']) $urlParameters['MP'] = $row['data_page_mp'];
02187                 if ($row['sys_language_uid']) $urlParameters['L'] = $row['sys_language_uid'];
02188 
02189                         // markup-GET vars:
02190                 $urlParameters = array_merge($urlParameters, $markUpSwParams);
02191 
02192                         // 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...
02193                 if (!is_array($this->domain_records[$id]))      {
02194                         $this->getPathFromPageId($id);
02195                 }
02196 
02197                         // If external domain, then link to that:
02198                 if (count($this->domain_records[$id]))  {
02199                         reset($this->domain_records[$id]);
02200                         $firstDom = current($this->domain_records[$id]);
02201                         $scheme = t3lib_div::getIndpEnv('TYPO3_SSL') ? 'https://' : 'http://';
02202 
02203                         $addParams = '';
02204                         if (is_array($urlParameters))   {
02205                                 if (count($urlParameters))      {
02206                                         $addParams.= t3lib_div::implodeArrayForUrl('',$urlParameters);
02207                                 }
02208                         }
02209 
02210                         if ($target=$this->conf['search.']['detect_sys_domain_records.']['target'])     {
02211                                 $target = ' target="'.$target.'"';
02212                         }
02213                         return '<a href="'.htmlspecialchars($scheme.$firstDom.'/index.php?id='.$id.$addParams).'"'.$target.'>'.htmlspecialchars($str).'</a>';
02214                 } else {
02215                         return $this->pi_linkToPage($str,$id,$this->conf['result_link_target'],$urlParameters);
02216                 }
02217         }
02218 
02226         function getRootLine($id,$pathMP='')    {
02227                 $identStr = $id.'|'.$pathMP;
02228 
02229                 if (!isset($this->cache_path[$identStr]))       {
02230                         $this->cache_rl[$identStr] = $GLOBALS['TSFE']->sys_page->getRootLine($id,$pathMP);
02231                 }
02232                 return $this->cache_rl[$identStr];
02233         }
02234 
02241         function getFirstSysDomainRecordForPage($id)    {
02242                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('domainName', 'sys_domain', 'pid='.intval($id).$this->cObj->enableFields('sys_domain'), '', 'sorting');
02243                 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
02244                 return ereg_replace('\/$','',$row['domainName']);
02245         }
02246 
02254         function getPathFromPageId($id,$pathMP='')      {
02255 
02256                 $identStr = $id.'|'.$pathMP;
02257 
02258                 if (!isset($this->cache_path[$identStr]))       {
02259                         $this->fe_groups_required[$id] = array();
02260                         $this->domain_records[$id] = array();
02261                         $rl = $this->getRootLine($id,$pathMP);
02262                         $hitRoot = 0;
02263                         $path = '';
02264                         if (is_array($rl) && count($rl))        {
02265                                 reset($rl);
02266                                 while(list($k,$v)=each($rl))    {
02267                                                 // Check fe_user
02268                                         if ($v['fe_group'] && ($v['uid']==$id || $v['extendToSubpages']))       {
02269                                                 $this->fe_groups_required[$id][]=$v['fe_group'];
02270                                         }
02271                                                 // Check sys_domain.
02272                                         if ($this->conf['search.']['detect_sys_domain_records'])        {
02273                                                 $sysDName = $this->getFirstSysDomainRecordForPage($v['uid']);
02274                                                 if ($sysDName)  {
02275                                                         $this->domain_records[$id][] = $sysDName;
02276                                                                 // Set path accordingly:
02277                                                         $path = $sysDName.$path;
02278                                                         break;
02279                                                 }
02280                                         }
02281 
02282                                                 // Stop, if we find that the current id is the current root page.
02283                                         if ($v['uid']==$GLOBALS['TSFE']->config['rootLine'][0]['uid'])          {
02284                                                 break;
02285                                         }
02286                                         $path = '/'.$v['title'].$path;
02287                                 }
02288                         }
02289 
02290                         $this->cache_path[$identStr] = $path;
02291 
02292                         if (is_array($this->conf['path_stdWrap.']))     {
02293                                 $this->cache_path[$identStr] = $this->cObj->stdWrap($this->cache_path[$identStr], $this->conf['path_stdWrap.']);
02294                         }
02295                 }
02296 
02297                 return $this->cache_path[$identStr];
02298         }
02299 
02306         function getMenu($id)   {
02307                 if ($this->conf['show.']['LxALLtypes']) {
02308                         $output = Array();
02309                         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('title,uid', 'pages', 'pid='.intval($id).$this->cObj->enableFields('pages'), '', 'sorting');
02310                         while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))       {
02311                                 $output[$row['uid']] = $GLOBALS['TSFE']->sys_page->getPageOverlay($row);
02312                         }
02313                         return $output;
02314                 } else {
02315                         return $GLOBALS['TSFE']->sys_page->getMenu($id);
02316                 }
02317         }
02318 
02325         function multiplePagesType($item_type)  {
02326                 return is_object($this->external_parsers[$item_type]) && $this->external_parsers[$item_type]->isMultiplePageExtension($item_type);
02327         }
02328 
02335         function utf8_to_currentCharset($str)   {
02336                 return $GLOBALS['TSFE']->csConv($str,'utf-8');
02337         }
02338 
02345         function &hookRequest($functionName)    {
02346                 global $TYPO3_CONF_VARS;
02347 
02348                         // Hook: menuConfig_preProcessModMenu
02349                 if ($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['pi1_hooks'][$functionName]) {
02350                         $hookObj = &t3lib_div::getUserObj($TYPO3_CONF_VARS['EXTCONF']['indexed_search']['pi1_hooks'][$functionName]);
02351                         if (method_exists ($hookObj, $functionName)) {
02352                                 $hookObj->pObj = &$this;
02353                                 return $hookObj;
02354                         }
02355                 }
02356         }
02357 }
02358 
02359 
02360 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/indexed_search/pi/class.tx_indexedsearch.php'])        {
02361         include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/indexed_search/pi/class.tx_indexedsearch.php']);
02362 }
02363 ?>