Documentation TYPO3 par Ameos

class.tslib_search.php

00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-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 ***************************************************************/
00088 class tslib_search {
00089         var $tables = Array ();
00090 
00091         var $group_by = 'PRIMARY_KEY';                                                  // Alternatively 'PRIMARY_KEY'; sorting by primary key
00092         var $default_operator = 'AND';                                                  // Standard SQL-operator between words
00093         var $operator_translate_table_caseinsensitive = '1';
00094         var $operator_translate_table = Array (                                 // case-sensitiv. Defineres the words, which will be operators between words
00095                 Array ('+' , 'AND'),
00096                 Array ('-' , 'AND NOT'),
00097                         // english
00098                 Array ('AND' , 'AND'),
00099                 Array ('OR' , 'OR'),
00100                 Array ('NOT' , 'AND NOT'),
00101                         // danish
00102                 Array ('OG' , 'AND'),
00103                 Array ('ELLER' , 'OR'),
00104                 Array ('UDEN' , 'AND NOT')
00105         );
00106 
00107         // Internal
00108         var $sword_array;               // Contains the search-words and operators
00109         var $queryParts;                // Contains the query parts after processing.
00110 
00111         var $other_where_clauses;       // Addition to the whereclause. This could be used to limit search to a certain page or alike in the system.
00112         var $fTable;            // This is set with the foreign table that 'pages' are connected to.
00113 
00114         var $res_offset = 0;    // How many rows to offset from the beginning
00115         var $res_shows = 20;    // How many results to show (0 = no limit)
00116         var $res_count;                 // Intern: How many results, there was last time (with the exact same searchstring.
00117 
00118         var $pageIdList='';             // List of pageIds.
00119 
00120         var $listOfSearchFields ='';
00121 
00130         function register_tables_and_columns($requestedCols,$allowedCols)       {
00131                 $rCols=$this->explodeCols($requestedCols);
00132                 $aCols=$this->explodeCols($allowedCols);
00133 
00134                 foreach ($rCols as $k => $v)    {
00135                         $rCols[$k]=trim($v);
00136                         if (in_array($rCols[$k], $aCols))       {
00137                                 $parts = explode('.',$rCols[$k]);
00138                                 $this->tables[$parts[0]]['searchfields'][] = $parts[1];
00139                         }
00140                 }
00141                 $this->tables['pages']['primary_key'] = 'uid';
00142                 $this->tables['pages']['resultfields'][] = 'uid';
00143                 unset($this->tables['pages']['fkey']);
00144 
00145                 foreach ($aCols as $k => $v)    {
00146                         $aCols[$k]=trim($v);
00147                         $parts = explode('.',$aCols[$k]);
00148                         $this->tables[$parts[0]]['resultfields'][] = $parts[1].' AS '.str_replace('.','_',$aCols[$k]);
00149                         $this->tables[$parts[0]]['fkey']='pid';
00150                 }
00151 
00152                 $this->fTable='';
00153                 foreach ($this->tables as $t => $v)     {
00154                         if ($t!='pages')        {
00155                                 if (!$this->fTable)     {
00156                                         $this->fTable = $t;
00157                                 } else {
00158                                         unset($this->tables[$t]);
00159                                 }
00160                         }
00161                 }
00162         }
00163 
00171         function explodeCols($in)       {
00172                 $theArray = explode(':',$in);
00173                 $out = Array();
00174                 while(list(,$val)=each($theArray))      {
00175                         $val=trim($val);
00176                         $parts = explode('.',$val);
00177                         if ($parts[0] && $parts[1])     {
00178                                 $subparts = explode('-',$parts[1]);
00179                                 while(list(,$piece)=each($subparts))    {
00180                                         $piece=trim($piece);
00181                                         if ($piece)             $out[]=$parts[0].'.'.$piece;
00182                                 }
00183                         }
00184                 }
00185                 return $out;
00186         }
00187 
00196         function register_and_explode_search_string($sword)     {
00197                 $sword = trim($sword);
00198                 if ($sword)     {
00199                         $components = $this->split($sword);
00200                         $s_sword = '';   // the searchword is stored here during the loop
00201                         if (is_array($components))      {
00202                                 $i=0;
00203                                 $lastoper = '';
00204                                 reset($components);
00205                                 while (list($key,$val) = each ($components))    {
00206                                         $operator=$this->get_operator($val);
00207                                         if ($operator)  {
00208                                                 $lastoper = $operator;
00209                                         } elseif (strlen($val)>1) {             // A searchword MUST be at least two characters long!
00210                                                 $this->sword_array[$i]['sword'] = $val;
00211                                                 $this->sword_array[$i]['oper'] = ($lastoper) ? $lastoper : $this->default_operator;
00212                                                 $lastoper = '';
00213                                                 $i++;
00214                                         }
00215                                 }
00216                         }
00217                 }
00218         }
00219 
00229         function split($origSword, $specchars='+-', $delchars='+.,-')   {
00230                 $sword = $origSword;
00231                 $specs = '['.$this->quotemeta($specchars).']';
00232                 $delchars = '['.$this->quotemeta($delchars).']';
00233 
00234                         // As long as $sword is true (that means $sword MUST be reduced little by little until its empty inside the loop!)
00235                 while ($sword)  {
00236                         if (ereg('^"',$sword))  {               // There was a double-quote and we will then look for the ending quote.
00237                                 $sword = ereg_replace('^"','',$sword);          // Removes first double-quote
00238                                 ereg('^[^"]*',$sword,$reg);  // Removes everything till next double-quote
00239                                 $value[] = $reg[0];  // reg[0] is the value, should not be trimmed
00240                                 $sword = ereg_replace('^'.$this->quotemeta($reg[0]),'',$sword);
00241                                 $sword = trim(ereg_replace('^"','',$sword));            // Removes last double-quote
00242                         } elseif (ereg('^'.$specs,$sword,$reg)) {
00243                                 $value[] = $reg[0];
00244                                 $sword = trim(ereg_replace('^'.$specs,'',$sword));              // Removes = sign
00245                         } elseif (ereg('[\+\-]',$sword)) {      // Check if $sword contains + or -
00246                                         // + and - shall only be interpreted as $specchars when there's whitespace before it
00247                                         // otherwise it's included in the searchword (e.g. "know-how")
00248                                 $a_sword = explode(' ',$sword); // explode $sword to single words
00249                                 $word = array_shift($a_sword);  // get first word
00250                                 $word = ereg_replace($delchars.'$','',$word);           // Delete $delchars at end of string
00251                                 $value[] = $word;       // add searchword to values
00252                                 $sword = implode(' ',$a_sword); // re-build $sword
00253                         } else {
00254                                         // There are no double-quotes around the value. Looking for next (space) or special char.
00255                                 ereg('^[^ '.$this->quotemeta($specchars).']*',$sword,$reg);
00256                                 $word = ereg_replace($delchars.'$','',trim($reg[0]));           // Delete $delchars at end of string
00257                                 $value[] = $word;
00258                                 $sword = trim(ereg_replace('^'.$this->quotemeta($reg[0]),'',$sword));
00259                         }
00260                 }
00261 
00262                 return $value;
00263         }
00264 
00272         function quotemeta($str)        {
00273                 $str = str_replace('|','\|',quotemeta($str));
00274                 #$str = str_replace('-','\-',$str);             // Breaks "-" which should NOT have a slash before it inside of [ ] in a regex.
00275                 return $str;
00276         }
00277 
00288         function build_search_query($endClause) {
00289 
00290                 if (is_array($this->tables))    {
00291                         $tables = $this->tables;
00292                         $primary_table = '';
00293 
00294                                 // Primary key table is found.
00295                         foreach($tables as $key => $val)        {
00296                                 if ($tables[$key]['primary_key'])       {$primary_table = $key;}
00297                         }
00298 
00299                         if ($primary_table) {
00300 
00301                                         // Initialize query parts:
00302                                 $this->queryParts = array(
00303                                         'SELECT' => '',
00304                                         'FROM' => '',
00305                                         'WHERE' => '',
00306                                         'GROUPBY' => '',
00307                                         'ORDERBY' => '',
00308                                         'LIMIT' => '',
00309                                 );
00310 
00311                                         // Find tables / field names to select:
00312                                 $fieldArray = array();
00313                                 $tableArray = array();
00314                                 foreach($tables as $key => $val)        {
00315                                         $tableArray[] = $key;
00316                                         $resultfields = $tables[$key]['resultfields'];
00317                                         if (is_array($resultfields))    {
00318                                                 foreach($resultfields as $key2 => $val2)        {
00319                                                         $fieldArray[] = $key.'.'.$val2;
00320                                                 }
00321                                         }
00322                                 }
00323                                 $this->queryParts['SELECT'] = implode(',',$fieldArray);
00324                                 $this->queryParts['FROM'] = implode(',',$tableArray);
00325 
00326                                         // Set join WHERE parts:
00327                                 $whereArray = array();
00328 
00329                                 $primary_table_and_key = $primary_table.'.'.$tables[$primary_table]['primary_key'];
00330                                 $primKeys = Array();
00331                                 foreach($tables as $key => $val)        {
00332                                         $fkey = $tables[$key]['fkey'];
00333                                         if ($fkey)      {
00334                                                  $primKeys[] = $key.'.'.$fkey.'='.$primary_table_and_key;
00335                                         }
00336                                 }
00337                                 if (count($primKeys))   {
00338                                         $whereArray[] = '('.implode(' OR ',$primKeys).')';
00339                                 }
00340 
00341                                         // Additional where clause:
00342                                 if (trim($endClause))   {
00343                                         $whereArray[] = trim($endClause);
00344                                 }
00345 
00346                                         // Add search word where clause:
00347                                 $query_part = $this->build_search_query_for_searchwords();
00348                                 if (!$query_part)       {
00349                                         $query_part = '(0!=0)';
00350                                 }
00351                                 $whereArray[] = '('.$query_part.')';
00352 
00353                                         // Implode where clauses:
00354                                 $this->queryParts['WHERE'] = implode(' AND ',$whereArray);
00355 
00356                                         // Group by settings:
00357                                 if ($this->group_by)    {
00358                                         if ($this->group_by == 'PRIMARY_KEY')   {
00359                                                 $this->queryParts['GROUPBY'] = $primary_table_and_key;
00360                                         } else {
00361                                                 $this->queryParts['GROUPBY'] = $this->group_by;
00362                                         }
00363                                 }
00364                         }
00365                 }
00366         }
00367 
00374         function build_search_query_for_searchwords()   {
00375 
00376                 if (is_array($this->sword_array))       {
00377                         $main_query_part = array();
00378 
00379                         foreach($this->sword_array as $key => $val)     {
00380                                 $s_sword = $this->sword_array[$key]['sword'];
00381 
00382                                         // Get subQueryPart
00383                                 $sub_query_part = array();
00384 
00385                                 $this->listOfSearchFields='';
00386                                 foreach($this->tables as $key3 => $val3)        {
00387                                         $searchfields = $this->tables[$key3]['searchfields'];
00388                                         if (is_array($searchfields))    {
00389                                                 foreach($searchfields as $key2 => $val2)        {
00390                                                         $this->listOfSearchFields.= $key3.'.'.$val2.',';
00391                                                         $sub_query_part[] = $key3.'.'.$val2.' LIKE "%'.$GLOBALS['TYPO3_DB']->quoteStr($s_sword, $key3).'%"';
00392                                                 }
00393                                         }
00394                                 }
00395 
00396                                 if (count($sub_query_part))     {
00397                                         $main_query_part[] = $this->sword_array[$key]['oper'];
00398                                         $main_query_part[] = '('.implode(' OR ',$sub_query_part).')';
00399                                 }
00400                         }
00401 
00402                         if (count($main_query_part))    {
00403                                 unset($main_query_part[0]);     // Remove first part anyways.
00404                                 return implode(' ',$main_query_part);
00405                         }
00406                 }
00407         }
00408 
00416         function get_operator($operator)        {
00417                 $operator = trim($operator);
00418                 $op_array = $this->operator_translate_table;
00419                 reset ($op_array);
00420                 if ($this->operator_translate_table_caseinsensitive)    {
00421                         $operator = strtoupper($operator);
00422                 }
00423                 while (list($key,$val) = each($op_array))       {
00424                         $item = $op_array[$key][0];
00425                         if ($this->operator_translate_table_caseinsensitive)    {
00426                                 $item = strtoupper($item);
00427                         }
00428                         if ($operator==$item)   {
00429                                 return $op_array[$key][1];
00430                         }
00431                 }
00432         }
00433 
00439         function count_query() {
00440                 if (is_array($this->queryParts))        {
00441                         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($this->queryParts['SELECT'], $this->queryParts['FROM'], $this->queryParts['WHERE'], $this->queryParts['GROUPBY']);
00442                     $this->res_count = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
00443                         return TRUE;
00444                 }
00445         }
00446 
00452         function execute_query() {
00453                 if (is_array($this->queryParts))        {
00454                 $this->result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($this->queryParts);
00455                         return TRUE;
00456                 }
00457         }
00458 
00465         function get_searchwords()      {
00466                 $SWORD_PARAMS='';
00467                 if (is_array($this->sword_array))       {
00468                         foreach($this->sword_array as $key => $val)     {
00469                                 $SWORD_PARAMS.='&sword_list[]='.rawurlencode($val['sword']);
00470                         }
00471                 }
00472                 return $SWORD_PARAMS;
00473         }
00474 
00480         function get_searchwordsArray() {
00481                 if (is_array($this->sword_array))       {
00482                         foreach($this->sword_array as $key => $val)     {
00483                                 $swords[]=$val['sword'];
00484                         }
00485                 }
00486                 return $swords;
00487         }
00488 }
00489 
00490 
00491 
00492 
00493 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['tslib/class.tslib_search.php'])    {
00494         include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['tslib/class.tslib_search.php']);
00495 }
00496 
00497 ?>


Généré par TYPO3 Ameos avec  doxygen 1.4.6