📄 fulltext_mysql.php
字号:
<?php/** ** @package search* @version $Id: fulltext_mysql.php,v 1.32 2006/11/27 19:32:18 acydburn Exp $* @copyright (c) 2005 phpBB Group * @license http://opensource.org/licenses/gpl-license.php GNU Public License **//***/if (!defined('IN_PHPBB')){ exit;}/*** @ignore*/include_once($phpbb_root_path . 'includes/search/search.' . $phpEx);/*** fulltext_mysql* Fulltext search for MySQL* @package search*/class fulltext_mysql extends search_backend{ var $stats = array(); var $word_length = array(); var $split_words = array(); var $search_query; var $common_words = array(); function fulltext_mysql(&$error) { global $config; $this->word_length = array('min' => $config['fulltext_mysql_min_word_len'], 'max' => $config['fulltext_mysql_max_word_len']); $error = false; } /** * Checks for correct MySQL version and stores min/max word length in the config */ function init() { global $db, $user; if (strpos($db->sql_layer, 'mysql') === false) { return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_VERSION']; } $result = $db->sql_query('SELECT VERSION() AS mysql_version'); $version = $db->sql_fetchfield('mysql_version'); $db->sql_freeresult($result); if (!preg_match('#^4|5|6#s', $version)) { return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_VERSION']; } $result = $db->sql_query('SHOW TABLE STATUS LIKE \'' . POSTS_TABLE . '\''); $info = $db->sql_fetchrow($result); $db->sql_freeresult($result); $engine = ''; if (isset($info['Engine'])) { $engine = $info['Engine']; } else if (isset($info['Type'])) { $engine = $info['Type']; } if ($engine != 'MyISAM') { return $user->lang['FULLTEXT_MYSQL_NOT_MYISAM']; } $sql = 'SHOW VARIABLES LIKE \'ft\_%\''; $result = $db->sql_query($sql); $mysql_info = array(); while ($row = $db->sql_fetchrow($result)) { $mysql_info[$row['Variable_name']] = $row['Value']; } $db->sql_freeresult($result); set_config('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']); set_config('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']); return false; } /** * Splits keywords entered by a user into an array of words stored in $this->split_words * Stores the tidied search query in $this->search_query * * @param string &$keywords Contains the keyword as entered by the user * @param string $terms is either 'all' or 'any' * @return bool false if no valid keywords were found and otherwise true */ function split_keywords(&$keywords, $terms) { global $config; $this->get_ignore_words(); $this->get_synonyms(); if ($terms == 'all') { $match = array('#\sand\s#iu', '#\sor\s#iu', '#\snot\s#iu', '#\+#', '#-#', '#\|#'); $replace = array(' +', ' |', ' -', ' +', ' -', ' |'); $keywords = preg_replace($match, $replace, $keywords); } $match = array(); // New lines, carriage returns $match[] = "#[\n\r]+#"; // NCRs like etc. $match[] = '#(&|&)[\#a-z0-9]+?;#i'; // Filter out as above $keywords = preg_replace($match, ' ', trim($keywords)); // Split words $split_keywords = preg_replace('#([^\w\'*])#', '$1$1', str_replace('\'\'', '\' \'', trim($keywords))); $matches = array(); preg_match_all('#(?:[^\w*]|^)([+\-|]?(?:[\w*]+\'?)*[\w*])(?:[^\w*]|$)#', $split_keywords, $matches); $this->split_words = $matches[1]; if (sizeof($this->ignore_words)) { $this->common_words = array_intersect($this->split_words, $this->ignore_words); $this->split_words = array_diff($this->split_words, $this->ignore_words); } if (sizeof($this->replace_synonym)) { $this->split_words = str_replace($this->replace_synonym, $this->match_synonym, $this->split_words); } foreach ($this->split_words as $i => $word) { $clean_word = preg_replace('#^[+\-|]#', '', $word); // check word length $clean_len = utf8_strlen(str_replace('*', '', $clean_word)); if (($clean_len < $config['fulltext_mysql_min_word_len']) || ($clean_len > $config['fulltext_mysql_max_word_len'])) { $this->common_words[] = $word; unset($this->split_words[$i]); } } $this->search_query = implode(' ', $this->split_words); if (sizeof($this->split_words)) { $this->split_words = array_values($this->split_words); sort($this->split_words); return true; } return false; } /** * Turns text into an array of words */ function split_message($text) { global $config; $this->get_ignore_words(); $this->get_synonyms(); // Split words $text = preg_replace('#([^\w\'*])#', '$1$1', str_replace('\'\'', '\' \'', trim($text))); $matches = array(); preg_match_all('#(?:[^\w*]|^)([+\-|]?(?:[\w*]+\'?)*[\w*])(?:[^\w*]|$)#', $text, $matches); $text = $matches[1]; if (sizeof($this->ignore_words)) { $text = array_diff($text, $this->ignore_words); } if (sizeof($this->replace_synonym)) { $text = str_replace($this->replace_synonym, $this->match_synonym, $text); } // remove too short or too long words $text = array_values($text); for ($i = 0, $n = sizeof($text); $i < $n; $i++) { $text[$i] = trim($text[$i]); if (utf8_strlen($text[$i]) < $config['fulltext_mysql_min_word_len'] || utf8_strlen($text[$i]) > $config['fulltext_mysql_max_word_len']) { unset($text[$i]); } } return array_values($text); } /** * Performs a search on keywords depending on display specific params. * * @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered * @param int $start indicates the first index of the page * @param int $per_page number of ids each page is supposed to contain * @return total number of results */ 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) { global $config, $db; // No keywords? No posts. if (!sizeof($this->split_words)) { return false; } // generate a search_key from all the options to identify the results $search_key = md5(implode('#', array( implode(',', $this->split_words), $type, $fields, $terms, $sort_days, $sort_key, $topic_id, implode(',', $ex_fid_ary), implode(',', $m_approve_fid_ary), implode(',', $author_ary) ))); // try reading the results from cache $result_count = 0; if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) { return $result_count; } $id_ary = array(); $join_topic = ($type == 'posts') ? false : true; // Build sql strings for sorting $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); $sql_sort_table = $sql_sort_join = ''; switch ($sql_sort[0]) { case 'u': $sql_sort_table = USERS_TABLE . ' u, '; $sql_sort_join = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster '; break; case 't': $join_topic = true; break; case 'f': $sql_sort_table = FORUMS_TABLE . ' f, '; $sql_sort_join = ' AND f.forum_id = p.forum_id '; break; } // Build some display specific sql strings switch ($fields) { case 'titleonly': $sql_match = 'p.post_subject'; $sql_match_where = ' AND p.post_id = t.topic_first_post_id'; $join_topic = true; break; case 'msgonly': $sql_match = 'p.post_text'; $sql_match_where = ''; break; case 'firstpost': $sql_match = 'p.post_subject, p.post_text'; $sql_match_where = ' AND p.post_id = t.topic_first_post_id'; $join_topic = true; break; default: $sql_match = 'p.post_subject, p.post_text'; $sql_match_where = ''; break; } if (!sizeof($m_approve_fid_ary)) { $m_approve_fid_sql = ' AND p.post_approved = 1'; } else if ($m_approve_fid_ary === array(-1)) { $m_approve_fid_sql = ''; } else { $m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; } $sql_select = (!$result_count) ? 'SQL_CALC_FOUND_ROWS ' : ''; $sql_select = ($type == 'posts') ? $sql_select . 'p.post_id' : 'DISTINCT ' . $sql_select . 't.topic_id'; $sql_from = ($join_topic) ? TOPICS_TABLE . ' t, ' : ''; $field = ($type == 'posts') ? 'post_id' : 'topic_id'; $sql_author = (sizeof($author_ary) == 1) ? ' = ' . $author_ary[0] : 'IN (' . implode(', ', $author_ary) . ')'; $sql_where_options = $sql_sort_join; $sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : ''; $sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : ''; $sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; $sql_where_options .= $m_approve_fid_sql; $sql_where_options .= (sizeof($author_ary)) ? ' AND p.poster_id ' . $sql_author : ''; $sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; $sql_where_options .= $sql_match_where; // split the words into words that have to be included or must not be included and optional words $words = $any_words = array(); if ($terms == 'all') { foreach ($this->split_words as $id => $word) { if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0)) { $words[] = $word; } else if (strpos($word, '|') === 0) { $any_words[] = substr($word, 1); } else { $words[] = '+' . $word; } } } else { foreach ($this->split_words as $id => $word) { if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0) || (strpos($word, '|') === 0)) { $words[] = substr($word, 1); } else { $words[] = $word; } } } // Get the ids for the current result block $any_words = (sizeof($any_words)) ? ' +(' . implode(' ', $any_words) . ')' : ''; $sql = "SELECT $sql_select FROM $sql_from$sql_sort_table" . POSTS_TABLE . " p WHERE MATCH ($sql_match) AGAINST ('" . $db->sql_escape(implode(' ', $words)) . $any_words . "' IN BOOLEAN MODE) $sql_where_options ORDER BY $sql_sort"; $result = $db->sql_query_limit($sql, $config['search_block_size'], $start); while ($row = $db->sql_fetchrow($result)) { $id_ary[] = $row[$field]; } $db->sql_freeresult($result); $id_ary = array_unique($id_ary); if (!sizeof($id_ary))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -