| [ PHPXref.com ] | [ Generated: Sun Jul 20 20:48:27 2008 ] | [ TYPO3 4.0 ] |
| [ Index ] [ Variables ] [ Functions ] [ Classes ] [ Constants ] [ Statistics ] | ||
[Summary view] [Print] [Text view]
1 <?php 2 /*************************************************************** 3 * Copyright notice 4 * 5 * (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com) 6 * All rights reserved 7 * 8 * This script is part of the TYPO3 project. The TYPO3 project is 9 * free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * The GNU General Public License can be found at 15 * http://www.gnu.org/copyleft/gpl.html. 16 * A copy is found in the textfile GPL.txt and important notices to the license 17 * from the author is found in LICENSE.txt distributed with these scripts. 18 * 19 * 20 * This script is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU General Public License for more details. 24 * 25 * This copyright notice MUST APPEAR in all copies of the script! 26 ***************************************************************/ 27 /** 28 * Searching in database tables, typ. "pages" and "tt_content" 29 * Used to generate search queries for TypoScript. 30 * The class is included from "class.tslib_pagegen.php" based on whether there has been detected content in the GPvar "sword" 31 * 32 * $Id: class.tslib_search.php,v 1.11 2005/04/01 14:37:14 typo3 Exp $ 33 * Revised for TYPO3 3.6 June/2003 by Kasper Skaarhoj 34 * 35 * @author Kasper Skaarhoj <kasperYYYY@typo3.com> 36 * @author Rene Fritz <r.fritz@colorcube.de> 37 */ 38 /** 39 * [CLASS/FUNCTION INDEX of SCRIPT] 40 * 41 * 42 * 43 * 88: class tslib_search 44 * 127: function register_tables_and_columns($requestedCols,$allowedCols) 45 * 168: function explodeCols($in) 46 * 193: function register_and_explode_search_string($sword) 47 * 226: function split($origSword, $specchars='+-', $delchars='+.,-') 48 * 269: function quotemeta($str) 49 * 285: function build_search_query($endClause) 50 * 371: function build_search_query_for_searchwords() 51 * 413: function get_operator($operator) 52 * 436: function count_query() 53 * 449: function execute_query() 54 * 462: function get_searchwords() 55 * 477: function get_searchwordsArray() 56 * 57 * TOTAL FUNCTIONS: 12 58 * (This index is automatically created/updated by the extension "extdeveval") 59 * 60 */ 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 /** 81 * Search class used for the content object SEARCHRESULT 82 * 83 * @author Kasper Skaarhoj <kasperYYYY@typo3.com> 84 * @package TYPO3 85 * @subpackage tslib 86 * @see tslib_cObj::SEARCHRESULT() 87 */ 88 class tslib_search { 89 var $tables = Array (); 90 91 var $group_by = 'PRIMARY_KEY'; // Alternatively 'PRIMARY_KEY'; sorting by primary key 92 var $default_operator = 'AND'; // Standard SQL-operator between words 93 var $operator_translate_table_caseinsensitive = TRUE; 94 var $operator_translate_table = Array ( // case-sensitiv. Defineres the words, which will be operators between words 95 Array ('+' , 'AND'), 96 Array ('|' , 'AND'), 97 Array ('-' , 'AND NOT'), 98 // english 99 Array ('and' , 'AND'), 100 Array ('or' , 'OR'), 101 Array ('not' , 'AND NOT'), 102 ); 103 104 // Internal 105 var $sword_array; // Contains the search-words and operators 106 var $queryParts; // Contains the query parts after processing. 107 108 var $other_where_clauses; // Addition to the whereclause. This could be used to limit search to a certain page or alike in the system. 109 var $fTable; // This is set with the foreign table that 'pages' are connected to. 110 111 var $res_offset = 0; // How many rows to offset from the beginning 112 var $res_shows = 20; // How many results to show (0 = no limit) 113 var $res_count; // Intern: How many results, there was last time (with the exact same searchstring. 114 115 var $pageIdList=''; // List of pageIds. 116 117 var $listOfSearchFields =''; 118 119 /** 120 * Creates the $this->tables-array. 121 * The 'pages'-table is ALWAYS included as the search is page-based. Apart from this there may be one and only one table, joined with the pages-table. This table is the first table mentioned in the requested-list. If any more tables are set here, they are ignored. 122 * 123 * @param string is a list (-) of columns that we want to search. This could be input from the search-form (see TypoScript documentation) 124 * @param string $allowedCols: is the list of columns, that MAY be searched. All allowed cols are set as result-fields. All requested cols MUST be in the allowed-fields list. 125 * @return void 126 */ 127 function register_tables_and_columns($requestedCols,$allowedCols) { 128 $rCols=$this->explodeCols($requestedCols); 129 $aCols=$this->explodeCols($allowedCols); 130 131 foreach ($rCols as $k => $v) { 132 $rCols[$k]=trim($v); 133 if (in_array($rCols[$k], $aCols)) { 134 $parts = explode('.',$rCols[$k]); 135 $this->tables[$parts[0]]['searchfields'][] = $parts[1]; 136 } 137 } 138 $this->tables['pages']['primary_key'] = 'uid'; 139 $this->tables['pages']['resultfields'][] = 'uid'; 140 unset($this->tables['pages']['fkey']); 141 142 foreach ($aCols as $k => $v) { 143 $aCols[$k]=trim($v); 144 $parts = explode('.',$aCols[$k]); 145 $this->tables[$parts[0]]['resultfields'][] = $parts[1].' AS '.str_replace('.','_',$aCols[$k]); 146 $this->tables[$parts[0]]['fkey']='pid'; 147 } 148 149 $this->fTable=''; 150 foreach ($this->tables as $t => $v) { 151 if ($t!='pages') { 152 if (!$this->fTable) { 153 $this->fTable = $t; 154 } else { 155 unset($this->tables[$t]); 156 } 157 } 158 } 159 } 160 161 /** 162 * Function that can convert the syntax for entering which tables/fields the search should be conducted in. 163 * 164 * @param string This is the code-line defining the tables/fields to search. Syntax: '[table1].[field1]-[field2]-[field3] : [table2].[field1]-[field2]' 165 * @return array An array where the values is "[table].[field]" strings to search 166 * @see register_tables_and_columns() 167 */ 168 function explodeCols($in) { 169 $theArray = explode(':',$in); 170 $out = Array(); 171 while(list(,$val)=each($theArray)) { 172 $val=trim($val); 173 $parts = explode('.',$val); 174 if ($parts[0] && $parts[1]) { 175 $subparts = explode('-',$parts[1]); 176 while(list(,$piece)=each($subparts)) { 177 $piece=trim($piece); 178 if ($piece) $out[]=$parts[0].'.'.$piece; 179 } 180 } 181 } 182 return $out; 183 } 184 185 /** 186 * Takes a search-string (WITHOUT SLASHES or else it'll be a little sppooky , NOW REMEMBER to unslash!!) 187 * Sets up $this->sword_array op with operators. 188 * This function uses $this->operator_translate_table as well as $this->default_operator 189 * 190 * @param string The input search-word string. 191 * @return void 192 */ 193 function register_and_explode_search_string($sword) { 194 $sword = trim($sword); 195 if ($sword) { 196 $components = $this->split($sword); 197 $s_sword = ''; // the searchword is stored here during the loop 198 if (is_array($components)) { 199 $i=0; 200 $lastoper = ''; 201 reset($components); 202 while (list($key,$val) = each ($components)) { 203 $operator=$this->get_operator($val); 204 if ($operator) { 205 $lastoper = $operator; 206 } elseif (strlen($val)>1) { // A searchword MUST be at least two characters long! 207 $this->sword_array[$i]['sword'] = $val; 208 $this->sword_array[$i]['oper'] = ($lastoper) ? $lastoper : $this->default_operator; 209 $lastoper = ''; 210 $i++; 211 } 212 } 213 } 214 } 215 } 216 217 /** 218 * Used to split a search-word line up into elements to search for. This function will detect boolean words like AND and OR, + and -, and even find sentences encapsulated in "" 219 * This function could be re-written to be more clean and effective - yet it's not that important. 220 * 221 * @param string The raw sword string from outside 222 * @param string Special chars which are used as operators (+- is default) 223 * @param string Special chars which are deleted if the append the searchword (+-., is default) 224 * @return mixed Returns an ARRAY if there were search words, othervise the return value may be unset. 225 */ 226 function split($origSword, $specchars='+-', $delchars='+.,-') { 227 $sword = $origSword; 228 $specs = '['.$this->quotemeta($specchars).']'; 229 $delchars = '['.$this->quotemeta($delchars).']'; 230 231 // As long as $sword is true (that means $sword MUST be reduced little by little until its empty inside the loop!) 232 while ($sword) { 233 if (ereg('^"',$sword)) { // There was a double-quote and we will then look for the ending quote. 234 $sword = ereg_replace('^"','',$sword); // Removes first double-quote 235 ereg('^[^"]*',$sword,$reg); // Removes everything till next double-quote 236 $value[] = $reg[0]; // reg[0] is the value, should not be trimmed 237 $sword = ereg_replace('^'.$this->quotemeta($reg[0]),'',$sword); 238 $sword = trim(ereg_replace('^"','',$sword)); // Removes last double-quote 239 } elseif (ereg('^'.$specs,$sword,$reg)) { 240 $value[] = $reg[0]; 241 $sword = trim(ereg_replace('^'.$specs,'',$sword)); // Removes = sign 242 } elseif (ereg('[\+\-]',$sword)) { // Check if $sword contains + or - 243 // + and - shall only be interpreted as $specchars when there's whitespace before it 244 // otherwise it's included in the searchword (e.g. "know-how") 245 $a_sword = explode(' ',$sword); // explode $sword to single words 246 $word = array_shift($a_sword); // get first word 247 $word = ereg_replace($delchars.'$','',$word); // Delete $delchars at end of string 248 $value[] = $word; // add searchword to values 249 $sword = implode(' ',$a_sword); // re-build $sword 250 } else { 251 // There are no double-quotes around the value. Looking for next (space) or special char. 252 ereg('^[^ '.$this->quotemeta($specchars).']*',$sword,$reg); 253 $word = ereg_replace($delchars.'$','',trim($reg[0])); // Delete $delchars at end of string 254 $value[] = $word; 255 $sword = trim(ereg_replace('^'.$this->quotemeta($reg[0]),'',$sword)); 256 } 257 } 258 259 return $value; 260 } 261 262 /** 263 * Local version of quotemeta. This is the same as the PHP function 264 * but the vertical line, |, and minus, -, is also escaped with a slash. 265 * 266 * @param string String to pass through quotemeta() 267 * @return string Return value 268 */ 269 function quotemeta($str) { 270 $str = str_replace('|','\|',quotemeta($str)); 271 #$str = str_replace('-','\-',$str); // Breaks "-" which should NOT have a slash before it inside of [ ] in a regex. 272 return $str; 273 } 274 275 /** 276 * This creates the search-query. 277 * In TypoScript this is used for searching only records not hidden, start/endtimed and fe_grouped! (enable-fields, see tt_content) 278 * Sets $this->queryParts 279 * 280 * @param string $endClause is some extra conditions that the search must match. 281 * @return boolean Returns true no matter what - sweet isn't it! 282 * @access private 283 * @see tslib_cObj::SEARCHRESULT() 284 */ 285 function build_search_query($endClause) { 286 287 if (is_array($this->tables)) { 288 $tables = $this->tables; 289 $primary_table = ''; 290 291 // Primary key table is found. 292 foreach($tables as $key => $val) { 293 if ($tables[$key]['primary_key']) {$primary_table = $key;} 294 } 295 296 if ($primary_table) { 297 298 // Initialize query parts: 299 $this->queryParts = array( 300 'SELECT' => '', 301 'FROM' => '', 302 'WHERE' => '', 303 'GROUPBY' => '', 304 'ORDERBY' => '', 305 'LIMIT' => '', 306 ); 307 308 // Find tables / field names to select: 309 $fieldArray = array(); 310 $tableArray = array(); 311 foreach($tables as $key => $val) { 312 $tableArray[] = $key; 313 $resultfields = $tables[$key]['resultfields']; 314 if (is_array($resultfields)) { 315 foreach($resultfields as $key2 => $val2) { 316 $fieldArray[] = $key.'.'.$val2; 317 } 318 } 319 } 320 $this->queryParts['SELECT'] = implode(',',$fieldArray); 321 $this->queryParts['FROM'] = implode(',',$tableArray); 322 323 // Set join WHERE parts: 324 $whereArray = array(); 325 326 $primary_table_and_key = $primary_table.'.'.$tables[$primary_table]['primary_key']; 327 $primKeys = Array(); 328 foreach($tables as $key => $val) { 329 $fkey = $tables[$key]['fkey']; 330 if ($fkey) { 331 $primKeys[] = $key.'.'.$fkey.'='.$primary_table_and_key; 332 } 333 } 334 if (count($primKeys)) { 335 $whereArray[] = '('.implode(' OR ',$primKeys).')'; 336 } 337 338 // Additional where clause: 339 if (trim($endClause)) { 340 $whereArray[] = trim($endClause); 341 } 342 343 // Add search word where clause: 344 $query_part = $this->build_search_query_for_searchwords(); 345 if (!$query_part) { 346 $query_part = '(0!=0)'; 347 } 348 $whereArray[] = '('.$query_part.')'; 349 350 // Implode where clauses: 351 $this->queryParts['WHERE'] = implode(' AND ',$whereArray); 352 353 // Group by settings: 354 if ($this->group_by) { 355 if ($this->group_by == 'PRIMARY_KEY') { 356 $this->queryParts['GROUPBY'] = $primary_table_and_key; 357 } else { 358 $this->queryParts['GROUPBY'] = $this->group_by; 359 } 360 } 361 } 362 } 363 } 364 365 /** 366 * Creates the part of the SQL-sentence, that searches for the search-words ($this->sword_array) 367 * 368 * @return string Part of where class limiting result to the those having the search word. 369 * @access private 370 */ 371 function build_search_query_for_searchwords() { 372 373 if (is_array($this->sword_array)) { 374 $main_query_part = array(); 375 376 foreach($this->sword_array as $key => $val) { 377 $s_sword = $this->sword_array[$key]['sword']; 378 379 // Get subQueryPart 380 $sub_query_part = array(); 381 382 $this->listOfSearchFields=''; 383 foreach($this->tables as $key3 => $val3) { 384 $searchfields = $this->tables[$key3]['searchfields']; 385 if (is_array($searchfields)) { 386 foreach($searchfields as $key2 => $val2) { 387 $this->listOfSearchFields.= $key3.'.'.$val2.','; 388 $sub_query_part[] = $key3.'.'.$val2.' LIKE \'%'.$GLOBALS['TYPO3_DB']->quoteStr($s_sword, $key3).'%\''; 389 } 390 } 391 } 392 393 if (count($sub_query_part)) { 394 $main_query_part[] = $this->sword_array[$key]['oper']; 395 $main_query_part[] = '('.implode(' OR ',$sub_query_part).')'; 396 } 397 } 398 399 if (count($main_query_part)) { 400 unset($main_query_part[0]); // Remove first part anyways. 401 return implode(' ',$main_query_part); 402 } 403 } 404 } 405 406 /** 407 * This returns an SQL search-operator (eg. AND, OR, NOT) translated from the current localized set of operators (eg. in danish OG, ELLER, IKKE). 408 * 409 * @param string The possible operator to find in the internal operator array. 410 * @return string If found, the SQL operator for the localized input operator. 411 * @access private 412 */ 413 function get_operator($operator) { 414 $operator = trim($operator); 415 $op_array = $this->operator_translate_table; 416 reset ($op_array); 417 if ($this->operator_translate_table_caseinsensitive) { 418 $operator = strtolower($operator); // case-conversion is charset insensitive, but it doesn't spoil anything if input string AND operator table is already converted 419 } 420 while (list($key,$val) = each($op_array)) { 421 $item = $op_array[$key][0]; 422 if ($this->operator_translate_table_caseinsensitive) { 423 $item = strtolower($item); // See note above. 424 } 425 if ($operator==$item) { 426 return $op_array[$key][1]; 427 } 428 } 429 } 430 431 /** 432 * Counts the results and sets the result in $this->res_count 433 * 434 * @return boolean True, if $this->query was found 435 */ 436 function count_query() { 437 if (is_array($this->queryParts)) { 438 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($this->queryParts['SELECT'], $this->queryParts['FROM'], $this->queryParts['WHERE'], $this->queryParts['GROUPBY']); 439 $this->res_count = $GLOBALS['TYPO3_DB']->sql_num_rows($res); 440 return TRUE; 441 } 442 } 443 444 /** 445 * Executes the search, sets result pointer in $this->result 446 * 447 * @return boolean True, if $this->query was set and query performed 448 */ 449 function execute_query() { 450 if (is_array($this->queryParts)) { 451 $this->result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($this->queryParts); 452 return TRUE; 453 } 454 } 455 456 /** 457 * Returns URL-parameters with the current search words. 458 * Used when linking to result pages so that search words can be highlighted. 459 * 460 * @return string URL-parameters with the searchwords 461 */ 462 function get_searchwords() { 463 $SWORD_PARAMS = ''; 464 if (is_array($this->sword_array)) { 465 foreach($this->sword_array as $key => $val) { 466 $SWORD_PARAMS.= '&sword_list[]='.rawurlencode($val['sword']); 467 } 468 } 469 return $SWORD_PARAMS; 470 } 471 472 /** 473 * Returns an array with the search words in 474 * 475 * @return array IF the internal sword_array contained search words it will return these, otherwise "void" 476 */ 477 function get_searchwordsArray() { 478 if (is_array($this->sword_array)) { 479 foreach($this->sword_array as $key => $val) { 480 $swords[] = $val['sword']; 481 } 482 } 483 return $swords; 484 } 485 } 486 487 488 489 490 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['tslib/class.tslib_search.php']) { 491 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['tslib/class.tslib_search.php']); 492 } 493 494 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| [ Powered by PHPXref - Served by Debian GNU/Linux ] |