Documentation TYPO3 par Ameos

class.tx_indexedsearch.php

00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2001-2004 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 ***************************************************************/
00042 require_once(PATH_tslib."class.tslib_pibase.php");
00043 require_once(PATH_tslib."class.tslib_search.php");
00044 require_once(t3lib_extMgm::extPath("indexed_search")."class.indexer.php");
00045 
00046 class tx_indexedsearch extends tslib_pibase {
00047     var $prefixId = "tx_indexedsearch";        // Same as class name
00048     var $scriptRelPath = "pi/class.tx_indexedsearch.php";    // Path to this script relative to the extension dir.
00049     var $extKey = "indexed_search";    // The extension key.
00050         var $join_pages=0;      // See document for info about this flag...
00051 
00052         var $defaultResultNumber=20;
00053         var $wholeSiteIdList = 0;
00054 
00055         var $operator_translate_table = Array (         // case-sensitiv. Defineres the words, which will be operators between words
00056                 Array ("+" , "AND"),
00057                 Array ("|" , "OR"),
00058                 Array ("-" , "AND NOT"),
00059                         // english
00060 #               Array ("AND" , "AND"),
00061 #               Array ("OR" , "OR"),
00062 #               Array ("NOT" , "AND NOT"),
00063         );
00064 
00065                 // Internals:
00066         var $cache_path=array();
00067         var $cache_rl=array();
00068         var $fe_groups_required=array();
00069         var $domain_records=array();
00070         var $sWArr=array();
00071         var $wSelClauses=array();
00072         var $firstRow=array();
00073         var $resultSections=array();
00074 
00075         var $anchorPrefix = '';                 // Prefix for local anchors. For "speaking URLs" to work with <base>-url set.
00076 
00077     function main($content,$conf)    {
00078         $this->conf=$conf;
00079         $this->pi_loadLL();
00080                 $this->pi_setPiVarDefaults();
00081                 $this->anchorPrefix = substr(t3lib_div::getIndpEnv('TYPO3_REQUEST_URL'),strlen(t3lib_div::getIndpEnv('TYPO3_SITE_URL')));
00082 
00083 #debug($this->piVars);
00084 
00085                         // Initialize the indexer-class - just to use a few function (for making hashes)
00086                 $this->indexerObj = t3lib_div::makeInstance("tx_indexedsearch_indexer");
00087 
00088                         // If "_sections" is set, this value overrides any existing value.
00089                 if ($this->piVars["_sections"])         $this->piVars["sections"] = $this->piVars["_sections"];
00090 
00091                         // Add previous search words to current
00092                 if ($this->piVars['sword_prev_include'] && $this->piVars["sword_prev"]) {
00093                         $this->piVars["sword"] = trim($this->piVars["sword_prev"]).' '.$this->piVars["sword"];
00094                 }
00095 
00096                         // Selector-box values defined here:
00097                 $optValues = Array(
00098                         "type" => Array(
00099                                 "0" => $this->pi_getLL("opt_type_0"),
00100                                 "1" => $this->pi_getLL("opt_type_1"),
00101                                 "2" => $this->pi_getLL("opt_type_2"),
00102                                 "3" => $this->pi_getLL("opt_type_3"),
00103                                 "10" => $this->pi_getLL("opt_type_10"),
00104                                 "20" => $this->pi_getLL("opt_type_20"),
00105                         ),
00106                         "defOp" => Array(
00107                                 "0" => $this->pi_getLL("opt_defOp_0"),
00108                                 "1" => $this->pi_getLL("opt_defOp_1"),
00109                         ),
00110                         "sections" => Array(
00111                                 "0" => $this->pi_getLL("opt_sections_0"),
00112                                 "-1" => $this->pi_getLL("opt_sections_-1"),
00113                                 "-2" => $this->pi_getLL("opt_sections_-2"),
00114                                 "-3" => $this->pi_getLL("opt_sections_-3"),
00115                                 // 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.
00116                         ),
00117                         "media" => Array(
00118                                 "-1" => $this->pi_getLL("opt_media_-1"),
00119                                 "0" => $this->pi_getLL("opt_media_0"),
00120                                 "-2" => $this->pi_getLL("opt_media_-2"),
00121                                 "1" => $this->pi_getLL("opt_media_1"),
00122                                 "2" => $this->pi_getLL("opt_media_2"),
00123                                 "3" => $this->pi_getLL("opt_media_3"),
00124                         ),
00125                         "order" => Array(
00126                                 "rank_flag" => $this->pi_getLL("opt_order_rank_flag"),
00127                                 "rank_freq" => $this->pi_getLL("opt_order_rank_freq"),
00128                                 "rank_first" => $this->pi_getLL("opt_order_rank_first"),
00129                                 "rank_count" => $this->pi_getLL("opt_order_rank_count"),
00130                                 "mtime" => $this->pi_getLL("opt_order_mtime"),
00131                                 "title" => $this->pi_getLL("opt_order_title"),
00132                                 "crdate" => $this->pi_getLL("opt_order_crdate"),
00133 #                               "rating" => "Page-rating",
00134 #                               "hits" => "Page-hits",
00135                         ),
00136                         "group" => Array (
00137                                 "sections" => $this->pi_getLL("opt_group_sections"),
00138                                 "flat" => $this->pi_getLL("opt_group_flat"),
00139                         ),
00140                         "lang" => Array (
00141                                 -1 => $this->pi_getLL("opt_lang_-1"),
00142                                 0 => $this->pi_getLL("opt_lang_0"),
00143                         ),
00144                         "desc" => Array (
00145                                 "0" => $this->pi_getLL("opt_desc_0"),
00146                                 "1" => $this->pi_getLL("opt_desc_1"),
00147                         ),
00148                         "results" => Array (
00149                                 "10" => "10",
00150                                 "20" => "20",
00151                                 "50" => "50",
00152                                 "100" => "100",
00153                         )
00154                 );
00155 
00156                 $this->operator_translate_table[]=Array ($this->pi_getLL("local_operator_AND") , "AND");
00157                 $this->operator_translate_table[]=Array ($this->pi_getLL("local_operator_OR") , "OR");
00158                 $this->operator_translate_table[]=Array ($this->pi_getLL("local_operator_NOT") , "AND NOT");
00159 
00160                         // This is the id of the site root. This value may be a commalist of integer (prepared for this)
00161                 $this->wholeSiteIdList=intval($GLOBALS["TSFE"]->config["rootLine"][0]["uid"]);
00162 
00163                         // This selects the first and secondary menus for the "sections" selector - so we can search in sections and sub sections.
00164                 if ($this->conf["show."]["L1sections"]) {
00165                         $firstLevelMenu = $this->getMenu($this->wholeSiteIdList);
00166         #               debug($firstLevelMenu);
00167                         while(list($kk,$mR)=each($firstLevelMenu))      {
00168                                 if ($mR["doktype"]!=5)  {
00169                                         $optValues["sections"]["rl1_".$mR["uid"]]=trim($this->pi_getLL("opt_RL1")." ".$mR["title"]);
00170                                         if ($this->conf["show."]["L2sections"]) {
00171                                                 $secondLevelMenu = $this->getMenu($mR["uid"]);
00172                                                 while(list($kk2,$mR2)=each($secondLevelMenu))   {
00173                                                         if ($mR["doktype"]!=5)  {
00174                                                                 $optValues["sections"]["rl2_".$mR2["uid"]]=trim($this->pi_getLL("opt_RL2")." ".$mR2["title"]);
00175                                                         } else unset($secondLevelMenu[$kk2]);
00176                                                 }
00177                                                 $optValues["sections"]["rl2_".implode(",",array_keys($secondLevelMenu))]=$this->pi_getLL("opt_RL2ALL");
00178                                         }
00179                                 } else unset($firstLevelMenu[$kk]);
00180                         }
00181                         $optValues["sections"]["rl1_".implode(",",array_keys($firstLevelMenu))]=$this->pi_getLL("opt_RL1ALL");
00182                 }
00183 
00184                         // 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...
00185                 if ($this->conf["search."]["rootPidList"])      {
00186                         $this->wholeSiteIdList = implode(",",t3lib_div::intExplode(",",$this->conf["search."]["rootPidList"]));
00187 #debug($this->wholeSiteIdList);
00188                 }
00189 
00190 
00191                         // Add search languages:
00192                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_language', '1'.$this->cObj->enableFields('sys_language'));
00193                 while($lR = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))        {
00194                         $optValues["lang"][$lR["uid"]]=$lR["title"];
00195                 }
00196 
00197 
00198 
00199 #debug($this->piVars);
00200                         // Setting first values in optValues as default values IF there is not corresponding piVar value set already.
00201                 reset($optValues);
00202                 while(list($kk,$vv)=each($optValues))   {
00203                         if (!isset($this->piVars[$kk])) {
00204                                 reset($vv);
00205                                 $this->piVars[$kk]=key($vv);
00206                         }
00207                 }
00208 #debug($this->piVars);
00209 
00210                         // Blind selectors:
00211                 if (is_array($this->conf["blind."]))    {
00212                         reset($this->conf["blind."]);
00213                         while(list($kk,$vv)=each($this->conf["blind."]))        {
00214                                 if (is_array($vv))      {
00215                                         reset($vv);
00216                                         while(list($kkk,$vvv)=each($vv))        {
00217                                                 if (!is_array($vvv) && $vvv && is_array($optValues[substr($kk,0,-1)]))  {
00218                                                         unset($optValues[substr($kk,0,-1)][$kkk]);
00219                                                 }
00220                                         }
00221                                 } elseif ($vv) {        // If value is not set, unset the option array.
00222                                         unset($optValues[$kk]);
00223                                 }
00224                         }
00225                 }
00226 
00227 
00228                         // This gets the search-words into the $sWArr:
00229                 $this->sWArr = $sWArr = $this->getSearchWords($this->piVars["defOp"]);
00230 #debug($this->sWArr);
00231 
00232                         // If there was any search words entered...
00233                 if (is_array($sWArr))   {
00234                         $content = $this->doSearch($sWArr);
00235                 }       // END: There was a search word.
00236 
00237                         // Finally compile all the content, form, messages and results:
00238         $content=
00239                         $this->makeSearchForm($optValues).
00240                         $this->printRules().
00241             $content;
00242 
00243         return $this->pi_wrapInBaseClass($content);
00244     }
00245 
00249         function doSearch($sWArr)       {
00250                 $rowcontent="";
00251                 $pt1=t3lib_div::milliseconds();
00252 
00253                         // This SEARCHES for the searchwords in $sWArr AND returns a COMPLETE list of phash-integers of the matches.
00254                 $list = $this->getPhashList($sWArr);
00255                 $pt2=t3lib_div::milliseconds();
00256 
00257 
00258                         // IF there were any matches (there is results...) then go on.
00259                 if ($list)      {
00260                         $GLOBALS["TT"]->push("Searching Final result");
00261 
00262                                 // Do the search:
00263                         $res = $this->execFinalQuery($list);
00264 
00265                                 // Get some variables:
00266                         $count = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
00267 #debug($count);
00268                         $this->piVars["results"] = $displayCount = t3lib_div::intInRange($this->piVars["results"],1,100000,$this->defaultResultNumber);
00269                         $pointer=t3lib_div::intInRange($this->piVars["pointer"],0,floor($count/$displayCount));
00270 
00271                         $pt3=t3lib_div::milliseconds();
00272 
00273                                 // Now, traverse result and put the rows to be displayed into an array
00274                         $lines=Array();
00275                         $c=0;
00276                         $this->firstRow=Array();        // Will hold the first row in result - used to calculate relative hit-ratings.
00277                         $this->resultRows=Array();      // Will hold the results rows for display.
00278                         $this->grouping_phashes=array();        // Used to filter out duplicates.
00279                         $this->grouping_chashes=array();        // Used to filter out duplicates BASED ON cHash.
00280                         while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))       {
00281                                 if (!$c)        {
00282                                         $this->firstRow=$row;
00283                                 }
00284 
00285                                 $row["show_resume"]=$this->checkResume($row);
00286                                 $phashGr = !in_array($row["phash_grouping"],$this->grouping_phashes);
00287                                 $chashGr = !in_array($row["contentHash"].".".$row["data_page_id"],$this->grouping_chashes);
00288                                 if ($phashGr && $chashGr)       {
00289                                         if ($row["show_resume"])        {       // Only if the resume may be shown are we going to filter out duplicates...
00290                                                 if ($row["item_type"]!=2)       {       // Only on documents which are not PDF files.
00291                                                         $this->grouping_phashes[]=$row["phash_grouping"];
00292                                                 }
00293                                                 $this->grouping_chashes[]=$row["contentHash"].".".$row["data_page_id"];
00294                                         }
00295                                         $c++;
00296 
00297                                                 // All rows for display is put into resultRows[]
00298                                         if ($c > $pointer*$displayCount)        {
00299                                                 $row["result_number"]=$c;
00300                                                 $this->resultRows[] = $row;
00301                                                 if ($c+1 > ($pointer+1)*$displayCount)  break;
00302                                         }
00303                                 } else {
00304                                         $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.
00305 #                                       debug();
00306                                 }
00307                         }
00308                         $GLOBALS["TT"]->pull();
00309 
00310 #debug($this->resultRows);
00311 #debug(count($this->resultRows));
00312 #debug($this->grouping_chashes);
00313 
00314                         $GLOBALS["TT"]->push("Display Final result");
00315 
00316                                 // SO, on to the result display here:
00317                         $rowcontent.=$this->compileResult($this->resultRows);
00318                         $pt4=t3lib_div::milliseconds();
00319 
00320                                 // Makes the result browsing navigation (next/prev, 1-2-3)
00321 #                       $PS = $this->makePointerSelector($count,$displayCount,$pointer);
00322 
00323 
00324                                 // Browsing box:
00325                         if ($count)     {
00326                                 #$content.=$PS."<HR>";
00327                                 $this->internal["res_count"]=$count;
00328                                 $this->internal["results_at_a_time"]=$displayCount;
00329                                 $this->internal["maxPages"]=t3lib_div::intInRange($this->conf["search."]["page_links"],1,100,10);
00330                                 $addString = ($count&&$this->piVars["group"]=="sections"?" ".sprintf($this->pi_getLL("inNsection".(count($this->resultSections)>1?"s":"")),count($this->resultSections)):"");
00331                                 $browseBox1 = $this->pi_list_browseresults(1,$addString,$this->printResultSectionLinks());
00332                                 $browseBox2 = $this->pi_list_browseresults(0);
00333                         }
00334 
00335                                 // Print the time the search took:
00336                         if ($pt1 && $this->conf["show."]["parsetimes"]) {
00337                                 $parsetimes="";
00338                                 $parsetimes.="<p>Word Search took: ".($pt2-$pt1)." ms<BR>";
00339                                 $parsetimes.="Order Search took: ".($pt3-$pt2)." ms<BR>";
00340                                 $parsetimes.="Display took: ".($pt4-$pt3)." ms</p><HR>";
00341                         }
00342 
00343                                 // Browsing nav, bottom.
00344                         if ($count)     {
00345                                 $content=$browseBox1.$rowcontent.$browseBox2;
00346                         } else {
00347                                 $content='<p'.$this->pi_classParam("noresults").'>'.$this->pi_getLL("noResults").'</p>';
00348                         }
00349                         $content.=$parsetimes;
00350 
00351                         $GLOBALS["TT"]->pull();
00352                 } else {        // No results found:
00353                         $content.='<p'.$this->pi_classParam("noresults").'>'.$this->pi_getLL("noResults").'</p>';
00354                 }
00355 
00356                         // Print a message telling which words we searched for, and in which sections etc.
00357                 $what=$this->tellUsWhatIsSeachedFor($sWArr).
00358                         (substr($this->piVars["sections"],0,2)=="rl"?" ".$this->pi_getLL("inSection")." '".substr($this->getPathFromPageId(substr($this->piVars["sections"],4)),1)."'":"");
00359                 $what='<div'.$this->pi_classParam("whatis").'><p>'.$what.'</p></div>';
00360                 $content=$what.$content;
00361 
00362                         // Write search statistics
00363                 $this->writeSearchStat($sWArr,$count,array($pt1,$pt2,$pt3,$pt4));
00364                 return $content;
00365         }
00366 
00367 
00368 
00369 
00370 
00371 
00372         /***********************************
00373 
00374                 SEARCHING FUNCTIONS
00375 
00376         ***********************************/
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00396         function getSearchWords($defOp) {
00397                 $inSW = substr($this->piVars["sword"],0,200);
00398                 if ($this->piVars["type"]==20)  {
00399                         return array(array("sword"=>trim($inSW),"oper"=>"AND"));
00400                 } else {
00401                         $search = t3lib_div::makeInstance("tslib_search");
00402                         $search->default_operator = $defOp==1 ? 'OR' : 'AND';
00403                         $search->operator_translate_table = $this->operator_translate_table;
00404                         $search->register_and_explode_search_string($inSW);
00405 
00406                         if (is_array($search->sword_array))     {
00407                                 return $search->sword_array;
00408                         }
00409                 }
00410         }
00411 
00416         function getPhashList($sWArr)   {
00417                 $c=0;
00418 
00419                 $totalHashList=array(); // This array accumulates the phash-values
00420                 $this->wSelClauses=array();
00421 
00422                 reset($sWArr);
00423                 while(list($k,$v)=each($sWArr)) {
00424                         $sWord = $this->indexerObj->strtolower_all($v["sword"]);        // lower-case all of them...
00425 
00426                         $GLOBALS["TT"]->push("SearchWord ".$sWord);
00427 
00428                         $plusQ="";
00429 /*
00430                                 // Maybe this will improve the search queries. Tests has shown it not to do so though...
00431                         if (count($totalHashList))      {
00432                                 switch($v["oper"])      {
00433                                         case "OR":
00434                                                 $plusQ = "AND IR.phash NOT IN (".implode(",",$totalHashList).")";
00435                                         break;
00436                                         case "AND NOT":
00437                                         default:        // AND
00438                                                 $plusQ = "AND IR.phash IN (".implode(",",$totalHashList).")";
00439                                         break;
00440                                 }
00441                         }
00442                         $plusQ="";
00443 */
00444 
00445                                 // Making the query for a single search word based on the search-type
00446                         $res="";
00447                         $theType = (string)$this->piVars["type"];
00448                         if (strstr($sWord," ")) $theType=20;    // If there are spaces in the search-word, make a full text search instead.
00449 
00450                         $wSel="";
00451                         switch($theType)        {
00452                                 case "1":
00453                                         $wSel = "IW.baseword LIKE '%".$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_words')."%'";
00454                                         $res = $this->execPHashListQuery($wSel,$plusQ);
00455 
00456                                 break;
00457                                 case "2":
00458                                         $wSel = "IW.baseword LIKE '".$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_words')."%'";
00459                                         $res = $this->execPHashListQuery($wSel,$plusQ);
00460                                 break;
00461                                 case "3":
00462                                         $wSel = "IW.baseword LIKE '%".$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_words')."'";
00463                                         $res = $this->execPHashListQuery($wSel,$plusQ);
00464                                 break;
00465                                 case "10":
00466                                         $wSel = "IW.metaphone = ".$this->indexerObj->metaphone($sWord);
00467                                         $res = $this->execPHashListQuery($wSel,$plusQ);
00468                                 break;
00469                                 case "20":
00470                                         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00471                                                                 'ISEC.phash',
00472                                                                 'index_section AS ISEC, index_fulltext AS IFT',
00473                                                                 'IFT.fulltextdata LIKE "%'.$GLOBALS['TYPO3_DB']->quoteStr($sWord, 'index_fulltext').'%" AND
00474                                                                         ISEC.phash = IFT.phash
00475                                                                         '.$this->sectionTableWhere(),
00476                                                                 'ISEC.phash'
00477                                                         );
00478                                         $wSel = "1=1";
00479 
00480                                         if ($this->piVars["type"]==20)  $this->piVars["order"]="mtime";         // If there is a fulltext search for a sentence there is a likelyness 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.
00481                                 break;
00482                                 default:
00483                                         $wSel = "IW.wid = ".$hash = $this->indexerObj->md5inthash($sWord);
00484                                         $res = $this->execPHashListQuery($wSel,$plusQ);
00485                                 break;
00486                         }
00487                         $this->wSelClauses[]=$wSel;
00488 
00489                                 // If there was a query to do, then select all phash-integers which resulted from this.
00490                         if ($res)       {
00491 
00492                                 # Get phash list by searching for it:
00493                                 $phashList = array();
00494                                 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))       {
00495                                         $phashList[]=$row["phash"];
00496                                 }
00497                                 $GLOBALS['TYPO3_DB']->sql_free_result($res);
00498 
00499                                         // Here the phash list are merged with the existing result based on whether we are dealing with OR, NOT or AND operations.
00500                                 if ($c) {
00501                                         switch($v["oper"])      {
00502                                                 case "OR":
00503                                                         $totalHashList=array_unique(array_merge($phashList,$totalHashList));
00504                                                 break;
00505                                                 case "AND NOT":
00506                                                         $totalHashList=array_diff($totalHashList,$phashList);
00507                                                 break;
00508                                                 default:        // AND...
00509                                                         $totalHashList=array_intersect($totalHashList,$phashList);
00510                                                 break;
00511                                         }
00512                                 } else {
00513                                         $totalHashList=$phashList;      // First search
00514                                 }
00515 #debug($totalHashList);
00516                         }
00517 
00518                         $GLOBALS["TT"]->pull();
00519                         $c++;
00520                 }
00521 
00522 #debug($sWArr);
00523                 return implode(",",$totalHashList);
00524         }
00525 
00529         function execPHashListQuery($wordSel,$plusQ="") {
00530                 return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00531                                         'STRAIGHT_JOIN IR.phash',
00532                                         'index_words AS IW,
00533                                                 index_rel AS IR,
00534                                                 index_section AS ISEC',
00535                                         $wordSel.'
00536                                                 AND IW.wid=IR.wid
00537                                                 AND ISEC.phash = IR.phash
00538                                                 '.$this->sectionTableWhere().'
00539                                                 '.$plusQ,
00540                                         'IR.phash'
00541                                 );
00542         }
00543 
00547         function sectionTableWhere()    {
00548 #debug($this->piVars["sections"]);
00549                 $out = $this->wholeSiteIdList<0 ? "" : "AND ISEC.rl0 IN (".$this->wholeSiteIdList.")";
00550                 $list = implode(",",t3lib_div::intExplode(",",substr($this->piVars["sections"],4)));
00551 
00552                 if (substr($this->piVars["sections"],0,4)=="rl1_")      {
00553                         $out.= "AND ISEC.rl1 IN (".$list.")";
00554                 } else if (substr($this->piVars["sections"],0,4)=="rl2_")       {
00555                         $out.= "AND ISEC.rl2 IN (".$list.")";
00556                 } else {
00557                         switch((string)$this->piVars["sections"])       {
00558                                 case "-1":              // "-1" => "Only this page",
00559                                         $out.= " AND ISEC.page_id=".$GLOBALS["TSFE"]->id;
00560                                 break;
00561                                 case "-2":              // "-2" => "Top + level 1",
00562                                         $out.= " AND ISEC.rl2=0";
00563                                 break;
00564                                 case "-3":              // "-3" => "Level 2 and out",
00565                                         $out.= " AND ISEC.rl2>0";
00566                                 break;
00567                         }
00568                 }
00569                 return $out;
00570         }
00571 
00575         function mediaTypeWhere()       {
00576                 switch($this->piVars["media"])  {
00577                         case 0:         // "0" => "Kun TYPO3 sider",
00578                                 $out = "AND IP.item_type=0";
00579                         break;
00580                         case 1:         // "1" => "Kun HTML dokumenter",
00581                                 $out = "AND IP.item_type=1";
00582                         break;
00583                         case 2:         // "2" => "Kun PDF dokumenter",
00584                                 $out = "AND IP.item_type=2";
00585                         break;
00586                         case 3:         // "3" => "Kun Word dokumenter",
00587                                 $out = "AND IP.item_type=3";
00588                         break;
00589                         case -2:                // All external documents
00590                                 $out = "AND IP.item_type>0";
00591                         break;
00592                         case -1:
00593                         default:
00594                                 $out="";
00595                         break;
00596                 }
00597                 return $out;
00598         }
00599 
00603         function languageWhere()        {
00604                 if ($this->piVars["lang"]>=0)   {       // -1 is the same as ALL language.
00605                         return "AND IP.sys_language_uid=".intval($this->piVars["lang"]);
00606                 }
00607         }
00608 
00612         function execFinalQuery($list)  {
00613 
00614                 $page_join="";
00615                 $page_where="";
00616                 if ($this->join_pages)  {
00617                         $page_join = ",
00618                                 pages";
00619                         $page_where = "pages.uid = ISEC.page_id
00620                                 ".$this->cObj->enableFields("pages")."
00621                                 AND pages.no_search=0
00622                                 AND pages.doktype<200
00623                         ";
00624                 } elseif ($this->wholeSiteIdList>=0) {
00625                         $siteIdNumbers = t3lib_div::intExplode(",",$this->wholeSiteIdList);
00626                         $id_list=array();
00627                         while(list(,$rootId)=each($siteIdNumbers))      {
00628                                 $id_list[]=$this->cObj->getTreeList($rootId,9999,0,0,"","").$rootId;
00629                         }
00630                         $page_where = "ISEC.page_id IN (".implode(",",$id_list).")";
00631                 } else {
00632                         $page_where = " 1=1 ";
00633                 }
00634 
00635                         // 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.
00636                 if (substr($this->piVars["order"],0,5)=="rank_")        {
00637                                 /*
00638                                          OK there were some fancy calculations promoted by Graeme Merrall:
00639 
00640                                         "However, regarding relevance you probably want to look at something like
00641                                         Salton's formula which is a good easy way to measure relevance.
00642                                         Oracle Intermedia uses this and it's pretty simple:
00643                                         Score can be between 0 and 100, but the top-scoring document in the query
00644                                         will not necessarily have a score of 100 -- scoring is relative, not
00645                                         absolute. This means that scores are not comparable across indexes, or even
00646                                         across different queries on the same index. Score for each document is
00647                                         computed using the standard Salton formula:
00648 
00649                                             3f(1+log(N/n))
00650 
00651                                         Where f is the frequency of the search term in the document, N is the total
00652                                         number of rows in the table, and n is the number of rows which contain the
00653                                         search term. This is converted into an integer in the range 0 - 100.
00654 
00655                                         There's a good doc on it at
00656                                         http://ls6-www.informatik.uni-dortmund.de/bib/fulltext/ir/Pfeifer:97/
00657                                         although it may be a little complex for what you require so just pick the
00658                                         relevant parts out.
00659                                         "
00660 
00661                                         However I chose not to go with this for several reasons.
00662                                         I do not claim that my ways of calculating importance here is the best.
00663                                         ANY (better) suggestions for ranking calculation is accepted! (as long as they are shipped with tested code in exchange for this.)
00664                                 */
00665 
00666                         switch($this->piVars["order"])  {
00667                                 case "rank_flag":       // This gives priority to word-position (max-value) so that words in title, keywords, description counts more than in content.
00668                                                                         // The ordering is refined with the frequency sum as well.
00669                                         $grsel = "MAX(IR.flags) AS order_val1, SUM(IR.freq) AS order_val2";
00670                                         $orderBy = "order_val1".$this->isDescending().",order_val2".$this->isDescending();
00671                                 break;
00672                                 case "rank_first":      // Results in average position of search words on page. Must be inversely sorted (low numbers are closer to top)
00673                                         $grsel = "AVG(IR.first) AS order_val";
00674                                         $orderBy = "order_val".$this->isDescending(1);
00675                                 break;
00676                                 case "rank_count":      // Number of words found
00677                                         $grsel = "SUM(IR.count) AS order_val";
00678                                         $orderBy = "order_val".$this->isDescending();
00679                                 break;
00680                                 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?
00681                                         $grsel = "SUM(IR.freq) AS order_val";
00682                                         $orderBy = "order_val".$this->isDescending();
00683                                 break;
00684                         }
00685 
00686                                 // So, words are imploded into an OR statement (no "sentence search" should be done here - may deselect results)
00687                         $wordSel='('.implode(' OR ',$this->wSelClauses).') AND ';
00688 
00689                         return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00690                                                 'STRAIGHT_JOIN ISEC.*, IP.*, '.$grsel,
00691                                                 'index_words AS IW,
00692                                                         index_rel AS IR,
00693                                                         index_section AS ISEC,
00694                                                         index_phash AS IP'.
00695                                                         $page_join,
00696                                                 $wordSel.'
00697                                                         IP.phash IN ('.$list.') '.
00698                                                         $this->mediaTypeWhere().' '.
00699                                                         $this->languageWhere().'
00700                                                         AND IW.wid=IR.wid
00701                                                         AND ISEC.phash = IR.phash
00702                                                         AND IP.phash = IR.phash
00703                                                         AND     '.$page_where,
00704                                                 'IP.phash',
00705                                                 $orderBy
00706                                         );
00707                 } else {        // Otherwise, if sorting are done with the pages table or other fields, there is no need for joining with the rel/word tables:
00708 
00709                         $orderBy = '';
00710                         switch((string)$this->piVars["order"])  {
00711                                 case "rating":
00712                                         debug("rating: NOT ACTIVE YET");
00713                                 break;
00714                                 case "hits":
00715                                         debug("rating: NOT ACTIVE YET");
00716                                 break;
00717                                 case "title":
00718                                         $orderBy = "IP.item_title".$this->isDescending();
00719                                 break;
00720                                 case "crdate":
00721                                         $orderBy = "IP.item_crdate".$this->isDescending();
00722                                 break;
00723                                 case "mtime":
00724                                         $orderBy = "IP.item_mtime".$this->isDescending();
00725                                 break;
00726                         }
00727 
00728                         return $GLOBALS['TYPO3_DB']->exec_SELECTquery(
00729                                                 'ISEC.*, IP.*',
00730                                                 'index_phash AS IP,index_section AS ISEC'.$page_join,
00731                                                 'IP.phash IN ('.$list.') '.
00732                                                         $this->mediaTypeWhere().' '.
00733                                                         $this->languageWhere().'
00734                                                         AND IP.phash = ISEC.phash
00735                                                         AND '.$page_where,
00736                                                 'IP.phash',
00737                                                 $orderBy
00738                                         );
00739                 }
00740         }
00741 
00745         function checkResume($row)      {
00746                 if ($row["item_type"]>0)        {
00747                                 // phash_t3 is the phash of the parent TYPO3 page row which initiated the indexing of the documents in this section.
00748 
00749                                 // So, selecting for the grlist records belonging to the parent phash-row where the current users gr_list exists.
00750                                 // 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 this case is rare.
00751                         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('phash', 'index_grlist', 'phash='.intval($row['phash_t3']).' AND gr_list="'.$GLOBALS['TYPO3_DB']->quoteStr($GLOBALS['TSFE']->gr_list, 'index_grlist').'"');
00752                         if ($GLOBALS['TYPO3_DB']->sql_num_rows($res))   {
00753 #                               debug("Look up for external media '".$row["data_filename"]."': phash:".$row["phash_t3"]." YES - (".$GLOBALS["TSFE"]->gr_list.")!",1);
00754                                 return 1;
00755                         } else {
00756 #                               debug("Look up for external media '".$row["data_filename"]."': phash:".$row["phash_t3"]." NO - (".$GLOBALS["TSFE"]->gr_list.")!",1);
00757                                 return 0;
00758                         }
00759                 } else {        // ALm typo3 pages:
00760                         if (strcmp($row["gr_list"],$GLOBALS["TSFE"]->gr_list))  {
00761                                         // 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...
00762                                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('phash', 'index_grlist', 'phash='.intval($row['phash']).' AND gr_list="'.$GLOBALS['TYPO3_DB']->quoteStr($GLOBALS['TSFE']->gr_list, 'index_grlist').'"');
00763                                 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res))   {
00764                                         #debug("Checking on it ...".$row["item_title"]."/".$row["phash"]." - YES (".$GLOBALS["TSFE"]->gr_list.")",1);
00765                                         return 1;
00766                                 } else {
00767                                         #debug("Checking on it ...".$row["item_title"]."/".$row["phash"]." - NOPE",1);
00768                                         return 0;
00769                                 }
00770                         } else {
00771                                         #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);
00772                                 return 1;
00773                         }
00774                 }
00775         }
00776 
00780         function isDescending($inverse=0)       {
00781                 $desc = $this->piVars["desc"];
00782                 if ($inverse)   $desc=!$desc;
00783                 return !$desc ? " DESC":"";
00784         }
00785 
00789         function writeSearchStat($sWArr,$count,$pt)     {
00790                 $insertFields = array(
00791                         'searchstring' => $this->piVars['sword'],
00792                         'searchoptions' => serialize(array($this->piVars,$sWArr,$pt)),
00793                         'feuser_id' => $this->fe_user->user['uid'],                     // fe_user id, integer
00794                         'cookie' => $this->fe_user->id,                                         // cookie as set or retrieve. If people has cookies disabled this will vary all the time...
00795                         'IP' => t3lib_div::getIndpEnv('REMOTE_ADDR'),           // Remote IP address
00796                         'hits' => intval($count),                                                       // Number of hits on the search.
00797                         'tstamp' => $GLOBALS['EXEC_TIME']                                       // Time stamp
00798                 );
00799 
00800                 $GLOBALS['TYPO3_DB']->exec_INSERTquery('index_stat_search', $insertFields);
00801                 $newId = $GLOBALS['TYPO3_DB']->sql_insert_id();
00802 
00803                 if ($newId)     {
00804                         foreach($sWArr as $val) {
00805                                 $insertFields = array(
00806                                         'word' => $this->indexerObj->strtolower_all($val['sword']),
00807                                         'index_stat_search_id' => $newId,
00808                                         'tstamp' => $GLOBALS['EXEC_TIME']               // Time stamp
00809                                 );
00810 
00811                                 $GLOBALS['TYPO3_DB']->exec_INSERTquery('index_stat_word', $insertFields);
00812                         }
00813                 }
00814         }
00815 
00816 
00817 
00818 
00819 
00820 
00821 
00822 
00823 
00824 
00825 
00826 
00827 
00828         /***********************************
00829 
00830                 LAYOUT FUNCTIONS
00831 
00832         ***********************************/
00833 
00834 
00835 
00836 
00840         function makeSearchForm($optValues)     {
00841                 $rows=array();
00842                         // Adding search field and button:
00843                 $rows[]='<tr>
00844                                 <td nowrap><p>'.$this->pi_getLL("form_searchFor").'&nbsp;</p></td>
00845                                 <td><input type="text" name="'.$this->prefixId.'[sword]" value="'.htmlspecialchars($this->conf["show."]["clearSearchBox"]?'':$this->piVars["sword"]).'"'.$this->pi_classParam("searchbox-sword").'>&nbsp;&nbsp;<input type="submit" name="'.$this->prefixId.'[submit_button]" value="'.$this->pi_getLL("submit_button_label").'"'.$this->pi_classParam("searchbox-button").'></td>
00846                         </tr>';
00847 
00848                 if ($this->conf["show."]["clearSearchBox"] && $this->conf["show."]["clearSearchBox."]['enableSubSearchCheckBox'])       {
00849                         $rows[]='<tr>
00850                                 <td></td>
00851                                 <td><input type="hidden" name="'.$this->prefixId.'[sword_prev]" value="'.htmlspecialchars($this->piVars["sword"]).'"><input type="checkbox" name="'.$this->prefixId.'[sword_prev_include]" value="1"'.($this->piVars['sword_prev_include']?' checked="checked"':'').'> Add to current search words</td>
00852                         </tr>';
00853                 }
00854 
00855 
00856                 if ($this->piVars["ext"])       {
00857                         if (is_array($optValues["type"]) || is_array($optValues["defOp"]))      $rows[]='<tr>
00858                                         <td nowrap><p>'.$this->pi_getLL("form_match").'&nbsp;</p></td>
00859                                         <td>'.$this->renderSelectBox($this->prefixId.'[type]',$this->piVars["type"],$optValues["type"]).
00860                                         $this->renderSelectBox($this->prefixId.'[defOp]',$this->piVars["defOp"],$optValues["defOp"]).'</td>
00861                                 </tr>';
00862                         if (is_array($optValues["media"]) || is_array($optValues["lang"]))      $rows[]='<tr>
00863                                         <td nowrap><p>'.$this->pi_getLL("form_searchIn").'&nbsp;</p></td>
00864                                         <td>'.$this->renderSelectBox($this->prefixId.'[media]',$this->piVars["media"],$optValues["media"]).
00865                                         $this->renderSelectBox($this->prefixId.'[lang]',$this->piVars["lang"],$optValues["lang"]).'</td>
00866                                 </tr>';
00867                         if (is_array($optValues["sections"]))   $rows[]='<tr>
00868                                         <td nowrap><p>'.$this->pi_getLL("form_fromSection").'&nbsp;</p></td>
00869                                         <td>'.$this->renderSelectBox($this->prefixId.'[sections]',$this->piVars["sections"],$optValues["sections"]).'</td>
00870                                 </tr>';
00871                         if (is_array($optValues["order"]) || is_array($optValues["desc"]) || is_array($optValues["results"]))   $rows[]='<tr>
00872                                         <td nowrap><p>'.$this->pi_getLL("form_orderBy").'&nbsp;</p></td>
00873                                         <td><p>'.$this->renderSelectBox($this->prefixId.'[order]',$this->piVars["order"],$optValues["order"]).
00874                                                 $this->renderSelectBox($this->prefixId.'[desc]',$this->piVars["desc"],$optValues["desc"]).
00875                                                 $this->renderSelectBox($this->prefixId.'[results]',$this->piVars["results"],$optValues["results"]).'&nbsp;'.$this->pi_getLL("form_atATime").'</p></td>
00876                                 </tr>';
00877                         if (is_array($optValues["group"]) || !$this->conf["blind."]["extResume"])       $rows[]='<tr>
00878                                         <td nowrap><p>'.$this->pi_getLL("form_style").'&nbsp;</p></td>
00879                                         <td><p>'.$this->renderSelectBox($this->prefixId.'[group]',$this->piVars["group"],$optValues["group"]).
00880                                         (!$this->conf["blind."]["extResume"] ? '&nbsp; &nbsp;
00881                                         <input type="hidden" name="'.$this->prefixId.'[extResume]" value="0"><input type="checkbox" value="1" name="'.$this->prefixId.'[extResume]"'.($this->piVars["extResume"]?" CHECKED":"").'>'.$this->pi_getLL("form_extResume"):'').'</p></td>
00882                                 </tr>';
00883                 }
00884 
00885 #debug(array($GLOBALS["TSFE"]->id,$GLOBALS["TSFE"]->sPre,$this->pi_getPageLink($GLOBALS["TSFE"]->id,$GLOBALS["TSFE"]->sPre)));
00886 
00887                 $out='<table '.$this->conf["tableParams."]["searchBox"].'>
00888                                         <form action="'.$this->pi_getPageLink($GLOBALS["TSFE"]->id,$GLOBALS["TSFE"]->sPre).'" method="POST" name="'.$this->prefixId.'">
00889                                 '.implode(chr(10),$rows).'
00890                                                 <input type="hidden" name="'.$this->prefixId.'[_sections]" value="0">
00891                                                 <input type="hidden" name="'.$this->prefixId.'[pointer]" value="0">
00892                                                 <input type="hidden" name="'.$this->prefixId.'[ext]" value="'.($this->piVars["ext"]?1:0).'">
00893                             </form>
00894                                 </table>';
00895                 $out.='<p>'.
00896                                 ($this->piVars["ext"] ?
00897                                         '<a href="'.$this->pi_getPageLink($GLOBALS["TSFE"]->id,$GLOBALS["TSFE"]->sPre,array($this->prefixId."[ext]"=>0)).'">'.$this->pi_getLL("link_regularSearch").'</a>' :
00898                                         '<a href="'.$this->pi_getPageLink($GLOBALS["TSFE"]->id,$GLOBALS["TSFE"]->sPre,array($this->prefixId."[ext]"=>1)).'">'.$this->pi_getLL("link_advancedSearch").'</a>'
00899                                 ).'</p>';
00900 
00901                 return '<div'.$this->pi_classParam("searchbox").'>'.$out.'</div>';
00902         }
00903 
00907         function printRules()   {
00908                 $out = "";
00909                 if ($this->conf["show."]["rules"])      {
00910                         $out = '<h2>'.$this->pi_getLL("rules_header").'</h2><p>'.nl2br(htmlspecialchars(trim($this->pi_getLL("rules_text")))).'</p>';
00911                         $out = '<div'.$this->pi_classParam("rules").'>'.$this->cObj->stdWrap($out, $this->conf["rules_stdWrap."]).'</div>';
00912                 }
00913                 return $out;
00914         }
00915 
00919         function printResultSectionLinks()      {
00920                 $lines=array();
00921                 reset($this->resultSections);
00922                 while(list($id,$dat)=each($this->resultSections))       {
00923                         $lines[]='<li><a href="'.$this->anchorPrefix.'#'.md5($id).'">'.(trim($dat[0])?htmlspecialchars(trim($dat[0])):$this->pi_getLL("unnamedSection")).' ('.$dat[1].' '.$this->pi_getLL("word_page".($dat[1]>1?"s":"")).')</a></li>';
00924                 }
00925                 $out = '<ul>'.implode(chr(10),$lines).'</ul>';
00926                 return '<div'.$this->pi_classParam("sectionlinks").'>'.$this->cObj->stdWrap($out, $this->conf["sectionlinks_stdWrap."]).'</div>';
00927         }
00928 
00932         function makePointerSelector($count,$displayCount,$pointer)     {
00933                 $lines=array();
00934 
00935                         // Previous pointer:
00936                 if ($pointer>0) {
00937                         $lines[]=$this->makePointerSelector_link("PREV",0);
00938                 }
00939 
00940                         // 1-2-3
00941                 for ($a=0;$a<t3lib_div::intInRange(ceil($count/$displayCount),1,10);$a++)       {
00942 #                       $str = ($a*$displayCount+1)."-".(($a+1)*$displayCount);
00943                         $str = $a+1;
00944                         $linkStr = $this->makePointerSelector_link($str,$a);
00945                         $lines[]=       $pointer==$a ? '<strong>['.$linkStr.']</strong>' : $linkStr;
00946                 }
00947 
00948                         // Next pointer:
00949                 if ($pointer+1<ceil($count/$displayCount))      $lines[]=$this->makePointerSelector_link("NEXT",$pointer+1);
00950 
00951                 return implode(" - ",$lines);
00952         }
00953 
00958         function makePointerSelector_link($str,$p)      {
00959                 return '<a href="#" onClick="document.'.$this->prefixId.'[\''.$this->prefixId.'[pointer]\'].value=\''.$p.'\';document.'.$this->prefixId.'.submit();return false;">'.$str.'</a>';
00960         }
00961 
00965         function tellUsWhatIsSeachedFor($sWArr) {
00966                 reset($sWArr);
00967                 $searchingFor="";
00968                 $c=0;
00969                 while(list($k,$v)=each($sWArr)) {
00970                         if ($c) {
00971                                 switch($v["oper"])      {
00972                                         case "OR":
00973                                                 $searchingFor.=" ".$this->pi_getLL("searchFor_or")." ".$this->wrapSW($v["sword"]);
00974                                         break;
00975                                         case "AND NOT":
00976                                                 $searchingFor.=" ".$this->pi_getLL("searchFor_butNot")." ".$this->wrapSW($v["sword"]);
00977                                         break;
00978                                         default:        // AND...
00979                                                 $searchingFor.=" ".$this->pi_getLL("searchFor_and")." ".$this->wrapSW($v["sword"]);
00980                                         break;
00981                                 }
00982 
00983                         } else {
00984                                 $searchingFor=$this->pi_getLL("searchFor")." ".$this->wrapSW($v["sword"]);
00985                         }
00986                         $c++;
00987                 }
00988                 return $searchingFor;
00989         }
00990 
00994         function wrapSW($str)   {
00995                 return "'<span".$this->pi_classParam("sw").">".htmlspecialchars($str)."</span>'";
00996         }
00997 
01001         function renderSelectBox($name,$value,$optValues)       {
01002                 if (is_array($optValues))       {
01003                         $opt=array();
01004                         $isSelFlag=0;
01005                         reset($optValues);
01006                         while(list($k,$v)=each($optValues))     {
01007                                 $sel = (!strcmp($k,$value)?" SELECTED":"");
01008                                 if ($sel)       $isSelFlag++;
01009                                 $opt[]='<option value="'.htmlspecialchars($k).'"'.$sel.'>'.htmlspecialchars($v).'</option>';
01010                         }
01011         #               if (!$isSelFlag && strcmp("",$value))   $opt[]='<option value="'.$value.'" SELECTED>'.htmlspecialchars("CURRENT VALUE '".$value."' DID NOT EXIST AMONG THE OPTIONS").'</option>';
01012                         return '<select name="'.$name.'">'.implode("",$opt).'</select>';
01013                 }
01014         }
01015 
01016 
01017 
01018 
01019 
01020 
01021 
01022 
01023 
01024 
01025 
01026 
01027 
01028 
01029 
01030         /***********************************
01031 
01032                 Result row LAYOUT
01033 
01034         ***********************************/
01035 
01040         function compileResult($resultRows)     {
01041                 $content="";
01042 
01043                 $newResultRows=array();
01044                 reset($resultRows);
01045                 while(list(,$row)=each($resultRows))    {
01046                         $id = md5($row["phash_grouping"]);
01047                         if (is_array($newResultRows[$id]))      {
01048                                 if (!$newResultRows[$id]["show_resume"] && $row["show_resume"]) {       // swapping:
01049                                                 // Remove old
01050                                         $subrows = $newResultRows[$id]["_sub"];
01051                                         unset($newResultRows[$id]["_sub"]);
01052                                         $subrows[] =$newResultRows[$id];
01053 
01054                                                 // Insert new:
01055                                         $newResultRows[$id]=$row;
01056                                         $newResultRows[$id]["_sub"]=$subrows;
01057                                 } else $newResultRows[$id]["_sub"][]=$row;
01058                         } else {
01059                                 $newResultRows[$id]=$row;
01060                         }
01061                 }
01062                 $resultRows=$newResultRows;
01063 
01064 
01065                 switch($this->piVars["group"])  {
01066                         case "sections":
01067                                 $rl2flag = substr($this->piVars["sections"],0,2)=="rl";
01068                                 $sections=array();
01069                                 reset($resultRows);
01070                                 while(list(,$row)=each($resultRows))    {
01071                                         $id = $row["rl0"]."-".$row["rl1"].($rl2flag?"-".$row["rl2"]:"");
01072                                         $sections[$id][]=$row;
01073                                 }
01074 
01075                                 $this->resultSections=array();
01076                                 reset($sections);
01077                                 while(list($id,$resultRows)=each($sections))    {
01078                                         $rlParts = explode("-",$id);
01079 
01080                                         $theId = $rlParts[2]?$rlParts[2]:($rlParts[1]?$rlParts[1]:$rlParts[0]);
01081                                         $theRLid = $rlParts[2]?"rl2_".$rlParts[2]:($rlParts[1]?"rl1_".$rlParts[1]:"0");
01082 
01083                                         $sectionName = substr($this->getPathFromPageId($theId),1);
01084                                         if (!trim($sectionName))        {
01085                                                 $sectionTitleLinked=$this->pi_getLL("unnamedSection").":";
01086                                         } else {
01087                                                 $sectionTitleLinked = '<a href="#" onClick="document.'.$this->prefixId.'[\''.$this->prefixId.'[_sections]\'].value=\''.$theRLid.'\';document.'.$this->prefixId.'.submit();return false;">'.$sectionName.':</a>';
01088                                         }
01089 
01090                                         $content.=$this->makeSectionHeader($id,$sectionTitleLinked,count($resultRows));
01091                                         $this->resultSections[$id] = array($sectionName,count($resultRows));
01092                                         reset($resultRows);
01093                                         while(list(,$row)=each($resultRows))    {
01094                                                 $content.=$this->printResultRow($row);
01095                                         }
01096                                 }
01097                         break;
01098                         default:        // flat:
01099                                 reset($resultRows);
01100                                 while(list(,$row)=each($resultRows))    {
01101                                         $content.=$this->printResultRow($row);
01102                                 }
01103                         break;
01104                 }
01105                 return '<div'.$this->pi_classParam("res").'>'.$content.'</div>';
01106         }
01107 
01111         function makeSectionHeader($id,$sectionTitleLinked,$countResultRows)    {
01112                 return '<div'.$this->pi_classParam("secHead").'><a name="'.md5($id).'"></a><table '.$this->conf["tableParams."]["secHead"].'>
01113                                                 <tr>
01114                                                 <td width="95%"><h2>'.$sectionTitleLinked.'</h2></td>
01115                                                 <td align="right" nowrap><p>'.$countResultRows.' '.$this->pi_getLL("word_page".($countResultRows>1?"s":"")).'</p></td>
01116                                                 </tr>
01117                                         </table></div>';
01118         }
01119 
01123         function printResultRow($row,$headerOnly=0)     {
01124                 $specRowConf = $this->getSpecialConfigForRow($row);
01125                 $CSSsuffix = $specRowConf["CSSsuffix"]?"-".$specRowConf["CSSsuffix"]:"";
01126 
01127                         // If external media, link to the media-file instead.
01128                 if ($row["item_type"])  {
01129                         if ($row["show_resume"])        {       // Can link directly.
01130                                 $title = '<a href="'.$row["data_filename"].'">'.$row["result_number"].": ".$this->makeTitle($row).'</a>';
01131                         } else {        // Suspicious, so linking to page instead...
01132                                 $copy_row=$row;
01133                                 unset($copy_row["cHashParams"]);
01134                                 $title = $this->linkPage($row["page_id"],$row["result_number"].": ".$this->makeTitle($row),$copy_row);
01135                         }
01136                 } else {        // Else the page:
01137                         $title = $this->linkPage($row["data_page_id"],$row["result_number"].": ".$this->makeTitle($row),$row);
01138                 }
01139 
01140                         // Make the header row with title, icon and rating bar.:
01141                 $out.='<tr '.$this->pi_classParam("title".$CSSsuffix).'>
01142                         <td width="16">'.$this->makeItemTypeIcon($row["item_type"],"",$specRowConf).'</td>
01143                         <td width="95%" nowrap><p>'.$title.'</p></td>
01144                         <td nowrap><p'.$this->pi_classParam("percent".$CSSsuffix).'>'.$this->makeRating($row).'</p></td>
01145                 </tr>';
01146 
01147                         // Print the resume-section. If headerOnly is 1, then  only the short resume is printed
01148                 if (!$headerOnly)       {
01149                         $out.='<tr>
01150                                 <td></td>
01151                                 <td colspan=2'.$this->pi_classParam("descr".$CSSsuffix).'><p>'.$this->makeDescription($row,$this->piVars["extResume"]?0:1).'</p></td>
01152                         </tr>';
01153                         $out.='<tr>
01154                                 <td></td>
01155                                 <td '.$this->pi_classParam("info".$CSSsuffix).' nowrap><p>'.$this->makeInfo($row).'</p></td>
01156                                 <td '.$this->pi_classParam("info".$CSSsuffix).' align="right"><p>'.$this->makeAccessIndication($row["page_id"]).''.$this->makeLanguageIndication($row).'</p></td>
01157                         </tr>';
01158                 } elseif ($headerOnly==1) {
01159                         $out.='<tr>
01160                                 <td></td>
01161                                 <td colspan=2'.$this->pi_classParam("descr".$CSSsuffix).'><p>'.$this->makeDescription($row,1,180).'</p></td>
01162                         </tr>';
01163                 } elseif ($headerOnly==2) {
01164                         // nothing.
01165                 }
01166 
01167                         // If there are subrows (eg. subpages in a PDF-file or if a duplicate page is selected due to user-login (phash_grouping))
01168                 if (is_array($row["_sub"]))     {
01169                         if ($row["item_type"]==2)       {
01170                                 $out.='<tr>
01171                                         <td></td>
01172                                         <td colspan=2><p><BR>'.$this->pi_getLL("res_otherMatching").'<BR><BR></p></td>
01173                                 </tr>';
01174 
01175                                 reset($row["_sub"]);
01176                                 while(list(,$subRow)=each($row["_sub"]))        {
01177                                         $out.='<tr>
01178                                                 <td></td>
01179                                                 <td colspan=2><p>'.$this->printResultRow($subRow,1).'</p></td>
01180                                         </tr>';
01181                                 }
01182                         } else {
01183                                 $out.='<tr>
01184                                         <td></td>
01185                                         <td colspan=2><p>'.$this->pi_getLL("res_otherPageAsWell").'</p></td>
01186                                 </tr>';
01187                         }
01188                 }
01189 
01190                 return '<table '.$this->conf["tableParams."]["searchRes"].'>'.$out.'</table><BR>';
01191         }
01192 
01196         function makeItemTypeIcon($it,$alt="",$specRowConf=array())     {
01197                 $spec_flag = 0;
01198 
01199                 switch($it)     {
01200                         case 1:
01201                                 $icon="html.gif";
01202                         break;
01203                         case 2:
01204                                 $icon="pdf.gif";
01205                         break;
01206                         case 3:
01207                                 $icon="doc.gif";
01208                         break;
01209                         case 4:
01210                                 $icon="txt.gif";
01211                         break;
01212                         default:
01213                                 $icon="pages.gif";
01214                                 if (is_array($specRowConf["pageIcon."]))        {
01215                                         $spec_flag = 1;
01216                                         $spec = $this->cObj->IMAGE($specRowConf["pageIcon."]);
01217                                 }
01218                         break;
01219                 }
01220                 if ($spec_flag) {
01221                         return $spec;
01222                 } else {
01223                         $fullPath = t3lib_extMgm::siteRelPath("indexed_search").'pi/res/'.$icon;
01224                         $info = @getimagesize(PATH_site.$fullPath);
01225 
01226                         return is_array($info) ? '<img src="'.$fullPath.'" hspace=3 '.$info[3].' title="'.htmlspecialchars($alt).'">' : '';
01227                 }
01228         }
01229 
01233         function makeRating($row)       {
01234 /*
01235                                 "rank_flag" => "Rang, prioritet",
01236                                 "rank_freq" => "Rang, frekvens",
01237                                 "rank_first" => "Rang, tæt på toppen",
01238                                 "rank_count" => "Rang, antal forekomster",
01239                                 "rating" => "Side-rating",
01240                                 "hits" => "Side-hits",
01241                                 "title" => "Dokumenttitel",
01242                                 "crdate" => "Oprettelsesdato",
01243                                 "mtime" => "Ændringsdato",
01244 */
01245                 switch((string)$this->piVars["order"])  {
01246                         case "rank_count":
01247                                 return $row["order_val"]." matches";
01248                         break;
01249                         case "rank_first":
01250                                 return ceil(t3lib_div::intInRange(255-$row["order_val"],1,255)/255*100)."%";
01251                         break;
01252                         case "rank_flag":
01253                                 if ($this->firstRow["order_val2"])      {
01254                                         $base=$row["order_val1"]*256; // (3 MSB bit, 224 is highest value of order_val1 currently)
01255                                         $freqNumber = $row["order_val2"]/$this->firstRow["order_val2"]*pow(2,13);       // 16-3 MSB = 13
01256                                         $total = t3lib_div::intInRange($base+$freqNumber,0,65536);
01257                                         #debug($total);
01258                                         #debug(log($total)/log(65536)*100,1);
01259                                         return ceil(log($total)/log(65536)*100)."%";
01260                                 }
01261                         break;
01262                         case "rank_freq":
01263                                 $max = 10000;
01264                                 $total = t3lib_div::intInRange($row["order_val"],0,$max);
01265 #                               debug($total);
01266                                 return ceil(log($total)/log($max)*100)."%";
01267                         break;
01268                         case "crdate":
01269                                 return $this->cObj->calcAge(time()-$row["item_crdate"],0); // ,$conf["age"]
01270                         break;
01271                         case "mtime":
01272                                 return $this->cObj->calcAge(time()-$row["item_mtime"],0); // ,$conf["age"]
01273                         break;
01274                         default:        // fx. title
01275 #                               return "[rating...]";
01276                                 return "&nbsp;";
01277                         break;
01278                 }
01279         }
01280 
01285         function makeDescription($row,$noMarkup=0,$lgd=180)     {
01286                 if ($row["show_resume"])        {
01287         #debug($row)    ;
01288                         if (!$noMarkup) {
01289                                 $markedSW = "";
01290                                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'index_fulltext', 'phash='.intval($row['phash']));
01291                                 if ($ftdrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {
01292                                         $markedSW = $this->markupSWpartsOfString($ftdrow["fulltextdata"]);
01293                                 }
01294                                 $GLOBALS['TYPO3_DB']->sql_free_result($res);
01295                         }
01296 
01297                         return htmlspecialchars(t3lib_div::fixed_lgd(str_replace("&nbsp;"," ",$row["item_description"]),$lgd)).(trim($markedSW)?" ... ".$markedSW:"").'
01298                                 <BR><img src=clear.gif width=1 height=5>';
01299                 } else {
01300                         return '<font color="#666666">'.$this->pi_getLL("res_noResume").'
01301                                 <BR><img src=clear.gif width=1 height=5></font>';
01302                 }
01303         }
01304 
01308         function markupSWpartsOfString($str)    {
01309                 $str = str_replace("&nbsp;"," ",t3lib_parsehtml::bidir_htmlspecialchars($str,-1));
01310                 reset($this->sWArr);
01311 #debug($this->sWArr);
01312                 $swForReg=array();
01313                 while(list(,$d)=each($this->sWArr))     {
01314                         $swForReg[]=quotemeta($d["sword"]);
01315                 }
01316                 $regExString = implode("|",$swForReg);
01317 
01318                 $noAlph="[^[:alnum:]]";
01319                 $theType = (string)$this->piVars["type"];
01320                 switch($theType)        {
01321                         case "1":
01322                         case "20":
01323                                 // Nothing...
01324                         break;
01325                         case "2":
01326                                 $regExString = $noAlph."(".$regExString.")";
01327                         break;
01328                         case "3":
01329                                 $regExString = "(".$regExString.")".$noAlph;
01330                         break;
01331                         case "10":
01332                         break;
01333                         default:
01334                                 $regExString = $noAlph."(".$regExString.")".$noAlph;
01335                         break;
01336                 }
01337 #debug(array($regExString));
01338 
01339                 $parts = spliti($regExString,$str,6);
01340 #debug($parts);
01341                 reset($parts);
01342                 $strLen=0;
01343 
01344                 $snippets=array();
01345                 while(list($k,$strP)=each($parts))      {
01346                         if ($k+1<count($parts)) {
01347                                 $strLen+=strlen($strP);
01348                                 $reg=array();
01349                                 eregi("^".$regExString,substr($str,$strLen,50),$reg);
01350 
01351                                 $snippets[] = array(
01352 #                                       substr($str,$strLen-50,50),
01353                                         substr($parts[$k],-50),
01354                                         substr($str,$strLen,strlen($reg[0])),
01355                                         substr($parts[$k+1],0,50)
01356 #                                       substr($str,$strLen+strlen($reg[0]),50),
01357                                 );
01358 
01359                                 $strLen+=strlen($reg[0]);
01360 #                               debug($reg);
01361                         }
01362                 }
01363 
01364                 reset($snippets);
01365                 $content=array();
01366                 while(list(,$d)=each($snippets))        {
01367                         $content[]=htmlspecialchars($d[0]).'<span'.$this->pi_classParam("redMarkup").'>'.htmlspecialchars($d[1]).'</span>'.htmlspecialchars($d[2]);
01368                 }
01369 
01370                 return implode(" ... ",$content);
01371         }
01372 
01376         function makeTitle($row)        {
01377                 $add="";
01378                 if ($row["item_type"]==2)       {
01379                         $dat = unserialize($row["cHashParams"]);
01380                         $pp=explode("-",$dat["key"]);
01381                         if ($pp[0]!=$pp[1])     {
01382                                 $add=", pages ".$dat["key"];
01383                         } else $add=", page ".$pp[0];
01384                 }
01385                 return htmlspecialchars(t3lib_div::fixed_lgd($row["item_title"],50)).$add;
01386         }
01387 
01391         function makeInfo($row) {
01392                 $lines=array();
01393                 $lines[]=$this->pi_getLL("res_size")." ".t3lib_div::formatSize($row["item_size"])."";
01394                 $lines[]=$this->pi_getLL("res_created")." ".date("d-m-y",$row["item_crdate"])."";
01395                 $lines[]=$this->pi_getLL("res_modified")." ".date("d-m-y H:i",$row["item_mtime"])."";
01396                 $out = implode(" - ",$lines);
01397                 $pathId = $row["data_page_id"]?$row["data_page_id"]:$row["page_id"];
01398                 $pathMP = $row["data_page_id"]?$row["data_page_mp"]:"";
01399                 $out.="<BR>".$this->pi_getLL("res_path")." ".$this->linkPage($pathId,htmlspecialchars($this->getPathFromPageId($pathId,$pathMP)));
01400                 return $out;
01401         }
01402 
01406         function getSpecialConfigForRow($row)   {
01407                 $pathId = $row["data_page_id"]?$row["data_page_id"]:$row["page_id"];
01408                 $pathMP = $row["data_page_id"]?$row["data_page_mp"]:"";
01409 
01410                 $rl = $this->getRootLine($pathId,$pathMP);
01411                 $specConf = $this->conf["specConfs."]["0."];
01412                 if (is_array($rl))      {
01413                         reset($rl);
01414                         while(list(,$dat)=each($rl))    {
01415                                 if (is_array($this->conf["specConfs."][$dat["uid"]."."]))       {
01416                                         $specConf = $this->conf["specConfs."][$dat["uid"]."."];
01417                                         break;
01418                                 }
01419                         }
01420                 }
01421 
01422                 return $specConf;
01423         }
01424 
01428         function makeLanguageIndication($row)   {
01429                 if ($row["item_type"]==0)       {
01430                         switch($row["sys_language_uid"])        {
01431                                         // OBVIOUSLY this will not work generally. First we need to know WHICH flag is used for WHICH language-uid. This just shows the concept works.
01432                                 case 1:
01433                                         return '<img src="tslib/media/flags/flag_dk.gif" width="21" height="13" border="0" alt="Danish">';
01434                                 break;
01435                                 case 2:
01436                                         return '<img src="tslib/media/flags/flag_de.gif" width="21" height="13" border="0" alt="German">';
01437                                 break;
01438                                 default:
01439                                 #       return '<img src="tslib/media/flags/flag_uk.gif" width="21" height="13" border="0" alt="English - default">';
01440                                 break;
01441                         }
01442                 }
01443                 return "&nbsp;";
01444         }
01445 
01449         function makeAccessIndication($id)      {
01450                 if (is_array($this->fe_groups_required[$id]) && count($this->fe_groups_required[$id]))  {
01451                         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"),implode(",",array_unique($this->fe_groups_required[$id]))).'">';
01452                 }
01453         }
01454 
01458         function linkPage($id,$str,$row=array())        {
01459 #               return $str;
01460                 $urlParameters = unserialize($row["cHashParams"]);
01461 #               $urlParameters["cHash"] = t3lib_div::shortMD5(serialize($row["cHashParams"]));  // not needed - it's there already...
01462 #debug($urlParameters);
01463 
01464 
01465                         // 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...
01466                 if (!is_array($this->domain_records[$id]))      {
01467                         $this->getPathFromPageId($id);
01468                 }
01469 
01470                         // If external domain, then link to that:
01471                 if (count($this->domain_records[$id]))  {
01472                         reset($this->domain_records[$id]);
01473                         $firstDom = current($this->domain_records[$id]);
01474                         $scheme = t3lib_div::getIndpEnv('TYPO3_SSL') ? 'https://' : 'http://';
01475 
01476                         $addParams="";
01477                         if (is_array($urlParameters))   {
01478                                 if (count($urlParameters))      {
01479                                         reset($urlParameters);
01480                                         while(list($k,$v)=each($urlParameters)) {
01481                                                 $addParams.="&".$k."=".rawurlencode($v);
01482                                         }
01483                                 }
01484                         }
01485 
01486                         return '<a href="'.$scheme.$firstDom.'/index.php?id='.$id.$addParams.'" target="'.$this->conf["search."]["detect_sys_domain_records."]["target"].'">'.htmlspecialchars($str).'</a>';
01487                 } else {
01488                         return $this->pi_linkToPage($str,$id,$this->conf["result_link_target"],$urlParameters);
01489                 }
01490         }
01491 
01495         function getRootLine($id,$pathMP="")    {
01496                 $identStr = $id."|".$pathMP;
01497 
01498                 if (!isset($this->cache_path[$identStr]))       {
01499                         $this->cache_rl[$identStr] = $GLOBALS["TSFE"]->sys_page->getRootLine($id,$pathMP);
01500                 }
01501                 return $this->cache_rl[$identStr];
01502         }
01503 
01507         function getFirstSysDomainRecordForPage($id)    {
01508                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('domainName', 'sys_domain', 'pid='.intval($id).$this->cObj->enableFields('sys_domain'), '', 'sorting');
01509                 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
01510                 return ereg_replace("\/$","",$row["domainName"]);
01511         }
01512 
01516         function getPathFromPageId($id,$pathMP="")      {
01517                         // Here I imagine some caching...
01518                 $identStr = $id."|".$pathMP;
01519 
01520                 if (!isset($this->cache_path[$identStr]))       {
01521                         $this->fe_groups_required[$id]=array();
01522                         $this->domain_records[$id]=array();
01523                         $rl = $this->getRootLine($id,$pathMP);
01524                         $hitRoot=0;
01525                         $path="";
01526                         if (is_array($rl) && count($rl))        {
01527                                 reset($rl);
01528                                 while(list($k,$v)=each($rl))    {
01529                                                 // Check fe_user
01530                                         if ($v["fe_group"] && ($v["uid"]==$id || $v["extendToSubpages"]))       {
01531                                                 $this->fe_groups_required[$id][]=$v["fe_group"];
01532                                         }
01533                                                 // Check sys_domain.
01534                                         if ($this->conf["search."]["detect_sys_domain_records"])        {
01535                                                 $sysDName = $this->getFirstSysDomainRecordForPage($v["uid"]);
01536                                                 if ($sysDName)  {
01537                                                         $this->domain_records[$id][]=$sysDName;
01538 #                                                       debug($sysDName);
01539                                                                 // Set path accordingly:
01540                                                         $path=$sysDName.$path;
01541                                                         break;
01542                                                 }
01543                                         }
01544 
01545                                                 // Stop, if we find that the current id is the current root page.
01546                                         if ($v["uid"]==$GLOBALS["TSFE"]->config["rootLine"][0]["uid"])          {
01547                                                 break;
01548                                         }
01549                                         $path="/".$v["title"].$path;
01550                                 }
01551                         }
01552 
01553 #                       $pageRec = $GLOBALS["TSFE"]->sys_page->checkRecord("pages",$id);
01554 #                       $path.="/".$pageRec["title"];
01555                         $this->cache_path[$identStr] = $path;
01556 
01557                         if (is_array($this->conf["path_stdWrap."]))     {
01558                                 $this->cache_path[$identStr] = $this->cObj->stdWrap($this->cache_path[$identStr], $this->conf["path_stdWrap."]);
01559                         }
01560                 }
01561 
01562                 return $this->cache_path[$identStr];
01563         }
01564 
01568         function pi_list_browseresults($showResultCount=1,$addString="",$addPart="")    {
01569 
01570                         // Initializing variables:
01571                 $pointer=$this->piVars["pointer"];
01572                 $count=$this->internal["res_count"];
01573                 $results_at_a_time = t3lib_div::intInRange($this->internal["results_at_a_time"],1,1000);
01574                 $maxPages = t3lib_div::intInRange($this->internal["maxPages"],1,100);
01575                 $max = t3lib_div::intInRange(ceil($count/$results_at_a_time),1,$maxPages);
01576                 $pointer=intval($pointer);
01577                 $links=array();
01578 
01579                         // Make browse-table/links:
01580                 if ($pointer>0) {
01581                         $links[]='<td><p>'.$this->makePointerSelector_link($this->pi_getLL("pi_list_browseresults_prev","< Previous"),$pointer-1).'</p></td>';
01582                 }
01583                 for($a=0;$a<$max;$a++)  {
01584                         $links[]='<td'.($pointer==$a?$this->pi_classParam("browsebox-SCell"):"").'><p>'.$this->makePointerSelector_link(trim($this->pi_getLL("pi_list_browseresults_page","Page")." ".($a+1)),$a).'</p></td>';
01585                 }
01586                 if ($pointer<ceil($count/$results_at_a_time)-1) {
01587                         $links[]='<td><p>'.$this->makePointerSelector_link($this->pi_getLL("pi_list_browseresults_next","Next >"),$pointer+1).'</p></td>';
01588                 }
01589 
01590                 $pR1 = $pointer*$results_at_a_time+1;
01591                 $pR2 = $pointer*$results_at_a_time+$results_at_a_time;
01592                 $sTables = '<DIV'.$this->pi_classParam("browsebox").'>'.
01593                         ($showResultCount ? '<P>'.sprintf(
01594                                 str_replace("###SPAN_BEGIN###","<span".$this->pi_classParam("browsebox-strong").">",$this->pi_getLL("pi_list_browseresults_displays","Displaying results ###SPAN_BEGIN###%s to %s</span> out of ###SPAN_BEGIN###%s</span>")),
01595                                 $pR1,
01596                                 min(array($this->internal["res_count"],$pR2)),
01597                                 $this->internal["res_count"]
01598                                 ).$addString.'</P>':''
01599                         ).$addPart.
01600                 '<table>
01601                         <tr>'.implode("",$links).'</tr>
01602                 </table></DIV>';
01603                 return $sTables;
01604         }
01605 
01609         function getMenu($id)   {
01610                 if ($this->conf["show."]["LxALLtypes"]) {
01611                         $output = Array();
01612                         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('title,uid', 'pages', 'pid='.intval($id).$this->cObj->enableFields('pages'), '', 'sorting');
01613                         while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))       {
01614                                 $output[$row["uid"]]=$GLOBALS["TSFE"]->sys_page->getPageOverlay($row);
01615                         }
01616                         return $output;
01617                 } else {
01618                         return $GLOBALS["TSFE"]->sys_page->getMenu($id);
01619                 }
01620         }
01621 }
01622 
01623 if (defined("TYPO3_MODE") && $TYPO3_CONF_VARS[TYPO3_MODE]["XCLASS"]["ext/indexed_search/pi/class.tx_indexedsearch.php"])        {
01624         include_once($TYPO3_CONF_VARS[TYPO3_MODE]["XCLASS"]["ext/indexed_search/pi/class.tx_indexedsearch.php"]);
01625 }
01626 
01627 ?>


Généré par L'expert TYPO3 avec  doxygen 1.4.6