[ Index ]

PHP Cross Reference of phpBB 3.0 Beta 3

title

Body

[close]

/includes/search/ -> fulltext_mysql.php (source)

   1  <?php
   2  /** 
   3  *
   4  * @package search
   5  * @version $Id: fulltext_mysql.php,v 1.30 2006/10/14 14:56:44 acydburn Exp $
   6  * @copyright (c) 2005 phpBB Group 
   7  * @license http://opensource.org/licenses/gpl-license.php GNU Public License 
   8  *
   9  */
  10  
  11  /**
  12  */
  13  if (!defined('IN_PHPBB'))
  14  {
  15      exit;
  16  }
  17  
  18  /**
  19  * @ignore
  20  */
  21  include_once($phpbb_root_path . 'includes/search/search.' . $phpEx);
  22  
  23  /**
  24  * fulltext_mysql
  25  * Fulltext search for MySQL
  26  * @package search
  27  */
  28  class fulltext_mysql extends search_backend
  29  {
  30      var $stats = array();
  31      var $word_length = array();
  32      var $split_words = array();
  33      var $search_query;
  34      var $common_words = array();
  35  
  36  	function fulltext_mysql(&$error)
  37      {
  38          global $config;
  39  
  40          $this->word_length = array('min' => $config['fulltext_mysql_min_word_len'], 'max' => $config['fulltext_mysql_max_word_len']);
  41  
  42          $error = false;
  43      }
  44  
  45      /**
  46      * Checks for correct MySQL version and stores min/max word length in the config
  47      */
  48  	function init()
  49      {
  50          global $db, $user;
  51  
  52          if (strpos($db->sql_layer, 'mysql') === false)
  53          {
  54              return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_VERSION'];
  55          }
  56  
  57          $result = $db->sql_query('SELECT VERSION() AS mysql_version');
  58          $version = $db->sql_fetchfield('mysql_version');
  59          $db->sql_freeresult($result);
  60  
  61          if (!preg_match('#^4|5|6#s', $version))
  62          {
  63              return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_VERSION'];
  64          }
  65  
  66          $result = $db->sql_query('SHOW TABLE STATUS LIKE \'' . POSTS_TABLE . '\'');
  67          $info = $db->sql_fetchrow($result);
  68          $db->sql_freeresult($result);
  69  
  70          $engine = '';
  71          if (isset($info['Engine']))
  72          {
  73              $engine = $info['Engine'];
  74          }
  75          else if (isset($info['Type']))
  76          {
  77              $engine = $info['Type'];
  78          }
  79  
  80          if ($engine != 'MyISAM')
  81          {
  82              return $user->lang['FULLTEXT_MYSQL_NOT_MYISAM'];
  83          }
  84  
  85          $sql = 'SHOW VARIABLES
  86              LIKE \'ft\_%\'';
  87          $result = $db->sql_query($sql);
  88  
  89          $mysql_info = array();
  90          while ($row = $db->sql_fetchrow($result))
  91          {
  92              $mysql_info[$row['Variable_name']] = $row['Value'];
  93          }
  94          $db->sql_freeresult($result);
  95  
  96          set_config('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']);
  97          set_config('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']);
  98  
  99          return false;
 100      }
 101  
 102      /**
 103      * Splits keywords entered by a user into an array of words stored in $this->split_words
 104      * Stores the tidied search query in $this->search_query
 105      *
 106      * @param string $keywords Contains the keyword as entered by the user
 107      * @param string $terms is either 'all' or 'any'
 108      * @return false if no valid keywords were found and otherwise true
 109      */
 110  	function split_keywords(&$keywords, $terms)
 111      {
 112          global $config;
 113  
 114          $this->get_ignore_words();
 115          $this->get_synonyms();
 116  
 117          if ($terms == 'all')
 118          {
 119              $match        = array('#\sand\s#i', '#\sor\s#i', '#\snot\s#i', '#\+#', '#-#', '#\|#');
 120              $replace    = array(' +', ' |', ' -', ' +', ' -', ' |');
 121  
 122              $keywords = preg_replace($match, $replace, $keywords);
 123          }
 124  
 125          $match = array();
 126          // New lines, carriage returns
 127          $match[] = "#[\n\r]+#";
 128          // NCRs like &nbsp; etc.
 129          $match[] = '#(&amp;|&)[\#a-z0-9]+?;#i';
 130  
 131          // Filter out as above
 132          $keywords = preg_replace($match, ' ', trim($keywords));
 133  
 134          // Split words
 135          $split_keywords = preg_replace('#([^\w\'*])#', '$1$1', str_replace('\'\'', '\' \'', trim($keywords)));
 136          $matches = array();
 137          preg_match_all('#(?:[^\w*]|^)([+\-|]?(?:[\w*]+\'?)*[\w*])(?:[^\w*]|$)#', $split_keywords, $matches);
 138          $this->split_words = $matches[1];
 139  
 140          if (sizeof($this->ignore_words))
 141          {
 142              $this->common_words = array_intersect($this->split_words, $this->ignore_words);
 143              $this->split_words = array_diff($this->split_words, $this->ignore_words);
 144          }
 145  
 146          if (sizeof($this->replace_synonym))
 147          {
 148              $this->split_words = str_replace($this->replace_synonym, $this->match_synonym, $this->split_words);
 149          }
 150  
 151          foreach ($this->split_words as $i => $word)
 152          {
 153              $clean_word = preg_replace('#^[+\-|]#', '', $word);
 154  
 155              // check word length
 156              $clean_len = utf8_strlen(str_replace('*', '', $clean_word));
 157              if (($clean_len < $config['fulltext_mysql_min_word_len']) || ($clean_len > $config['fulltext_mysql_max_word_len']))
 158              {
 159                  $this->common_words[] = $word;
 160                  unset($this->split_words[$i]);
 161              }
 162          }
 163  
 164          $this->search_query = implode(' ', $this->split_words);
 165  
 166          if (sizeof($this->split_words))
 167          {
 168              $this->split_words = array_values($this->split_words);
 169              sort($this->split_words);
 170              return true;
 171          }
 172          return false;
 173      }
 174  
 175      /**
 176      * Turns text into an array of words
 177      */
 178  	function split_message($text)
 179      {
 180          global $config;
 181  
 182          $this->get_ignore_words();
 183          $this->get_synonyms();
 184  
 185          // Split words
 186          $text = preg_replace('#([^\w\'*])#', '$1$1', str_replace('\'\'', '\' \'', trim($text)));
 187          $matches = array();
 188          preg_match_all('#(?:[^\w*]|^)([+\-|]?(?:[\w*]+\'?)*[\w*])(?:[^\w*]|$)#', $text, $matches);
 189          $text = $matches[1];
 190  
 191          if (sizeof($this->ignore_words))
 192          {
 193              $text = array_diff($text, $this->ignore_words);
 194          }
 195  
 196          if (sizeof($this->replace_synonym))
 197          {
 198              $text = str_replace($this->replace_synonym, $this->match_synonym, $text);
 199          }
 200  
 201          // remove too short or too long words
 202          $text = array_values($text);
 203          for ($i = 0, $n = sizeof($text); $i < $n; $i++)
 204          {
 205              $text[$i] = trim($text[$i]);
 206              if (utf8_strlen($text[$i]) < $config['fulltext_mysql_min_word_len'] || utf8_strlen($text[$i]) > $config['fulltext_mysql_max_word_len'])
 207              {
 208                  unset($text[$i]);
 209              }
 210          }
 211  
 212          return array_values($text);
 213      }
 214  
 215      /**
 216      * Performs a search on keywords depending on display specific params.
 217      *
 218      * @param array $id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
 219      * @param int $start indicates the first index of the page
 220      * @param int $per_page number of ids each page is supposed to contain
 221      * @return total number of results
 222      */
 223  	function keyword_search($type, &$fields, &$terms, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page)
 224      {
 225          global $config, $db;
 226  
 227          // No keywords? No posts.
 228          if (!sizeof($this->split_words))
 229          {
 230              return false;
 231          }
 232  
 233          // generate a search_key from all the options to identify the results
 234          $search_key = md5(implode('#', array(
 235              implode(',', $this->split_words),
 236              $type,
 237              $fields,
 238              $terms,
 239              $sort_days,
 240              $sort_key,
 241              $topic_id,
 242              implode(',', $ex_fid_ary),
 243              implode(',', $m_approve_fid_ary),
 244              implode(',', $author_ary)
 245          )));
 246  
 247          // try reading the results from cache
 248          $result_count = 0;
 249          if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE)
 250          {
 251              return $result_count;
 252          }
 253  
 254          $id_ary = array();
 255  
 256          $join_topic = ($type == 'posts') ? false : true;
 257  
 258          // Build sql strings for sorting
 259          $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
 260          $sql_sort_table = $sql_sort_join = '';
 261  
 262          switch ($sql_sort[0])
 263          {
 264              case 'u':
 265                  $sql_sort_table    = USERS_TABLE . ' u, ';
 266                  $sql_sort_join    = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster ';
 267              break;
 268  
 269              case 't':
 270                  $join_topic = true;
 271              break;
 272  
 273              case 'f':
 274                  $sql_sort_table    = FORUMS_TABLE . ' f, ';
 275                  $sql_sort_join    = ' AND f.forum_id = p.forum_id ';
 276              break;
 277          }
 278  
 279          // Build some display specific sql strings
 280          switch ($fields)
 281          {
 282              case 'titleonly':
 283                  $sql_match = 'p.post_subject';
 284                  $sql_match_where = ' AND p.post_id = t.topic_first_post_id';
 285                  $join_topic = true;
 286              break;
 287  
 288              case 'msgonly':
 289                  $sql_match = 'p.post_text';
 290                  $sql_match_where = '';
 291              break;
 292  
 293              case 'firstpost':
 294                  $sql_match = 'p.post_subject, p.post_text';
 295                  $sql_match_where = ' AND p.post_id = t.topic_first_post_id';
 296                  $join_topic = true;
 297              break;
 298  
 299              default:
 300                  $sql_match = 'p.post_subject, p.post_text';
 301                  $sql_match_where = '';
 302              break;
 303          }
 304  
 305          if (!sizeof($m_approve_fid_ary))
 306          {
 307              $m_approve_fid_sql = ' AND p.post_approved = 1';
 308          }
 309          else if ($m_approve_fid_ary === array(-1))
 310          {
 311              $m_approve_fid_sql = '';
 312          }
 313          else
 314          {
 315              $m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
 316          }
 317  
 318          $sql_select            = (!$result_count) ? 'SQL_CALC_FOUND_ROWS ' : '';
 319          $sql_select            = ($type == 'posts') ? $sql_select . 'p.post_id' : 'DISTINCT ' . $sql_select . 't.topic_id';
 320          $sql_from            = ($join_topic) ? TOPICS_TABLE . ' t, ' : '';
 321          $field                = ($type == 'posts') ? 'post_id' : 'topic_id';
 322          $sql_author            = (sizeof($author_ary) == 1) ? ' = ' . $author_ary[0] : 'IN (' . implode(', ', $author_ary) . ')';
 323  
 324          $sql_where_options = $sql_sort_join;
 325          $sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : '';
 326          $sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : '';
 327          $sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
 328          $sql_where_options .= $m_approve_fid_sql;
 329          $sql_where_options .= (sizeof($author_ary)) ? ' AND p.poster_id ' . $sql_author : '';
 330          $sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
 331          $sql_where_options .= $sql_match_where;
 332  
 333          // split the words into words that have to be included or must not be included and optional words
 334          $words = $any_words = array();
 335          if ($terms == 'all')
 336          {
 337              foreach ($this->split_words as $id => $word)
 338              {
 339                  if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0))
 340                  {
 341                      $words[] = $word;
 342                  }
 343                  else if (strpos($word, '|') === 0)
 344                  {
 345                      $any_words[] = substr($word, 1);
 346                  }
 347                  else
 348                  {
 349                      $words[] = '+' . $word;
 350                  }
 351              }
 352          }
 353          else
 354          {
 355              foreach ($this->split_words as $id => $word)
 356              {
 357                  if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0) || (strpos($word, '|') === 0))
 358                  {
 359                      $words[] = substr($word, 1);
 360                  }
 361                  else
 362                  {
 363                      $words[] = $word;
 364                  }
 365              }
 366          }
 367  
 368          // Get the ids for the current result block
 369          $any_words = (sizeof($any_words)) ? ' +(' . implode(' ', $any_words) . ')' : '';
 370  
 371          $sql = "SELECT $sql_select
 372              FROM $sql_from$sql_sort_table" . POSTS_TABLE . " p
 373              WHERE MATCH ($sql_match) AGAINST ('" . $db->sql_escape(implode(' ', $words)) . $any_words . "' IN BOOLEAN MODE)
 374                  $sql_where_options
 375              ORDER BY $sql_sort";
 376          $result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
 377  
 378          while ($row = $db->sql_fetchrow($result))
 379          {
 380              $id_ary[] = $row[$field];
 381          }
 382          $db->sql_freeresult($result);
 383  
 384          $id_ary = array_unique($id_ary);
 385  
 386          if (!sizeof($id_ary))
 387          {
 388              return false;
 389          }
 390  
 391          // if the total result count is not cached yet, retrieve it from the db
 392          if (!$result_count)
 393          {
 394              $sql = 'SELECT FOUND_ROWS() as result_count';
 395              $result = $db->sql_query($sql);
 396              $result_count = (int) $db->sql_fetchfield('result_count');
 397              $db->sql_freeresult($result);
 398  
 399              if (!$result_count)
 400              {
 401                  return false;
 402              }
 403          }
 404  
 405          // store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
 406          $this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir);
 407          $id_ary = array_slice($id_ary, 0, (int) $per_page);
 408  
 409          return $result_count;
 410      }
 411  
 412      /**
 413      * Performs a search on an author's posts without caring about message contents. Depends on display specific params
 414      *
 415      * @param array $id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
 416      * @param int $start indicates the first index of the page
 417      * @param int $per_page number of ids each page is supposed to contain
 418      * @return total number of results
 419      */
 420  	function author_search($type, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page)
 421      {
 422          global $config, $db;
 423  
 424          // No author? No posts.
 425          if (!sizeof($author_ary))
 426          {
 427              return 0;
 428          }
 429  
 430          // generate a search_key from all the options to identify the results
 431          $search_key = md5(implode('#', array(
 432              '',
 433              $type,
 434              '',
 435              '',
 436              $sort_days,
 437              $sort_key,
 438              $topic_id,
 439              implode(',', $ex_fid_ary),
 440              implode(',', $m_approve_fid_ary),
 441              implode(',', $author_ary)
 442          )));
 443  
 444          // try reading the results from cache
 445          $result_count = 0;
 446          if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE)
 447          {
 448              return $result_count;
 449          }
 450  
 451          $id_ary = array();
 452  
 453          // Create some display specific sql strings
 454          $sql_author        = $db->sql_in_set('p.poster_id', $author_ary);
 455          $sql_fora        = (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
 456          $sql_topic_id    = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
 457          $sql_time        = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
 458  
 459          // Build sql strings for sorting
 460          $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
 461          $sql_sort_table = $sql_sort_join = '';
 462          switch ($sql_sort[0])
 463          {
 464              case 'u':
 465                  $sql_sort_table    = USERS_TABLE . ' u, ';
 466                  $sql_sort_join    = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster ';
 467              break;
 468  
 469              case 't':
 470                  $sql_sort_table    = ($type == 'posts') ? TOPICS_TABLE . ' t, ' : '';
 471                  $sql_sort_join    = ($type == 'posts') ? ' AND t.topic_id = p.topic_id ' : '';
 472              break;
 473  
 474              case 'f':
 475                  $sql_sort_table    = FORUMS_TABLE . ' f, ';
 476                  $sql_sort_join    = ' AND f.forum_id = p.forum_id ';
 477              break;
 478          }
 479  
 480          if (!sizeof($m_approve_fid_ary))
 481          {
 482              $m_approve_fid_sql = ' AND p.post_approved = 1';
 483          }
 484          else if ($m_approve_fid_ary == array(-1))
 485          {
 486              $m_approve_fid_sql = '';
 487          }
 488          else
 489          {
 490              $m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
 491          }
 492  
 493          // If the cache was completely empty count the results
 494          $calc_results = ($result_count) ? '' : 'SQL_CALC_FOUND_ROWS ';
 495  
 496          // Build the query for really selecting the post_ids
 497          if ($type == 'posts')
 498          {
 499              $sql = "SELECT {$calc_results}p.post_id
 500                  FROM " . $sql_sort_table . POSTS_TABLE . " p
 501                  WHERE $sql_author
 502                      $sql_topic_id
 503                      $m_approve_fid_sql
 504                      $sql_fora
 505                      $sql_sort_join
 506                      $sql_time
 507                  ORDER BY $sql_sort";
 508              $field = 'post_id';
 509          }
 510          else
 511          {
 512              $sql = "SELECT {$calc_results}t.topic_id
 513                  FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
 514                  WHERE $sql_author
 515                      $sql_topic_id
 516                      $m_approve_fid_sql
 517                      $sql_fora
 518                      AND t.topic_id = p.topic_id
 519                      $sql_sort_join
 520                      $sql_time
 521                  GROUP BY t.topic_id
 522                  ORDER BY $sql_sort";
 523              $field = 'topic_id';
 524          }
 525  
 526          // Only read one block of posts from the db and then cache it
 527          $result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
 528  
 529          while ($row = $db->sql_fetchrow($result))
 530          {
 531              $id_ary[] = $row[$field];
 532          }
 533          $db->sql_freeresult($result);
 534  
 535          // retrieve the total result count if needed
 536          if (!$result_count)
 537          {
 538              $sql = 'SELECT FOUND_ROWS() as result_count';
 539              $result = $db->sql_query($sql);
 540              $result_count = (int) $db->sql_fetchfield('result_count');
 541              $db->sql_freeresult($result);
 542  
 543              if (!$result_count)
 544              {
 545                  return false;
 546              }
 547          }
 548  
 549          if (sizeof($id_ary))
 550          {
 551              $this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir);
 552              $id_ary = array_slice($id_ary, 0, $per_page);
 553  
 554              return $result_count;
 555          }
 556          return false;
 557      }
 558  
 559      /**
 560      * Destroys cached search results, that contained one of the new words in a post so the results won't be outdated.
 561      *
 562      * @param string $mode contains the post mode: edit, post, reply, quote ...
 563      */
 564  	function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
 565      {
 566          global $db;
 567  
 568          // Split old and new post/subject to obtain array of words
 569          $split_text = $this->split_message($message);
 570          $split_title = ($subject) ? $this->split_message($subject) : array();
 571  
 572          $words = array();
 573          if ($mode == 'edit')
 574          {
 575              $old_text = array();
 576              $old_title = array();
 577  
 578              $sql = 'SELECT post_text, post_subject
 579                  FROM ' . POSTS_TABLE . "
 580                  WHERE post_id = $post_id";
 581              $result = $db->sql_query($sql);
 582  
 583              if ($row = $db->sql_fetchrow($result))
 584              {
 585                  $old_text = $this->split_message($row['post_text']);
 586                  $old_title = $this->split_message($row['post_subject']);
 587              }
 588              $db->sql_freeresult($result);
 589  
 590              $words = array_unique(array_merge(
 591                  array_diff($split_text, $old_text), 
 592                  array_diff($split_title, $old_title),
 593                  array_diff($old_text, $split_text),
 594                  array_diff($old_title, $split_title)
 595              ));
 596              unset($old_title);
 597              unset($old_text);
 598          }
 599          else
 600          {
 601              $words = array_unique(array_merge($split_text, $split_title));
 602          }
 603          unset($split_text);
 604          unset($split_title);
 605  
 606          // destroy cached search results containing any of the words removed or added
 607          $this->destroy_cache($words, array($poster_id));
 608  
 609          unset($words);
 610      }
 611  
 612      /**
 613      * Destroy cached results, that might be outdated after deleting a post
 614      */
 615  	function index_remove($post_ids, $author_ids, $forum_ids)
 616      {
 617          $this->destroy_cache(array(), $author_ids);
 618      }
 619  
 620      /**
 621      * Destroy old cache entries
 622      */
 623  	function tidy()
 624      {
 625          global $db, $config;
 626  
 627          // destroy too old cached search results
 628          $this->destroy_cache(array());
 629  
 630          set_config('search_last_gc', time(), true);
 631      }
 632  
 633      /**
 634      * Create fulltext index
 635      */
 636  	function create_index($acp_module, $u_action)
 637      {
 638          global $db;
 639  
 640          // Make sure we can actually use MySQL with fulltext indexes
 641          if ($error = $this->init())
 642          {
 643              return $error;
 644          }
 645  
 646          if (empty($this->stats))
 647          {
 648              $this->get_stats();
 649          }
 650  
 651          if (!isset($this->stats['post_subject']))
 652          {
 653              $db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ADD FULLTEXT (post_subject)');
 654          }
 655  
 656          if (!isset($this->stats['post_text']))
 657          {
 658              $db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ADD FULLTEXT (post_text)');
 659          }
 660  
 661          $db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
 662  
 663          return false;
 664      }
 665  
 666      /**
 667      * Drop fulltext index
 668      */
 669  	function delete_index($acp_module, $u_action)
 670      {
 671          global $db;
 672  
 673          // Make sure we can actually use MySQL with fulltext indexes
 674          if ($error = $this->init())
 675          {
 676              return $error;
 677          }
 678  
 679          if (empty($this->stats))
 680          {
 681              $this->get_stats();
 682          }
 683  
 684          if (isset($this->stats['post_subject']))
 685          {
 686              $db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' DROP INDEX post_subject');
 687          }
 688  
 689          if (isset($this->stats['post_text']))
 690          {
 691              $db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' DROP INDEX post_text');
 692          }
 693  
 694          $db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
 695  
 696          return false;
 697      }
 698  
 699      /**
 700      * Returns true if both FULLTEXT indexes exist
 701      */
 702  	function index_created()
 703      {
 704          if (empty($this->stats))
 705          {
 706              $this->get_stats();
 707          }
 708  
 709          return (isset($this->stats['post_text']) && isset($this->stats['post_subject'])) ? true : false;
 710      }
 711  
 712      /**
 713      * Returns an associative array containing information about the indexes
 714      */
 715  	function index_stats()
 716      {
 717          global $user;
 718  
 719          if (empty($this->stats))
 720          {
 721              $this->get_stats();
 722          }
 723  
 724          return array(
 725              $user->lang['FULLTEXT_MYSQL_TOTAL_POSTS']            => ($this->index_created()) ? $this->stats['total_posts'] : 0,
 726              $user->lang['FULLTEXT_MYSQL_TEXT_CARDINALITY']        => isset($this->stats['post_text']['Cardinality']) ? $this->stats['post_text']['Cardinality'] : 0,
 727              $user->lang['FULLTEXT_MYSQL_SUBJECT_CARDINALITY']    => isset($this->stats['post_subject']['Cardinality']) ? $this->stats['post_subject']['Cardinality'] : 0,
 728          );
 729      }
 730  
 731  	function get_stats()
 732      {
 733          global $db;
 734  
 735          if (strpos($db->sql_layer, 'mysql') === false)
 736          {
 737              $this->stats = array();
 738              return;
 739          }
 740  
 741          $sql = 'SHOW INDEX
 742              FROM ' . POSTS_TABLE;
 743          $result = $db->sql_query($sql);
 744  
 745          while ($row = $db->sql_fetchrow($result))
 746          {
 747              // deal with older MySQL versions which didn't use Index_type
 748              $index_type = (isset($row['Index_type'])) ? $row['Index_type'] : $row['Comment'];
 749  
 750              if ($index_type == 'FULLTEXT')
 751              {
 752                  if ($row['Column_name'] == 'post_text')
 753                  {
 754                      $this->stats['post_text'] = $row;
 755                  }
 756                  else if ($row['Column_name'] == 'post_subject')
 757                  {
 758                      $this->stats['post_subject'] = $row;
 759                  }
 760              }
 761          }
 762          $db->sql_freeresult($result);
 763  
 764          $sql = 'SELECT COUNT(post_id) as total_posts
 765              FROM ' . POSTS_TABLE;
 766          $result = $db->sql_query($sql);
 767          $this->stats['total_posts'] = (int) $db->sql_fetchfield('total_posts');
 768          $db->sql_freeresult($result);
 769      }
 770  }
 771  
 772  ?>


Generated: Wed Nov 22 00:35:05 2006 Cross-referenced by PHPXref 0.6