aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/phpbb/search
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/phpbb/search')
-rw-r--r--phpBB/phpbb/search/base.php12
-rw-r--r--phpBB/phpbb/search/fulltext_mysql.php138
-rw-r--r--phpBB/phpbb/search/fulltext_native.php208
-rw-r--r--phpBB/phpbb/search/fulltext_postgres.php104
-rw-r--r--phpBB/phpbb/search/fulltext_sphinx.php76
-rw-r--r--phpBB/phpbb/search/sphinx/config.php4
-rw-r--r--phpBB/phpbb/search/sphinx/config_section.php6
7 files changed, 400 insertions, 148 deletions
diff --git a/phpBB/phpbb/search/base.php b/phpBB/phpbb/search/base.php
index d9313dddab..e7d0774b6c 100644
--- a/phpBB/phpbb/search/base.php
+++ b/phpBB/phpbb/search/base.php
@@ -133,7 +133,7 @@ class base
{
global $cache, $config, $db, $user;
- $length = min(sizeof($id_ary), $config['search_block_size']);
+ $length = min(count($id_ary), $config['search_block_size']);
// nothing to cache so exit
if (!$length)
@@ -148,7 +148,7 @@ class base
if (!($store = $cache->get('_search_results_' . $search_key)))
{
// add the current keywords to the recent searches in the cache which are listed on the search page
- if (!empty($keywords) || sizeof($author_ary))
+ if (!empty($keywords) || count($author_ary))
{
$sql = 'SELECT search_time
FROM ' . SEARCH_RESULTS_TABLE . '
@@ -201,7 +201,7 @@ class base
$store += $store_ids;
// if the cache is too big
- if (sizeof($store) - 2 > 20 * $config['search_block_size'])
+ if (count($store) - 2 > 20 * $config['search_block_size'])
{
// remove everything in front of two blocks in front of the current start index
for ($i = 0, $n = $id_range[0] - 2 * $config['search_block_size']; $i < $n; $i++)
@@ -243,7 +243,7 @@ class base
global $db, $cache, $config;
// clear all searches that searched for the specified words
- if (sizeof($words))
+ if (count($words))
{
$sql_where = '';
foreach ($words as $word)
@@ -264,7 +264,7 @@ class base
}
// clear all searches that searched for the specified authors
- if (is_array($authors) && sizeof($authors))
+ if (is_array($authors) && count($authors))
{
$sql_where = '';
foreach ($authors as $author)
@@ -286,7 +286,7 @@ class base
$sql = 'DELETE
FROM ' . SEARCH_RESULTS_TABLE . '
- WHERE search_time < ' . (time() - $config['search_store_results']);
+ WHERE search_time < ' . (time() - (int) $config['search_store_results']);
$db->sql_query($sql);
}
}
diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php
index 64a63e83e0..1105d0892f 100644
--- a/phpBB/phpbb/search/fulltext_mysql.php
+++ b/phpBB/phpbb/search/fulltext_mysql.php
@@ -188,7 +188,7 @@ class fulltext_mysql extends \phpbb\search\base
}
$sql = 'SHOW VARIABLES
- LIKE \'ft\_%\'';
+ LIKE \'%ft\_%\'';
$result = $this->db->sql_query($sql);
$mysql_info = array();
@@ -198,8 +198,16 @@ class fulltext_mysql extends \phpbb\search\base
}
$this->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']);
+ if ($engine === 'MyISAM')
+ {
+ $this->config->set('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']);
+ $this->config->set('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']);
+ }
+ else if ($engine === 'InnoDB')
+ {
+ $this->config->set('fulltext_mysql_max_word_len', $mysql_info['innodb_ft_max_token_size']);
+ $this->config->set('fulltext_mysql_min_word_len', $mysql_info['innodb_ft_min_token_size']);
+ }
return false;
}
@@ -232,9 +240,9 @@ class fulltext_mysql extends \phpbb\search\base
$this->split_words = $matches[1];
// We limit the number of allowed keywords to minimize load on the database
- if ($this->config['max_num_search_keywords'] && sizeof($this->split_words) > $this->config['max_num_search_keywords'])
+ if ($this->config['max_num_search_keywords'] && count($this->split_words) > $this->config['max_num_search_keywords'])
{
- trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], sizeof($this->split_words)));
+ trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], count($this->split_words)));
}
// to allow phrase search, we need to concatenate quoted words
@@ -361,7 +369,7 @@ class fulltext_mysql extends \phpbb\search\base
// remove too short or too long words
$text = array_values($text);
- for ($i = 0, $n = sizeof($text); $i < $n; $i++)
+ for ($i = 0, $n = count($text); $i < $n; $i++)
{
$text[$i] = trim($text[$i]);
if (utf8_strlen($text[$i]) < $this->config['fulltext_mysql_min_word_len'] || utf8_strlen($text[$i]) > $this->config['fulltext_mysql_max_word_len'])
@@ -563,12 +571,12 @@ class fulltext_mysql extends \phpbb\search\base
$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';
- if (sizeof($author_ary) && $author_name)
+ if (count($author_ary) && $author_name)
{
// first one matches post of registered users, second one guests and deleted users
$sql_author = ' AND (' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
}
- else if (sizeof($author_ary))
+ else if (count($author_ary))
{
$sql_author = ' AND ' . $this->db->sql_in_set('p.poster_id', $author_ary);
}
@@ -580,7 +588,7 @@ class fulltext_mysql extends \phpbb\search\base
$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 ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
+ $sql_where_options .= (count($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_where_options .= ' AND ' . $post_visibility;
$sql_where_options .= $sql_author;
$sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
@@ -591,6 +599,7 @@ class fulltext_mysql extends \phpbb\search\base
WHERE MATCH ($sql_match) AGAINST ('" . $this->db->sql_escape(htmlspecialchars_decode($this->search_query)) . "' IN BOOLEAN MODE)
$sql_where_options
ORDER BY $sql_sort";
+ $this->db->sql_return_on_error(true);
$result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start);
while ($row = $this->db->sql_fetchrow($result))
@@ -602,7 +611,7 @@ class fulltext_mysql extends \phpbb\search\base
$id_ary = array_unique($id_ary);
// if the total result count is not cached yet, retrieve it from the db
- if (!$result_count)
+ if (!$result_count && count($id_ary))
{
$sql_found_rows = 'SELECT FOUND_ROWS() as result_count';
$result = $this->db->sql_query($sql_found_rows);
@@ -659,7 +668,7 @@ class fulltext_mysql extends \phpbb\search\base
public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)
{
// No author? No posts
- if (!sizeof($author_ary))
+ if (!count($author_ary))
{
return 0;
}
@@ -736,7 +745,7 @@ class fulltext_mysql extends \phpbb\search\base
{
$sql_author = $this->db->sql_in_set('p.poster_id', $author_ary);
}
- $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
+ $sql_fora = (count($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
$sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : '';
@@ -889,7 +898,7 @@ class fulltext_mysql extends \phpbb\search\base
$id_ary = array_unique($id_ary);
}
- if (sizeof($id_ary))
+ if (count($id_ary))
{
$this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir);
$id_ary = array_slice($id_ary, 0, $per_page);
@@ -917,6 +926,34 @@ class fulltext_mysql extends \phpbb\search\base
$words = array_unique(array_merge($split_text, $split_title));
+ /**
+ * Event to modify method arguments and words before the MySQL search index is updated
+ *
+ * @event core.search_mysql_index_before
+ * @var string mode Contains the post mode: edit, post, reply, quote
+ * @var int post_id The id of the post which is modified/created
+ * @var string message New or updated post content
+ * @var string subject New or updated post subject
+ * @var int poster_id Post author's user id
+ * @var int forum_id The id of the forum in which the post is located
+ * @var array words List of words added to the index
+ * @var array split_text Array of words from the message
+ * @var array split_title Array of words from the title
+ * @since 3.2.3-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'post_id',
+ 'message',
+ 'subject',
+ 'poster_id',
+ 'forum_id',
+ 'words',
+ 'split_text',
+ 'split_title',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_index_before', compact($vars)));
+
unset($split_text);
unset($split_title);
@@ -942,7 +979,7 @@ class fulltext_mysql extends \phpbb\search\base
// destroy too old cached search results
$this->destroy_cache(array());
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
@@ -996,12 +1033,37 @@ class fulltext_mysql extends \phpbb\search\base
$alter_list[] = $alter_entry;
}
- if (sizeof($alter_list))
+ $sql_queries = [];
+
+ foreach ($alter_list as $alter)
{
- foreach ($alter_list as $alter)
- {
- $this->db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter));
- }
+ $sql_queries[] = 'ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter);
+ }
+
+ if (!isset($this->stats['post_text']))
+ {
+ $sql_queries[] = 'ALTER TABLE ' . POSTS_TABLE . ' ADD FULLTEXT post_text (post_text)';
+ }
+
+ $stats = $this->stats;
+
+ /**
+ * Event to modify SQL queries before the MySQL search index is created
+ *
+ * @event core.search_mysql_create_index_before
+ * @var array sql_queries Array with queries for creating the search index
+ * @var array stats Array with statistics of the current index (read only)
+ * @since 3.2.3-RC1
+ */
+ $vars = array(
+ 'sql_queries',
+ 'stats',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_create_index_before', compact($vars)));
+
+ foreach ($sql_queries as $sql_query)
+ {
+ $this->db->sql_query($sql_query);
}
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
@@ -1039,9 +1101,37 @@ class fulltext_mysql extends \phpbb\search\base
$alter[] = 'DROP INDEX post_content';
}
- if (sizeof($alter))
+ if (isset($this->stats['post_text']))
{
- $this->db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter));
+ $alter[] = 'DROP INDEX post_text';
+ }
+
+ $sql_queries = [];
+
+ if (count($alter))
+ {
+ $sql_queries[] = 'ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter);
+ }
+
+ $stats = $this->stats;
+
+ /**
+ * Event to modify SQL queries before the MySQL search index is deleted
+ *
+ * @event core.search_mysql_delete_index_before
+ * @var array sql_queries Array with queries for deleting the search index
+ * @var array stats Array with statistics of the current index (read only)
+ * @since 3.2.3-RC1
+ */
+ $vars = array(
+ 'sql_queries',
+ 'stats',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_delete_index_before', compact($vars)));
+
+ foreach ($sql_queries as $sql_query)
+ {
+ $this->db->sql_query($sql_query);
}
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
@@ -1059,7 +1149,7 @@ class fulltext_mysql extends \phpbb\search\base
$this->get_stats();
}
- return isset($this->stats['post_subject']) && isset($this->stats['post_content']);
+ return isset($this->stats['post_subject']) && isset($this->stats['post_content']) && isset($this->stats['post_text']);
}
/**
@@ -1103,6 +1193,10 @@ class fulltext_mysql extends \phpbb\search\base
{
$this->stats['post_subject'] = $row;
}
+ else if ($row['Key_name'] == 'post_text')
+ {
+ $this->stats['post_text'] = $row;
+ }
else if ($row['Key_name'] == 'post_content')
{
$this->stats['post_content'] = $row;
diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php
index 63b0b24edf..c83de75eed 100644
--- a/phpBB/phpbb/search/fulltext_native.php
+++ b/phpBB/phpbb/search/fulltext_native.php
@@ -18,6 +18,13 @@ namespace phpbb\search;
*/
class fulltext_native extends \phpbb\search\base
{
+ const UTF8_HANGUL_FIRST = "\xEA\xB0\x80";
+ const UTF8_HANGUL_LAST = "\xED\x9E\xA3";
+ const UTF8_CJK_FIRST = "\xE4\xB8\x80";
+ const UTF8_CJK_LAST = "\xE9\xBE\xBB";
+ const UTF8_CJK_B_FIRST = "\xF0\xA0\x80\x80";
+ const UTF8_CJK_B_LAST = "\xF0\xAA\x9B\x96";
+
/**
* Associative array holding index stats
* @var array
@@ -99,7 +106,7 @@ class fulltext_native extends \phpbb\search\base
protected $user;
/**
- * Initialises the fulltext_native search backend with min/max word length and makes sure the UTF-8 normalizer is loaded
+ * Initialises the fulltext_native search backend with min/max word length
*
* @param boolean|string &$error is passed by reference and should either be set to false on success or an error message on failure
* @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object
@@ -113,15 +120,11 @@ class fulltext_native extends \phpbb\search\base
$this->phpbb_dispatcher = $phpbb_dispatcher;
$this->user = $user;
- $this->word_length = array('min' => $this->config['fulltext_native_min_chars'], 'max' => $this->config['fulltext_native_max_chars']);
+ $this->word_length = array('min' => (int) $this->config['fulltext_native_min_chars'], 'max' => (int) $this->config['fulltext_native_max_chars']);
/**
* Load the UTF tools
*/
- if (!class_exists('utf_normalizer'))
- {
- include($this->phpbb_root_path . 'includes/utf/utf_normalizer.' . $this->php_ext);
- }
if (!function_exists('utf8_decode_ncr'))
{
include($this->phpbb_root_path . 'includes/utf/utf_tools.' . $this->php_ext);
@@ -187,7 +190,7 @@ class fulltext_native extends \phpbb\search\base
*/
public function split_keywords($keywords, $terms)
{
- $tokens = '+-|()*';
+ $tokens = '+-|()* ';
$keywords = trim($this->cleanup($keywords, $tokens));
@@ -221,12 +224,10 @@ class fulltext_native extends \phpbb\search\base
$keywords[$i] = '|';
break;
case '*':
- if ($i === 0 || ($keywords[$i - 1] !== '*' && strcspn($keywords[$i - 1], $tokens) === 0))
+ // $i can never be 0 here since $open_bracket is initialised to false
+ if (strpos($tokens, $keywords[$i - 1]) !== false && ($i + 1 === $n || strpos($tokens, $keywords[$i + 1]) !== false))
{
- if ($i === $n - 1 || ($keywords[$i + 1] !== '*' && strcspn($keywords[$i + 1], $tokens) === 0))
- {
- $keywords = substr($keywords, 0, $i) . substr($keywords, $i + 1);
- }
+ $keywords[$i] = '|';
}
break;
}
@@ -261,7 +262,7 @@ class fulltext_native extends \phpbb\search\base
}
}
- if ($open_bracket)
+ if ($open_bracket !== false)
{
$keywords .= ')';
}
@@ -282,7 +283,7 @@ class fulltext_native extends \phpbb\search\base
);
$keywords = preg_replace($match, $replace, $keywords);
- $num_keywords = sizeof(explode(' ', $keywords));
+ $num_keywords = count(explode(' ', $keywords));
// We limit the number of allowed keywords to minimize load on the database
if ($this->config['max_num_search_keywords'] && $num_keywords > $this->config['max_num_search_keywords'])
@@ -298,12 +299,26 @@ class fulltext_native extends \phpbb\search\base
$words = array();
preg_match_all('#([^\\s+\\-|()]+)(?:$|[\\s+\\-|()])#u', $keywords, $words);
- if (sizeof($words[1]))
+ if (count($words[1]))
{
$keywords = '(' . implode('|', $words[1]) . ')';
}
}
+ // Remove non trailing wildcards from each word to prevent a full table scan (it's now using the database index)
+ $match = '#\*(?!$|\s)#';
+ $replace = '$1';
+ $keywords = preg_replace($match, $replace, $keywords);
+
+ // Only allow one wildcard in the search query to limit the database load
+ $match = '#\*#';
+ $replace = '$1';
+ $count_wildcards = substr_count($keywords, '*');
+
+ // Reverse the string to remove all wildcards except the first one
+ $keywords = strrev(preg_replace($match, $replace, strrev($keywords), $count_wildcards - 1));
+ unset($count_wildcards);
+
// set the search_query which is shown to the user
$this->search_query = $keywords;
@@ -313,7 +328,7 @@ class fulltext_native extends \phpbb\search\base
$common_ids = $words = array();
- if (sizeof($exact_words))
+ if (count($exact_words))
{
$sql = 'SELECT word_id, word_text, word_common
FROM ' . SEARCH_WORDLIST_TABLE . '
@@ -349,9 +364,6 @@ class fulltext_native extends \phpbb\search\base
$this->must_not_contain_ids = array();
$this->must_exclude_one_ids = array();
- $mode = '';
- $ignore_no_id = true;
-
foreach ($query as $word)
{
if (empty($word))
@@ -409,8 +421,16 @@ class fulltext_native extends \phpbb\search\base
{
if (strpos($word_part, '*') !== false)
{
- $id_words[] = '\'' . $this->db->sql_escape(str_replace('*', '%', $word_part)) . '\'';
- $non_common_words[] = $word_part;
+ $len = utf8_strlen(str_replace('*', '', $word_part));
+ if ($len >= $this->word_length['min'] && $len <= $this->word_length['max'])
+ {
+ $id_words[] = '\'' . $this->db->sql_escape(str_replace('*', '%', $word_part)) . '\'';
+ $non_common_words[] = $word_part;
+ }
+ else
+ {
+ $this->common_words[] = $word_part;
+ }
}
else if (isset($words[$word_part]))
{
@@ -426,10 +446,10 @@ class fulltext_native extends \phpbb\search\base
}
}
}
- if (sizeof($id_words))
+ if (count($id_words))
{
sort($id_words);
- if (sizeof($id_words) > 1)
+ if (count($id_words) > 1)
{
$this->{$mode . '_ids'}[] = $id_words;
}
@@ -440,7 +460,7 @@ class fulltext_native extends \phpbb\search\base
}
}
// throw an error if we shall not ignore unexistant words
- else if (!$ignore_no_id && sizeof($non_common_words))
+ else if (!$ignore_no_id && count($non_common_words))
{
trigger_error(sprintf($this->user->lang['WORDS_IN_NO_POST'], implode($this->user->lang['COMMA_SEPARATOR'], $non_common_words)));
}
@@ -480,7 +500,7 @@ class fulltext_native extends \phpbb\search\base
}
// Return true if all words are not common words
- if (sizeof($exact_words) - sizeof($this->common_words) > 0)
+ if (count($exact_words) - count($this->common_words) > 0)
{
return true;
}
@@ -594,7 +614,6 @@ class fulltext_native extends \phpbb\search\base
$id_ary = array();
$sql_where = array();
- $group_by = false;
$m_num = 0;
$w_num = 0;
@@ -717,7 +736,7 @@ class fulltext_native extends \phpbb\search\base
}
}
- if (sizeof($this->must_not_contain_ids))
+ if (count($this->must_not_contain_ids))
{
$sql_array['LEFT_JOIN'][] = array(
'FROM' => array(SEARCH_WORDMATCH_TABLE => 'm' . $m_num),
@@ -827,7 +846,7 @@ class fulltext_native extends \phpbb\search\base
$sql_where[] = 'p.topic_id = ' . $topic_id;
}
- if (sizeof($author_ary))
+ if (count($author_ary))
{
if ($author_name)
{
@@ -841,7 +860,7 @@ class fulltext_native extends \phpbb\search\base
$sql_where[] = $sql_author;
}
- if (sizeof($ex_fid_ary))
+ if (count($ex_fid_ary))
{
$sql_where[] = $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true);
}
@@ -879,7 +898,6 @@ class fulltext_native extends \phpbb\search\base
break;
- case 'sqlite':
case 'sqlite3':
$sql_array_count['SELECT'] = ($type == 'posts') ? 'DISTINCT p.post_id' : 'DISTINCT p.topic_id';
$sql = 'SELECT COUNT(' . (($type == 'posts') ? 'post_id' : 'topic_id') . ') as total_results
@@ -1012,7 +1030,7 @@ class fulltext_native extends \phpbb\search\base
public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)
{
// No author? No posts
- if (!sizeof($author_ary))
+ if (!count($author_ary))
{
return 0;
}
@@ -1084,7 +1102,7 @@ class fulltext_native extends \phpbb\search\base
{
$sql_author = $this->db->sql_in_set('p.poster_id', $author_ary);
}
- $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
+ $sql_fora = (count($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
$sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : '';
@@ -1186,7 +1204,7 @@ class fulltext_native extends \phpbb\search\base
}
else
{
- if ($this->db->get_sql_layer() == 'sqlite' || $this->db->get_sql_layer() == 'sqlite3')
+ if ($this->db->get_sql_layer() == 'sqlite3')
{
$sql = 'SELECT COUNT(topic_id) as total_results
FROM (SELECT DISTINCT t.topic_id';
@@ -1203,7 +1221,7 @@ class fulltext_native extends \phpbb\search\base
$post_visibility
$sql_fora
AND t.topic_id = p.topic_id
- $sql_time" . (($this->db->get_sql_layer() == 'sqlite' || $this->db->get_sql_layer() == 'sqlite3') ? ')' : '');
+ $sql_time" . ($this->db->get_sql_layer() == 'sqlite3' ? ')' : '');
}
$result = $this->db->sql_query($sql);
@@ -1291,7 +1309,7 @@ class fulltext_native extends \phpbb\search\base
$this->db->sql_freeresult($result);
}
- if (sizeof($id_ary))
+ if (count($id_ary))
{
$this->save_ids($search_key, '', $author_ary, $total_results, $id_ary, $start, $sort_dir);
$id_ary = array_slice($id_ary, 0, $per_page);
@@ -1325,7 +1343,6 @@ class fulltext_native extends \phpbb\search\base
$match[] = '#\[\/?[a-z0-9\*\+\-]+(?:=.*?)?(?::[a-z])?(\:?[0-9a-z]{5,})\]#';
$min = $this->word_length['min'];
- $max = $this->word_length['max'];
$isset_min = $min - 1;
@@ -1361,9 +1378,9 @@ class fulltext_native extends \phpbb\search\base
* Note: this could be optimized. If the codepoint is lower than Hangul's range
* we know that it will also be lower than CJK ranges
*/
- if ((strncmp($word, UTF8_HANGUL_FIRST, 3) < 0 || strncmp($word, UTF8_HANGUL_LAST, 3) > 0)
- && (strncmp($word, UTF8_CJK_FIRST, 3) < 0 || strncmp($word, UTF8_CJK_LAST, 3) > 0)
- && (strncmp($word, UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, UTF8_CJK_B_LAST, 4) > 0))
+ if ((strncmp($word, self::UTF8_HANGUL_FIRST, 3) < 0 || strncmp($word, self::UTF8_HANGUL_LAST, 3) > 0)
+ && (strncmp($word, self::UTF8_CJK_FIRST, 3) < 0 || strncmp($word, self::UTF8_CJK_LAST, 3) > 0)
+ && (strncmp($word, self::UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, self::UTF8_CJK_B_LAST, 4) > 0))
{
$word = strtok(' ');
continue;
@@ -1436,6 +1453,38 @@ class fulltext_native extends \phpbb\search\base
$words['del']['post'] = array();
$words['del']['title'] = array();
}
+
+ /**
+ * Event to modify method arguments and words before the native search index is updated
+ *
+ * @event core.search_native_index_before
+ * @var string mode Contains the post mode: edit, post, reply, quote
+ * @var int post_id The id of the post which is modified/created
+ * @var string message New or updated post content
+ * @var string subject New or updated post subject
+ * @var int poster_id Post author's user id
+ * @var int forum_id The id of the forum in which the post is located
+ * @var array words Grouped lists of words added to or remove from the index
+ * @var array split_text Array of words from the message
+ * @var array split_title Array of words from the title
+ * @var array cur_words Array of words currently in the index for comparing to new words
+ * when mode is edit. Empty for other modes.
+ * @since 3.2.3-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'post_id',
+ 'message',
+ 'subject',
+ 'poster_id',
+ 'forum_id',
+ 'words',
+ 'split_text',
+ 'split_title',
+ 'cur_words',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_native_index_before', compact($vars)));
+
unset($split_text);
unset($split_title);
@@ -1446,7 +1495,7 @@ class fulltext_native extends \phpbb\search\base
// individual arrays of added and removed words for text and title. What
// we need to do now is add the new words (if they don't already exist)
// and then add (or remove) matches between the words and this post
- if (sizeof($unique_add_words))
+ if (count($unique_add_words))
{
$sql = 'SELECT word_id, word_text
FROM ' . SEARCH_WORDLIST_TABLE . '
@@ -1462,7 +1511,7 @@ class fulltext_native extends \phpbb\search\base
$new_words = array_diff($unique_add_words, array_keys($word_ids));
$this->db->sql_transaction('begin');
- if (sizeof($new_words))
+ if (count($new_words))
{
$sql_ary = array();
@@ -1486,7 +1535,7 @@ class fulltext_native extends \phpbb\search\base
{
$title_match = ($word_in == 'title') ? 1 : 0;
- if (sizeof($word_ary))
+ if (count($word_ary))
{
$sql_in = array();
foreach ($word_ary as $word)
@@ -1515,7 +1564,7 @@ class fulltext_native extends \phpbb\search\base
{
$title_match = ($word_in == 'title') ? 1 : 0;
- if (sizeof($word_ary))
+ if (count($word_ary))
{
$sql = 'INSERT INTO ' . SEARCH_WORDMATCH_TABLE . ' (post_id, word_id, title_match)
SELECT ' . (int) $post_id . ', word_id, ' . (int) $title_match . '
@@ -1546,7 +1595,7 @@ class fulltext_native extends \phpbb\search\base
*/
public function index_remove($post_ids, $author_ids, $forum_ids)
{
- if (sizeof($post_ids))
+ if (count($post_ids))
{
$sql = 'SELECT w.word_id, w.word_text, m.title_match
FROM ' . SEARCH_WORDMATCH_TABLE . ' m, ' . SEARCH_WORDLIST_TABLE . ' w
@@ -1569,7 +1618,7 @@ class fulltext_native extends \phpbb\search\base
}
$this->db->sql_freeresult($result);
- if (sizeof($title_word_ids))
+ if (count($title_word_ids))
{
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
SET word_count = word_count - 1
@@ -1578,7 +1627,7 @@ class fulltext_native extends \phpbb\search\base
$this->db->sql_query($sql);
}
- if (sizeof($message_word_ids))
+ if (count($message_word_ids))
{
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
SET word_count = word_count - 1
@@ -1608,7 +1657,7 @@ class fulltext_native extends \phpbb\search\base
// carry on ... it's okay ... I know when I'm not wanted boo hoo
if (!$this->config['fulltext_native_load_upd'])
{
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
return;
}
@@ -1633,7 +1682,7 @@ class fulltext_native extends \phpbb\search\base
}
$this->db->sql_freeresult($result);
- if (sizeof($sql_in))
+ if (count($sql_in))
{
// Flag the words
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
@@ -1643,7 +1692,7 @@ class fulltext_native extends \phpbb\search\base
// by setting search_last_gc to the new time here we make sure that if a user reloads because the
// following query takes too long, he won't run into it again
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
// Delete the matches
$sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
@@ -1653,13 +1702,13 @@ class fulltext_native extends \phpbb\search\base
unset($sql_in);
}
- if (sizeof($destroy_cache_words))
+ if (count($destroy_cache_words))
{
// destroy cached search results containing any of the words that are now common or were removed
$this->destroy_cache(array_unique($destroy_cache_words));
}
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
@@ -1667,21 +1716,43 @@ class fulltext_native extends \phpbb\search\base
*/
public function delete_index($acp_module, $u_action)
{
+ $sql_queries = [];
+
switch ($this->db->get_sql_layer())
{
- case 'sqlite':
case 'sqlite3':
- $this->db->sql_query('DELETE FROM ' . SEARCH_WORDLIST_TABLE);
- $this->db->sql_query('DELETE FROM ' . SEARCH_WORDMATCH_TABLE);
- $this->db->sql_query('DELETE FROM ' . SEARCH_RESULTS_TABLE);
+ $sql_queries[] = 'DELETE FROM ' . SEARCH_WORDLIST_TABLE;
+ $sql_queries[] = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE;
+ $sql_queries[] = 'DELETE FROM ' . SEARCH_RESULTS_TABLE;
break;
default:
- $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDLIST_TABLE);
- $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDMATCH_TABLE);
- $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
+ $sql_queries[] = 'TRUNCATE TABLE ' . SEARCH_WORDLIST_TABLE;
+ $sql_queries[] = 'TRUNCATE TABLE ' . SEARCH_WORDMATCH_TABLE;
+ $sql_queries[] = 'TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE;
break;
}
+
+ $stats = $this->stats;
+
+ /**
+ * Event to modify SQL queries before the native search index is deleted
+ *
+ * @event core.search_native_delete_index_before
+ * @var array sql_queries Array with queries for deleting the search index
+ * @var array stats Array with statistics of the current index (read only)
+ * @since 3.2.3-RC1
+ */
+ $vars = array(
+ 'sql_queries',
+ 'stats',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_native_delete_index_before', compact($vars)));
+
+ foreach ($sql_queries as $sql_query)
+ {
+ $this->db->sql_query($sql_query);
+ }
}
/**
@@ -1689,7 +1760,7 @@ class fulltext_native extends \phpbb\search\base
*/
public function index_created()
{
- if (!sizeof($this->stats))
+ if (!count($this->stats))
{
$this->get_stats();
}
@@ -1702,7 +1773,7 @@ class fulltext_native extends \phpbb\search\base
*/
public function index_stats()
{
- if (!sizeof($this->stats))
+ if (!count($this->stats))
{
$this->get_stats();
}
@@ -1730,13 +1801,11 @@ class fulltext_native extends \phpbb\search\base
* @param string $allowed_chars String of special chars to allow
* @param string $encoding Text encoding
* @return string Cleaned up text, only alphanumeric chars are left
- *
- * @todo \normalizer::cleanup being able to be used?
*/
protected function cleanup($text, $allowed_chars = null, $encoding = 'utf-8')
{
static $conv = array(), $conv_loaded = array();
- $words = $allow = array();
+ $allow = array();
// Convert the text to UTF-8
$encoding = strtolower($encoding);
@@ -1758,12 +1827,9 @@ class fulltext_native extends \phpbb\search\base
$text = htmlspecialchars_decode(utf8_decode_ncr($text), ENT_QUOTES);
/**
- * Load the UTF-8 normalizer
- *
- * If we use it more widely, an instance of that class should be held in a
- * a global variable instead
+ * Normalize to NFC
*/
- \utf_normalizer::nfc($text);
+ $text = \Normalizer::normalize($text);
/**
* The first thing we do is:
@@ -1856,9 +1922,9 @@ class fulltext_native extends \phpbb\search\base
$utf_char = substr($text, $pos, $utf_len);
$pos += $utf_len;
- if (($utf_char >= UTF8_HANGUL_FIRST && $utf_char <= UTF8_HANGUL_LAST)
- || ($utf_char >= UTF8_CJK_FIRST && $utf_char <= UTF8_CJK_LAST)
- || ($utf_char >= UTF8_CJK_B_FIRST && $utf_char <= UTF8_CJK_B_LAST))
+ if (($utf_char >= self::UTF8_HANGUL_FIRST && $utf_char <= self::UTF8_HANGUL_LAST)
+ || ($utf_char >= self::UTF8_CJK_FIRST && $utf_char <= self::UTF8_CJK_LAST)
+ || ($utf_char >= self::UTF8_CJK_B_FIRST && $utf_char <= self::UTF8_CJK_B_LAST))
{
/**
* All characters within these ranges are valid
diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/fulltext_postgres.php
index 04441e6226..2f387e791e 100644
--- a/phpBB/phpbb/search/fulltext_postgres.php
+++ b/phpBB/phpbb/search/fulltext_postgres.php
@@ -294,7 +294,7 @@ class fulltext_postgres extends \phpbb\search\base
// remove too short or too long words
$text = array_values($text);
- for ($i = 0, $n = sizeof($text); $i < $n; $i++)
+ for ($i = 0, $n = count($text); $i < $n; $i++)
{
$text[$i] = trim($text[$i]);
if (utf8_strlen($text[$i]) < $this->config['fulltext_postgres_min_word_len'] || utf8_strlen($text[$i]) > $this->config['fulltext_postgres_max_word_len'])
@@ -498,17 +498,16 @@ class fulltext_postgres extends \phpbb\search\base
);
extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_keywords_main_query_before', compact($vars)));
- $sql_select = ($type == 'posts') ? 'p.post_id' : 'DISTINCT t.topic_id';
+ $sql_select = ($type == 'posts') ? 'p.post_id' : 'DISTINCT t.topic_id, ' . $sort_by_sql[$sort_key];
$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) . ')';
- if (sizeof($author_ary) && $author_name)
+ if (count($author_ary) && $author_name)
{
// first one matches post of registered users, second one guests and deleted users
$sql_author = '(' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
}
- else if (sizeof($author_ary))
+ else if (count($author_ary))
{
$sql_author = ' AND ' . $this->db->sql_in_set('p.poster_id', $author_ary);
}
@@ -520,13 +519,12 @@ class fulltext_postgres extends \phpbb\search\base
$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 ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
+ $sql_where_options .= (count($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_where_options .= ' AND ' . $post_visibility;
$sql_where_options .= $sql_author;
$sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_where_options .= $sql_match_where;
- $tmp_sql_match = array();
$sql_match = str_replace(',', " || ' ' ||", $sql_match);
$tmp_sql_match = "to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', " . $sql_match . ") @@ to_tsquery ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', '" . $this->db->sql_escape($this->tsearch_query) . "')";
@@ -611,7 +609,7 @@ class fulltext_postgres extends \phpbb\search\base
public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)
{
// No author? No posts
- if (!sizeof($author_ary))
+ if (!count($author_ary))
{
return 0;
}
@@ -688,7 +686,7 @@ class fulltext_postgres extends \phpbb\search\base
{
$sql_author = $this->db->sql_in_set('p.poster_id', $author_ary);
}
- $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
+ $sql_fora = (count($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
$sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : '';
@@ -838,7 +836,7 @@ class fulltext_postgres extends \phpbb\search\base
GROUP BY t.topic_id, $sort_by_sql[$sort_key]";
}
- $result = $this->db->sql_query($sql_count);
+ $this->db->sql_query($sql_count);
$result_count = (int) $this->db->sql_fetchfield('result_count');
if (!$result_count)
@@ -863,7 +861,7 @@ class fulltext_postgres extends \phpbb\search\base
$id_ary = array_unique($id_ary);
}
- if (sizeof($id_ary))
+ if (count($id_ary))
{
$this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir);
$id_ary = array_slice($id_ary, 0, $per_page);
@@ -891,6 +889,34 @@ class fulltext_postgres extends \phpbb\search\base
$words = array_unique(array_merge($split_text, $split_title));
+ /**
+ * Event to modify method arguments and words before the PostgreSQL search index is updated
+ *
+ * @event core.search_postgres_index_before
+ * @var string mode Contains the post mode: edit, post, reply, quote
+ * @var int post_id The id of the post which is modified/created
+ * @var string message New or updated post content
+ * @var string subject New or updated post subject
+ * @var int poster_id Post author's user id
+ * @var int forum_id The id of the forum in which the post is located
+ * @var array words Array of words added to the index
+ * @var array split_text Array of words from the message
+ * @var array split_title Array of words from the title
+ * @since 3.2.3-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'post_id',
+ 'message',
+ 'subject',
+ 'poster_id',
+ 'forum_id',
+ 'words',
+ 'split_text',
+ 'split_title',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_index_before', compact($vars)));
+
unset($split_text);
unset($split_title);
@@ -916,7 +942,7 @@ class fulltext_postgres extends \phpbb\search\base
// destroy too old cached search results
$this->destroy_cache(array());
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
@@ -937,14 +963,37 @@ class fulltext_postgres extends \phpbb\search\base
$this->get_stats();
}
+ $sql_queries = [];
+
if (!isset($this->stats['post_subject']))
{
- $this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_subject ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_subject))");
+ $sql_queries[] = "CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_subject ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_subject))";
}
if (!isset($this->stats['post_content']))
{
- $this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_content ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_text || ' ' || post_subject))");
+ $sql_queries[] = "CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_content ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_text || ' ' || post_subject))";
+ }
+
+ $stats = $this->stats;
+
+ /**
+ * Event to modify SQL queries before the Postgres search index is created
+ *
+ * @event core.search_postgres_create_index_before
+ * @var array sql_queries Array with queries for creating the search index
+ * @var array stats Array with statistics of the current index (read only)
+ * @since 3.2.3-RC1
+ */
+ $vars = array(
+ 'sql_queries',
+ 'stats',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_create_index_before', compact($vars)));
+
+ foreach ($sql_queries as $sql_query)
+ {
+ $this->db->sql_query($sql_query);
}
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
@@ -970,14 +1019,37 @@ class fulltext_postgres extends \phpbb\search\base
$this->get_stats();
}
+ $sql_queries = [];
+
if (isset($this->stats['post_subject']))
{
- $this->db->sql_query('DROP INDEX ' . $this->stats['post_subject']['relname']);
+ $sql_queries[] = 'DROP INDEX ' . $this->stats['post_subject']['relname'];
}
if (isset($this->stats['post_content']))
{
- $this->db->sql_query('DROP INDEX ' . $this->stats['post_content']['relname']);
+ $sql_queries[] = 'DROP INDEX ' . $this->stats['post_content']['relname'];
+ }
+
+ $stats = $this->stats;
+
+ /**
+ * Event to modify SQL queries before the Postgres search index is created
+ *
+ * @event core.search_postgres_delete_index_before
+ * @var array sql_queries Array with queries for deleting the search index
+ * @var array stats Array with statistics of the current index (read only)
+ * @since 3.2.3-RC1
+ */
+ $vars = array(
+ 'sql_queries',
+ 'stats',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_delete_index_before', compact($vars)));
+
+ foreach ($sql_queries as $sql_query)
+ {
+ $this->db->sql_query($sql_query);
}
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php
index 0dbc6e33df..227fbd3fd6 100644
--- a/phpBB/phpbb/search/fulltext_sphinx.php
+++ b/phpBB/phpbb/search/fulltext_sphinx.php
@@ -85,7 +85,7 @@ class fulltext_sphinx
/**
* Database Tools object
- * @var \phpbb\db\tools
+ * @var \phpbb\db\tools\tools_interface
*/
protected $db_tools;
@@ -143,12 +143,13 @@ class fulltext_sphinx
$this->db = $db;
$this->auth = $auth;
- // Initialize \phpbb\db\tools object
- $this->db_tools = new \phpbb\db\tools($this->db);
+ // Initialize \phpbb\db\tools\tools object
+ global $phpbb_container; // TODO inject into object
+ $this->db_tools = $phpbb_container->get('dbal.tools');
if (!$this->config['fulltext_sphinx_id'])
{
- set_config('fulltext_sphinx_id', unique_id());
+ $this->config->set('fulltext_sphinx_id', unique_id());
}
$this->id = $this->config['fulltext_sphinx_id'];
$this->indexes = 'index_phpbb_' . $this->id . '_delta;index_phpbb_' . $this->id . '_main';
@@ -219,7 +220,7 @@ class fulltext_sphinx
}
// Move delta to main index each hour
- set_config('search_gc', 3600);
+ $this->config->set('search_gc', 3600);
return false;
}
@@ -291,7 +292,6 @@ class fulltext_sphinx
AND p.post_id >= $start AND p.post_id <= $end'),
array('sql_query_post', ''),
array('sql_query_post_index', 'UPDATE ' . SPHINX_TABLE . ' SET max_doc_id = $maxid WHERE counter_id = 1'),
- array('sql_query_info', 'SELECT * FROM ' . POSTS_TABLE . ' WHERE post_id = $id'),
array('sql_attr_uint', 'forum_id'),
array('sql_attr_uint', 'topic_id'),
array('sql_attr_uint', 'poster_id'),
@@ -303,7 +303,7 @@ class fulltext_sphinx
array('sql_attr_string', 'post_subject'),
),
'source source_phpbb_' . $this->id . '_delta : source_phpbb_' . $this->id . '_main' => array(
- array('sql_query_pre', ''),
+ array('sql_query_pre', 'SET NAMES \'utf8\''),
array('sql_query_range', ''),
array('sql_range_step', ''),
array('sql_query', 'SELECT
@@ -323,6 +323,7 @@ class fulltext_sphinx
WHERE
p.topic_id = t.topic_id
AND p.post_id >= ( SELECT max_doc_id FROM ' . SPHINX_TABLE . ' WHERE counter_id=1 )'),
+ array('sql_query_post_index', ''),
),
'index index_phpbb_' . $this->id . '_main' => array(
array('path', $this->config['fulltext_sphinx_data_path'] . 'index_phpbb_' . $this->id . '_main'),
@@ -331,10 +332,10 @@ class fulltext_sphinx
array('morphology', 'none'),
array('stopwords', ''),
array('min_word_len', '2'),
- array('charset_type', 'utf-8'),
array('charset_table', 'U+FF10..U+FF19->0..9, 0..9, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z, A..Z->a..z, a..z, U+0149, U+017F, U+0138, U+00DF, U+00FF, U+00C0..U+00D6->U+00E0..U+00F6, U+00E0..U+00F6, U+00D8..U+00DE->U+00F8..U+00FE, U+00F8..U+00FE, U+0100->U+0101, U+0101, U+0102->U+0103, U+0103, U+0104->U+0105, U+0105, U+0106->U+0107, U+0107, U+0108->U+0109, U+0109, U+010A->U+010B, U+010B, U+010C->U+010D, U+010D, U+010E->U+010F, U+010F, U+0110->U+0111, U+0111, U+0112->U+0113, U+0113, U+0114->U+0115, U+0115, U+0116->U+0117, U+0117, U+0118->U+0119, U+0119, U+011A->U+011B, U+011B, U+011C->U+011D, U+011D, U+011E->U+011F, U+011F, U+0130->U+0131, U+0131, U+0132->U+0133, U+0133, U+0134->U+0135, U+0135, U+0136->U+0137, U+0137, U+0139->U+013A, U+013A, U+013B->U+013C, U+013C, U+013D->U+013E, U+013E, U+013F->U+0140, U+0140, U+0141->U+0142, U+0142, U+0143->U+0144, U+0144, U+0145->U+0146, U+0146, U+0147->U+0148, U+0148, U+014A->U+014B, U+014B, U+014C->U+014D, U+014D, U+014E->U+014F, U+014F, U+0150->U+0151, U+0151, U+0152->U+0153, U+0153, U+0154->U+0155, U+0155, U+0156->U+0157, U+0157, U+0158->U+0159, U+0159, U+015A->U+015B, U+015B, U+015C->U+015D, U+015D, U+015E->U+015F, U+015F, U+0160->U+0161, U+0161, U+0162->U+0163, U+0163, U+0164->U+0165, U+0165, U+0166->U+0167, U+0167, U+0168->U+0169, U+0169, U+016A->U+016B, U+016B, U+016C->U+016D, U+016D, U+016E->U+016F, U+016F, U+0170->U+0171, U+0171, U+0172->U+0173, U+0173, U+0174->U+0175, U+0175, U+0176->U+0177, U+0177, U+0178->U+00FF, U+00FF, U+0179->U+017A, U+017A, U+017B->U+017C, U+017C, U+017D->U+017E, U+017E, U+0410..U+042F->U+0430..U+044F, U+0430..U+044F, U+4E00..U+9FFF'),
array('min_prefix_len', '0'),
array('min_infix_len', '0'),
+ array('html_strip', '1'),
),
'index index_phpbb_' . $this->id . '_delta : index_phpbb_' . $this->id . '_main' => array(
array('path', $this->config['fulltext_sphinx_data_path'] . 'index_phpbb_' . $this->id . '_delta'),
@@ -344,14 +345,12 @@ class fulltext_sphinx
array('mem_limit', $this->config['fulltext_sphinx_indexer_mem_limit'] . 'M'),
),
'searchd' => array(
- array('compat_sphinxql_magics' , '0'),
array('listen' , ($this->config['fulltext_sphinx_host'] ? $this->config['fulltext_sphinx_host'] : 'localhost') . ':' . ($this->config['fulltext_sphinx_port'] ? $this->config['fulltext_sphinx_port'] : '9312')),
array('log', $this->config['fulltext_sphinx_data_path'] . 'log/searchd.log'),
array('query_log', $this->config['fulltext_sphinx_data_path'] . 'log/sphinx-query.log'),
array('read_timeout', '5'),
array('max_children', '30'),
array('pid_file', $this->config['fulltext_sphinx_data_path'] . 'searchd.pid'),
- array('max_matches', (string) SPHINX_MAX_MATCHES),
array('binlog_path', $this->config['fulltext_sphinx_data_path']),
),
);
@@ -403,7 +402,7 @@ class fulltext_sphinx
$variable = $section->get_variable_by_name($key);
if (!$variable)
{
- $variable = $section->create_variable($key, $value);
+ $section->create_variable($key, $value);
}
else
{
@@ -412,7 +411,7 @@ class fulltext_sphinx
}
else
{
- $variable = $section->create_variable($key, $value);
+ $section->create_variable($key, $value);
}
}
}
@@ -436,7 +435,6 @@ class fulltext_sphinx
$match = array('#\sand\s#i', '#\sor\s#i', '#\snot\s#i', '#\+#', '#-#', '#\|#', '#@#');
$replace = array(' & ', ' | ', ' - ', ' +', ' -', ' |', '');
- $replacements = 0;
$keywords = preg_replace($match, $replace, $keywords);
$this->sphinx->SetMatchMode(SPH_MATCH_EXTENDED);
}
@@ -479,16 +477,16 @@ class fulltext_sphinx
*/
public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)
{
+ global $user, $phpbb_log;
+
// No keywords? No posts.
- if (!strlen($this->search_query) && !sizeof($author_ary))
+ if (!strlen($this->search_query) && !count($author_ary))
{
return false;
}
$id_ary = array();
- $join_topic = ($type != 'posts');
-
// Sorting
if ($type == 'topics')
@@ -622,7 +620,7 @@ class fulltext_sphinx
break;
}
- if (sizeof($author_ary))
+ if (count($author_ary))
{
$this->sphinx->SetFilter('poster_id', $author_ary);
}
@@ -632,14 +630,14 @@ class fulltext_sphinx
// but at least it will also cause the same for normal users.
$this->sphinx->SetFilter('post_visibility', array(ITEM_APPROVED));
- if (sizeof($ex_fid_ary))
+ if (count($ex_fid_ary))
{
// All forums that a user is allowed to access
$fid_ary = array_unique(array_intersect(array_keys($this->auth->acl_getf('f_read', true)), array_keys($this->auth->acl_getf('f_search', true))));
// All forums that the user wants to and can search in
$search_forums = array_diff($fid_ary, $ex_fid_ary);
- if (sizeof($search_forums))
+ if (count($search_forums))
{
$this->sphinx->SetFilter('forum_id', $search_forums);
}
@@ -647,8 +645,8 @@ class fulltext_sphinx
$this->sphinx->SetFilter('deleted', array(0));
- $this->sphinx->SetLimits($start, (int) $per_page, SPHINX_MAX_MATCHES);
- $result = $this->sphinx->Query($search_query_prefix . str_replace('&quot;', '"', $this->search_query), $this->indexes);
+ $this->sphinx->SetLimits((int) $start, (int) $per_page, max(SPHINX_MAX_MATCHES, (int) $start + $per_page));
+ $result = $this->sphinx->Query($search_query_prefix . $this->sphinx->EscapeString(str_replace('&quot;', '"', $this->search_query)), $this->indexes);
// Could be connection to localhost:9312 failed (errno=111,
// msg=Connection refused) during rotate, retry if so
@@ -656,12 +654,12 @@ class fulltext_sphinx
while (!$result && (strpos($this->sphinx->GetLastError(), "errno=111,") !== false) && $retries--)
{
usleep(SPHINX_CONNECT_WAIT_TIME);
- $result = $this->sphinx->Query($search_query_prefix . str_replace('&quot;', '"', $this->search_query), $this->indexes);
+ $result = $this->sphinx->Query($search_query_prefix . $this->sphinx->EscapeString(str_replace('&quot;', '"', $this->search_query)), $this->indexes);
}
if ($this->sphinx->GetLastError())
{
- add_log('critical', 'LOG_SPHINX_ERROR', $this->sphinx->GetLastError());
+ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_SPHINX_ERROR', false, array($this->sphinx->GetLastError()));
if ($this->auth->acl_get('a_'))
{
trigger_error($this->user->lang('SPHINX_SEARCH_FAILED', $this->sphinx->GetLastError()));
@@ -678,8 +676,8 @@ class fulltext_sphinx
{
$start = floor(($result_count - 1) / $per_page) * $per_page;
- $this->sphinx->SetLimits((int) $start, (int) $per_page, SPHINX_MAX_MATCHES);
- $result = $this->sphinx->Query($search_query_prefix . str_replace('&quot;', '"', $this->search_query), $this->indexes);
+ $this->sphinx->SetLimits((int) $start, (int) $per_page, max(SPHINX_MAX_MATCHES, (int) $start + $per_page));
+ $result = $this->sphinx->Query($search_query_prefix . $this->sphinx->EscapeString(str_replace('&quot;', '"', $this->search_query)), $this->indexes);
// Could be connection to localhost:9312 failed (errno=111,
// msg=Connection refused) during rotate, retry if so
@@ -687,7 +685,7 @@ class fulltext_sphinx
while (!$result && (strpos($this->sphinx->GetLastError(), "errno=111,") !== false) && $retries--)
{
usleep(SPHINX_CONNECT_WAIT_TIME);
- $result = $this->sphinx->Query($search_query_prefix . str_replace('&quot;', '"', $this->search_query), $this->indexes);
+ $result = $this->sphinx->Query($search_query_prefix . $this->sphinx->EscapeString(str_replace('&quot;', '"', $this->search_query)), $this->indexes);
}
}
@@ -757,6 +755,28 @@ class fulltext_sphinx
*/
public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
{
+ /**
+ * Event to modify method arguments before the Sphinx search index is updated
+ *
+ * @event core.search_sphinx_index_before
+ * @var string mode Contains the post mode: edit, post, reply, quote
+ * @var int post_id The id of the post which is modified/created
+ * @var string message New or updated post content
+ * @var string subject New or updated post subject
+ * @var int poster_id Post author's user id
+ * @var int forum_id The id of the forum in which the post is located
+ * @since 3.2.3-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'post_id',
+ 'message',
+ 'subject',
+ 'poster_id',
+ 'forum_id',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_sphinx_index_before', compact($vars)));
+
if ($mode == 'edit')
{
$this->sphinx->UpdateAttributes($this->indexes, array('forum_id', 'poster_id'), array((int) $post_id => array((int) $forum_id, (int) $poster_id)));
@@ -789,7 +809,7 @@ class fulltext_sphinx
}
$this->db->sql_freeresult($result);
- if (sizeof($post_updates))
+ if (count($post_updates))
{
$this->sphinx->UpdateAttributes($this->indexes, array('topic_last_post_time'), $post_updates);
}
@@ -815,7 +835,7 @@ class fulltext_sphinx
*/
public function tidy($create = false)
{
- set_config('search_last_gc', time(), true);
+ $this->config->set('search_last_gc', time(), false);
}
/**
diff --git a/phpBB/phpbb/search/sphinx/config.php b/phpBB/phpbb/search/sphinx/config.php
index 675649b460..3205574b45 100644
--- a/phpBB/phpbb/search/sphinx/config.php
+++ b/phpBB/phpbb/search/sphinx/config.php
@@ -46,7 +46,7 @@ class config
*/
function get_section_by_name($name)
{
- for ($i = 0, $size = sizeof($this->sections); $i < $size; $i++)
+ for ($i = 0, $size = count($this->sections); $i < $size; $i++)
{
// Make sure this is really a section object and not a comment
if (($this->sections[$i] instanceof \phpbb\search\sphinx\config_section) && $this->sections[$i]->get_name() == $name)
@@ -67,7 +67,7 @@ class config
function add_section($name)
{
$this->sections[] = new \phpbb\search\sphinx\config_section($name, '');
- return $this->sections[sizeof($this->sections) - 1];
+ return $this->sections[count($this->sections) - 1];
}
/**
diff --git a/phpBB/phpbb/search/sphinx/config_section.php b/phpBB/phpbb/search/sphinx/config_section.php
index 14ab3a752c..2fc8b2da17 100644
--- a/phpBB/phpbb/search/sphinx/config_section.php
+++ b/phpBB/phpbb/search/sphinx/config_section.php
@@ -87,7 +87,7 @@ class config_section
*/
function get_variable_by_name($name)
{
- for ($i = 0, $size = sizeof($this->variables); $i < $size; $i++)
+ for ($i = 0, $size = count($this->variables); $i < $size; $i++)
{
// Make sure this is a variable object and not a comment
if (($this->variables[$i] instanceof \phpbb\search\sphinx\config_variable) && $this->variables[$i]->get_name() == $name)
@@ -106,7 +106,7 @@ class config_section
*/
function delete_variables_by_name($name)
{
- for ($i = 0, $size = sizeof($this->variables); $i < $size; $i++)
+ for ($i = 0, $size = count($this->variables); $i < $size; $i++)
{
// Make sure this is a variable object and not a comment
if (($this->variables[$i] instanceof \phpbb\search\sphinx\config_variable) && $this->variables[$i]->get_name() == $name)
@@ -129,7 +129,7 @@ class config_section
function create_variable($name, $value)
{
$this->variables[] = new \phpbb\search\sphinx\config_variable($name, $value, '');
- return $this->variables[sizeof($this->variables) - 1];
+ return $this->variables[count($this->variables) - 1];
}
/**