PDF rausgenommen
This commit is contained in:
292
msd2/phpBB3/phpbb/search/base.php
Normal file
292
msd2/phpBB3/phpbb/search/base.php
Normal file
@ -0,0 +1,292 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
define('SEARCH_RESULT_NOT_IN_CACHE', 0);
|
||||
define('SEARCH_RESULT_IN_CACHE', 1);
|
||||
define('SEARCH_RESULT_INCOMPLETE', 2);
|
||||
|
||||
/**
|
||||
* optional base class for search plugins providing simple caching based on ACM
|
||||
* and functions to retrieve ignore_words and synonyms
|
||||
*/
|
||||
class base
|
||||
{
|
||||
var $ignore_words = array();
|
||||
var $match_synonym = array();
|
||||
var $replace_synonym = array();
|
||||
|
||||
function search_backend(&$error)
|
||||
{
|
||||
// This class cannot be used as a search plugin
|
||||
$error = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves cached search results
|
||||
*
|
||||
* @param string $search_key an md5 string generated from all the passed search options to identify the results
|
||||
* @param int &$result_count will contain the number of all results for the search (not only for the current page)
|
||||
* @param array &$id_ary is filled with the ids belonging to the requested page that are stored in the cache
|
||||
* @param int &$start indicates the first index of the page
|
||||
* @param int $per_page number of ids each page is supposed to contain
|
||||
* @param string $sort_dir is either a or d representing ASC and DESC
|
||||
*
|
||||
* @return int SEARCH_RESULT_NOT_IN_CACHE or SEARCH_RESULT_IN_CACHE or SEARCH_RESULT_INCOMPLETE
|
||||
*/
|
||||
function obtain_ids($search_key, &$result_count, &$id_ary, &$start, $per_page, $sort_dir)
|
||||
{
|
||||
global $cache;
|
||||
|
||||
if (!($stored_ids = $cache->get('_search_results_' . $search_key)))
|
||||
{
|
||||
// no search results cached for this search_key
|
||||
return SEARCH_RESULT_NOT_IN_CACHE;
|
||||
}
|
||||
else
|
||||
{
|
||||
$result_count = $stored_ids[-1];
|
||||
$reverse_ids = ($stored_ids[-2] != $sort_dir) ? true : false;
|
||||
$complete = true;
|
||||
|
||||
// Change start parameter in case out of bounds
|
||||
if ($result_count)
|
||||
{
|
||||
if ($start < 0)
|
||||
{
|
||||
$start = 0;
|
||||
}
|
||||
else if ($start >= $result_count)
|
||||
{
|
||||
$start = floor(($result_count - 1) / $per_page) * $per_page;
|
||||
}
|
||||
}
|
||||
|
||||
// change the start to the actual end of the current request if the sort direction differs
|
||||
// from the dirction in the cache and reverse the ids later
|
||||
if ($reverse_ids)
|
||||
{
|
||||
$start = $result_count - $start - $per_page;
|
||||
|
||||
// the user requested a page past the last index
|
||||
if ($start < 0)
|
||||
{
|
||||
return SEARCH_RESULT_NOT_IN_CACHE;
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = $start, $n = $start + $per_page; ($i < $n) && ($i < $result_count); $i++)
|
||||
{
|
||||
if (!isset($stored_ids[$i]))
|
||||
{
|
||||
$complete = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$id_ary[] = $stored_ids[$i];
|
||||
}
|
||||
}
|
||||
unset($stored_ids);
|
||||
|
||||
if ($reverse_ids)
|
||||
{
|
||||
$id_ary = array_reverse($id_ary);
|
||||
}
|
||||
|
||||
if (!$complete)
|
||||
{
|
||||
return SEARCH_RESULT_INCOMPLETE;
|
||||
}
|
||||
return SEARCH_RESULT_IN_CACHE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches post/topic ids
|
||||
*
|
||||
* @param string $search_key an md5 string generated from all the passed search options to identify the results
|
||||
* @param string $keywords contains the keywords as entered by the user
|
||||
* @param array $author_ary an array of author ids, if the author should be ignored during the search the array is empty
|
||||
* @param int $result_count contains the number of all results for the search (not only for the current page)
|
||||
* @param array &$id_ary contains a list of post or topic ids that shall be cached, the first element
|
||||
* must have the absolute index $start in the result set.
|
||||
* @param int $start indicates the first index of the page
|
||||
* @param string $sort_dir is either a or d representing ASC and DESC
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function save_ids($search_key, $keywords, $author_ary, $result_count, &$id_ary, $start, $sort_dir)
|
||||
{
|
||||
global $cache, $config, $db, $user;
|
||||
|
||||
$length = min(count($id_ary), $config['search_block_size']);
|
||||
|
||||
// nothing to cache so exit
|
||||
if (!$length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$store_ids = array_slice($id_ary, 0, $length);
|
||||
|
||||
// create a new resultset if there is none for this search_key yet
|
||||
// or add the ids to the existing resultset
|
||||
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) || count($author_ary))
|
||||
{
|
||||
$sql = 'SELECT search_time
|
||||
FROM ' . SEARCH_RESULTS_TABLE . '
|
||||
WHERE search_key = \'' . $db->sql_escape($search_key) . '\'';
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
if (!$db->sql_fetchrow($result))
|
||||
{
|
||||
$sql_ary = array(
|
||||
'search_key' => $search_key,
|
||||
'search_time' => time(),
|
||||
'search_keywords' => $keywords,
|
||||
'search_authors' => ' ' . implode(' ', $author_ary) . ' '
|
||||
);
|
||||
|
||||
$sql = 'INSERT INTO ' . SEARCH_RESULTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
$sql = 'UPDATE ' . USERS_TABLE . '
|
||||
SET user_last_search = ' . time() . '
|
||||
WHERE user_id = ' . $user->data['user_id'];
|
||||
$db->sql_query($sql);
|
||||
|
||||
$store = array(-1 => $result_count, -2 => $sort_dir);
|
||||
$id_range = range($start, $start + $length - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we use one set of results for both sort directions so we have to calculate the indizes
|
||||
// for the reversed array and we also have to reverse the ids themselves
|
||||
if ($store[-2] != $sort_dir)
|
||||
{
|
||||
$store_ids = array_reverse($store_ids);
|
||||
$id_range = range($store[-1] - $start - $length, $store[-1] - $start - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$id_range = range($start, $start + $length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
$store_ids = array_combine($id_range, $store_ids);
|
||||
|
||||
// append the ids
|
||||
if (is_array($store_ids))
|
||||
{
|
||||
$store += $store_ids;
|
||||
|
||||
// if the cache is too big
|
||||
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++)
|
||||
{
|
||||
if (isset($store[$i]))
|
||||
{
|
||||
unset($store[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
// remove everything after two blocks after the current stop index
|
||||
end($id_range);
|
||||
for ($i = $store[-1] - 1, $n = current($id_range) + 2 * $config['search_block_size']; $i > $n; $i--)
|
||||
{
|
||||
if (isset($store[$i]))
|
||||
{
|
||||
unset($store[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$cache->put('_search_results_' . $search_key, $store, $config['search_store_results']);
|
||||
|
||||
$sql = 'UPDATE ' . SEARCH_RESULTS_TABLE . '
|
||||
SET search_time = ' . time() . '
|
||||
WHERE search_key = \'' . $db->sql_escape($search_key) . '\'';
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
|
||||
unset($store);
|
||||
unset($store_ids);
|
||||
unset($id_range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes old entries from the search results table and removes searches with keywords that contain a word in $words.
|
||||
*/
|
||||
function destroy_cache($words, $authors = false)
|
||||
{
|
||||
global $db, $cache, $config;
|
||||
|
||||
// clear all searches that searched for the specified words
|
||||
if (count($words))
|
||||
{
|
||||
$sql_where = '';
|
||||
foreach ($words as $word)
|
||||
{
|
||||
$sql_where .= " OR search_keywords " . $db->sql_like_expression($db->get_any_char() . $word . $db->get_any_char());
|
||||
}
|
||||
|
||||
$sql = 'SELECT search_key
|
||||
FROM ' . SEARCH_RESULTS_TABLE . "
|
||||
WHERE search_keywords LIKE '%*%' $sql_where";
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$cache->destroy('_search_results_' . $row['search_key']);
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
// clear all searches that searched for the specified authors
|
||||
if (is_array($authors) && count($authors))
|
||||
{
|
||||
$sql_where = '';
|
||||
foreach ($authors as $author)
|
||||
{
|
||||
$sql_where .= (($sql_where) ? ' OR ' : '') . 'search_authors ' . $db->sql_like_expression($db->get_any_char() . ' ' . (int) $author . ' ' . $db->get_any_char());
|
||||
}
|
||||
|
||||
$sql = 'SELECT search_key
|
||||
FROM ' . SEARCH_RESULTS_TABLE . "
|
||||
WHERE $sql_where";
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$cache->destroy('_search_results_' . $row['search_key']);
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
$sql = 'DELETE
|
||||
FROM ' . SEARCH_RESULTS_TABLE . '
|
||||
WHERE search_time < ' . (time() - (int) $config['search_store_results']);
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
}
|
1227
msd2/phpBB3/phpbb/search/fulltext_mysql.php
Normal file
1227
msd2/phpBB3/phpbb/search/fulltext_mysql.php
Normal file
File diff suppressed because it is too large
Load Diff
2042
msd2/phpBB3/phpbb/search/fulltext_native.php
Normal file
2042
msd2/phpBB3/phpbb/search/fulltext_native.php
Normal file
File diff suppressed because it is too large
Load Diff
1178
msd2/phpBB3/phpbb/search/fulltext_postgres.php
Normal file
1178
msd2/phpBB3/phpbb/search/fulltext_postgres.php
Normal file
File diff suppressed because it is too large
Load Diff
992
msd2/phpBB3/phpbb/search/fulltext_sphinx.php
Normal file
992
msd2/phpBB3/phpbb/search/fulltext_sphinx.php
Normal file
@ -0,0 +1,992 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search;
|
||||
|
||||
define('SPHINX_MAX_MATCHES', 20000);
|
||||
define('SPHINX_CONNECT_RETRIES', 3);
|
||||
define('SPHINX_CONNECT_WAIT_TIME', 300);
|
||||
|
||||
/**
|
||||
* Fulltext search based on the sphinx search deamon
|
||||
*/
|
||||
class fulltext_sphinx
|
||||
{
|
||||
/**
|
||||
* Associative array holding index stats
|
||||
* @var array
|
||||
*/
|
||||
protected $stats = array();
|
||||
|
||||
/**
|
||||
* Holds the words entered by user, obtained by splitting the entered query on whitespace
|
||||
* @var array
|
||||
*/
|
||||
protected $split_words = array();
|
||||
|
||||
/**
|
||||
* Holds unique sphinx id
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* Stores the names of both main and delta sphinx indexes
|
||||
* separated by a semicolon
|
||||
* @var string
|
||||
*/
|
||||
protected $indexes;
|
||||
|
||||
/**
|
||||
* Sphinx searchd client object
|
||||
* @var SphinxClient
|
||||
*/
|
||||
protected $sphinx;
|
||||
|
||||
/**
|
||||
* Relative path to board root
|
||||
* @var string
|
||||
*/
|
||||
protected $phpbb_root_path;
|
||||
|
||||
/**
|
||||
* PHP Extension
|
||||
* @var string
|
||||
*/
|
||||
protected $php_ext;
|
||||
|
||||
/**
|
||||
* Auth object
|
||||
* @var \phpbb\auth\auth
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Config object
|
||||
* @var \phpbb\config\config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Database connection
|
||||
* @var \phpbb\db\driver\driver_interface
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* Database Tools object
|
||||
* @var \phpbb\db\tools\tools_interface
|
||||
*/
|
||||
protected $db_tools;
|
||||
|
||||
/**
|
||||
* Stores the database type if supported by sphinx
|
||||
* @var string
|
||||
*/
|
||||
protected $dbtype;
|
||||
|
||||
/**
|
||||
* phpBB event dispatcher object
|
||||
* @var \phpbb\event\dispatcher_interface
|
||||
*/
|
||||
protected $phpbb_dispatcher;
|
||||
|
||||
/**
|
||||
* User object
|
||||
* @var \phpbb\user
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Stores the generated content of the sphinx config file
|
||||
* @var string
|
||||
*/
|
||||
protected $config_file_data = '';
|
||||
|
||||
/**
|
||||
* Contains tidied search query.
|
||||
* Operators are prefixed in search query and common words excluded
|
||||
* @var string
|
||||
*/
|
||||
protected $search_query;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Creates a new \phpbb\search\fulltext_postgres, which is used as a search backend
|
||||
*
|
||||
* @param string|bool $error Any error that occurs is passed on through this reference variable otherwise false
|
||||
* @param string $phpbb_root_path Relative path to phpBB root
|
||||
* @param string $phpEx PHP file extension
|
||||
* @param \phpbb\auth\auth $auth Auth object
|
||||
* @param \phpbb\config\config $config Config object
|
||||
* @param \phpbb\db\driver\driver_interface Database object
|
||||
* @param \phpbb\user $user User object
|
||||
* @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object
|
||||
*/
|
||||
public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher)
|
||||
{
|
||||
$this->phpbb_root_path = $phpbb_root_path;
|
||||
$this->php_ext = $phpEx;
|
||||
$this->config = $config;
|
||||
$this->phpbb_dispatcher = $phpbb_dispatcher;
|
||||
$this->user = $user;
|
||||
$this->db = $db;
|
||||
$this->auth = $auth;
|
||||
|
||||
// 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'])
|
||||
{
|
||||
$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';
|
||||
|
||||
if (!class_exists('SphinxClient'))
|
||||
{
|
||||
require($this->phpbb_root_path . 'includes/sphinxapi.' . $this->php_ext);
|
||||
}
|
||||
|
||||
// Initialize sphinx client
|
||||
$this->sphinx = new \SphinxClient();
|
||||
|
||||
$this->sphinx->SetServer(($this->config['fulltext_sphinx_host'] ? $this->config['fulltext_sphinx_host'] : 'localhost'), ($this->config['fulltext_sphinx_port'] ? (int) $this->config['fulltext_sphinx_port'] : 9312));
|
||||
|
||||
$error = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this search backend to be displayed to administrators
|
||||
*
|
||||
* @return string Name
|
||||
*/
|
||||
public function get_name()
|
||||
{
|
||||
return 'Sphinx Fulltext';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the search_query
|
||||
*
|
||||
* @return string search query
|
||||
*/
|
||||
public function get_search_query()
|
||||
{
|
||||
return $this->search_query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false as there is no word_len array
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
public function get_word_length()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty array as there are no common_words
|
||||
*
|
||||
* @return array common words that are ignored by search backend
|
||||
*/
|
||||
public function get_common_words()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks permissions and paths, if everything is correct it generates the config file
|
||||
*
|
||||
* @return string|bool Language key of the error/incompatiblity encountered, or false if successful
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->db->get_sql_layer() != 'mysql' && $this->db->get_sql_layer() != 'mysql4' && $this->db->get_sql_layer() != 'mysqli' && $this->db->get_sql_layer() != 'postgres')
|
||||
{
|
||||
return $this->user->lang['FULLTEXT_SPHINX_WRONG_DATABASE'];
|
||||
}
|
||||
|
||||
// Move delta to main index each hour
|
||||
$this->config->set('search_gc', 3600);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates content of sphinx.conf
|
||||
*
|
||||
* @return bool True if sphinx.conf content is correctly generated, false otherwise
|
||||
*/
|
||||
protected function config_generate()
|
||||
{
|
||||
// Check if Database is supported by Sphinx
|
||||
if ($this->db->get_sql_layer() =='mysql' || $this->db->get_sql_layer() == 'mysql4' || $this->db->get_sql_layer() == 'mysqli')
|
||||
{
|
||||
$this->dbtype = 'mysql';
|
||||
}
|
||||
else if ($this->db->get_sql_layer() == 'postgres')
|
||||
{
|
||||
$this->dbtype = 'pgsql';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->config_file_data = $this->user->lang('FULLTEXT_SPHINX_WRONG_DATABASE');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if directory paths have been filled
|
||||
if (!$this->config['fulltext_sphinx_data_path'])
|
||||
{
|
||||
$this->config_file_data = $this->user->lang('FULLTEXT_SPHINX_NO_CONFIG_DATA');
|
||||
return false;
|
||||
}
|
||||
|
||||
include($this->phpbb_root_path . 'config.' . $this->php_ext);
|
||||
|
||||
/* Now that we're sure everything was entered correctly,
|
||||
generate a config for the index. We use a config value
|
||||
fulltext_sphinx_id for this, as it should be unique. */
|
||||
$config_object = new \phpbb\search\sphinx\config($this->config_file_data);
|
||||
$config_data = array(
|
||||
'source source_phpbb_' . $this->id . '_main' => array(
|
||||
array('type', $this->dbtype . ' # mysql or pgsql'),
|
||||
// This config value sql_host needs to be changed incase sphinx and sql are on different servers
|
||||
array('sql_host', $dbhost . ' # SQL server host sphinx connects to'),
|
||||
array('sql_user', '[dbuser]'),
|
||||
array('sql_pass', '[dbpassword]'),
|
||||
array('sql_db', $dbname),
|
||||
array('sql_port', $dbport . ' # optional, default is 3306 for mysql and 5432 for pgsql'),
|
||||
array('sql_query_pre', 'SET NAMES \'utf8\''),
|
||||
array('sql_query_pre', 'UPDATE ' . SPHINX_TABLE . ' SET max_doc_id = (SELECT MAX(post_id) FROM ' . POSTS_TABLE . ') WHERE counter_id = 1'),
|
||||
array('sql_query_range', 'SELECT MIN(post_id), MAX(post_id) FROM ' . POSTS_TABLE . ''),
|
||||
array('sql_range_step', '5000'),
|
||||
array('sql_query', 'SELECT
|
||||
p.post_id AS id,
|
||||
p.forum_id,
|
||||
p.topic_id,
|
||||
p.poster_id,
|
||||
p.post_visibility,
|
||||
CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post,
|
||||
p.post_time,
|
||||
p.post_subject,
|
||||
p.post_subject as title,
|
||||
p.post_text as data,
|
||||
t.topic_last_post_time,
|
||||
0 as deleted
|
||||
FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t
|
||||
WHERE
|
||||
p.topic_id = t.topic_id
|
||||
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_attr_uint', 'forum_id'),
|
||||
array('sql_attr_uint', 'topic_id'),
|
||||
array('sql_attr_uint', 'poster_id'),
|
||||
array('sql_attr_uint', 'post_visibility'),
|
||||
array('sql_attr_bool', 'topic_first_post'),
|
||||
array('sql_attr_bool', 'deleted'),
|
||||
array('sql_attr_timestamp', 'post_time'),
|
||||
array('sql_attr_timestamp', 'topic_last_post_time'),
|
||||
array('sql_attr_string', 'post_subject'),
|
||||
),
|
||||
'source source_phpbb_' . $this->id . '_delta : source_phpbb_' . $this->id . '_main' => array(
|
||||
array('sql_query_pre', 'SET NAMES \'utf8\''),
|
||||
array('sql_query_range', ''),
|
||||
array('sql_range_step', ''),
|
||||
array('sql_query', 'SELECT
|
||||
p.post_id AS id,
|
||||
p.forum_id,
|
||||
p.topic_id,
|
||||
p.poster_id,
|
||||
p.post_visibility,
|
||||
CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post,
|
||||
p.post_time,
|
||||
p.post_subject,
|
||||
p.post_subject as title,
|
||||
p.post_text as data,
|
||||
t.topic_last_post_time,
|
||||
0 as deleted
|
||||
FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t
|
||||
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'),
|
||||
array('source', 'source_phpbb_' . $this->id . '_main'),
|
||||
array('docinfo', 'extern'),
|
||||
array('morphology', 'none'),
|
||||
array('stopwords', ''),
|
||||
array('min_word_len', '2'),
|
||||
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'),
|
||||
),
|
||||
'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'),
|
||||
array('source', 'source_phpbb_' . $this->id . '_delta'),
|
||||
),
|
||||
'indexer' => array(
|
||||
array('mem_limit', $this->config['fulltext_sphinx_indexer_mem_limit'] . 'M'),
|
||||
),
|
||||
'searchd' => array(
|
||||
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('binlog_path', $this->config['fulltext_sphinx_data_path']),
|
||||
),
|
||||
);
|
||||
|
||||
$non_unique = array('sql_query_pre' => true, 'sql_attr_uint' => true, 'sql_attr_timestamp' => true, 'sql_attr_str2ordinal' => true, 'sql_attr_bool' => true);
|
||||
$delete = array('sql_group_column' => true, 'sql_date_column' => true, 'sql_str2ordinal_column' => true);
|
||||
|
||||
/**
|
||||
* Allow adding/changing the Sphinx configuration data
|
||||
*
|
||||
* @event core.search_sphinx_modify_config_data
|
||||
* @var array config_data Array with the Sphinx configuration data
|
||||
* @var array non_unique Array with the Sphinx non-unique variables to delete
|
||||
* @var array delete Array with the Sphinx variables to delete
|
||||
* @since 3.1.7-RC1
|
||||
*/
|
||||
$vars = array(
|
||||
'config_data',
|
||||
'non_unique',
|
||||
'delete',
|
||||
);
|
||||
extract($this->phpbb_dispatcher->trigger_event('core.search_sphinx_modify_config_data', compact($vars)));
|
||||
|
||||
foreach ($config_data as $section_name => $section_data)
|
||||
{
|
||||
$section = $config_object->get_section_by_name($section_name);
|
||||
if (!$section)
|
||||
{
|
||||
$section = $config_object->add_section($section_name);
|
||||
}
|
||||
|
||||
foreach ($delete as $key => $void)
|
||||
{
|
||||
$section->delete_variables_by_name($key);
|
||||
}
|
||||
|
||||
foreach ($non_unique as $key => $void)
|
||||
{
|
||||
$section->delete_variables_by_name($key);
|
||||
}
|
||||
|
||||
foreach ($section_data as $entry)
|
||||
{
|
||||
$key = $entry[0];
|
||||
$value = $entry[1];
|
||||
|
||||
if (!isset($non_unique[$key]))
|
||||
{
|
||||
$variable = $section->get_variable_by_name($key);
|
||||
if (!$variable)
|
||||
{
|
||||
$section->create_variable($key, $value);
|
||||
}
|
||||
else
|
||||
{
|
||||
$variable->set_value($value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$section->create_variable($key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->config_file_data = $config_object->get_data();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 false if no valid keywords were found and otherwise true
|
||||
*/
|
||||
public function split_keywords(&$keywords, $terms)
|
||||
{
|
||||
if ($terms == 'all')
|
||||
{
|
||||
$match = array('#\sand\s#i', '#\sor\s#i', '#\snot\s#i', '#\+#', '#-#', '#\|#', '#@#');
|
||||
$replace = array(' & ', ' | ', ' - ', ' +', ' -', ' |', '');
|
||||
|
||||
$keywords = preg_replace($match, $replace, $keywords);
|
||||
$this->sphinx->SetMatchMode(SPH_MATCH_EXTENDED);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->sphinx->SetMatchMode(SPH_MATCH_ANY);
|
||||
}
|
||||
|
||||
// Keep quotes and new lines
|
||||
$keywords = str_replace(array('"', "\n"), array('"', ' '), trim($keywords));
|
||||
|
||||
if (strlen($keywords) > 0)
|
||||
{
|
||||
$this->search_query = str_replace('"', '"', $keywords);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a search on keywords depending on display specific params. You have to run split_keywords() first
|
||||
*
|
||||
* @param string $type contains either posts or topics depending on what should be searched for
|
||||
* @param string $fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched)
|
||||
* @param string $terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words)
|
||||
* @param array $sort_by_sql contains SQL code for the ORDER BY part of a query
|
||||
* @param string $sort_key is the key of $sort_by_sql for the selected sorting
|
||||
* @param string $sort_dir is either a or d representing ASC and DESC
|
||||
* @param string $sort_days specifies the maximum amount of days a post may be old
|
||||
* @param array $ex_fid_ary specifies an array of forum ids which should not be searched
|
||||
* @param string $post_visibility specifies which types of posts the user can view in which forums
|
||||
* @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
|
||||
* @param array $author_ary an array of author ids if the author should be ignored during the search the array is empty
|
||||
* @param string $author_name specifies the author match, when ANONYMOUS is also a search-match
|
||||
* @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 boolean|int total number of results
|
||||
*/
|
||||
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) && !count($author_ary))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$id_ary = array();
|
||||
|
||||
// Sorting
|
||||
|
||||
if ($type == 'topics')
|
||||
{
|
||||
switch ($sort_key)
|
||||
{
|
||||
case 'a':
|
||||
$this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'poster_id ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'));
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
$this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'forum_id ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'));
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
|
||||
case 's':
|
||||
$this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'post_subject ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'));
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
||||
default:
|
||||
$this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'topic_last_post_time ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ($sort_key)
|
||||
{
|
||||
case 'a':
|
||||
$this->sphinx->SetSortMode(($sort_dir == 'a') ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'poster_id');
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
$this->sphinx->SetSortMode(($sort_dir == 'a') ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'forum_id');
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
|
||||
case 's':
|
||||
$this->sphinx->SetSortMode(($sort_dir == 'a') ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'post_subject');
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
||||
default:
|
||||
$this->sphinx->SetSortMode(($sort_dir == 'a') ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'post_time');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Most narrow filters first
|
||||
if ($topic_id)
|
||||
{
|
||||
$this->sphinx->SetFilter('topic_id', array($topic_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow modifying the Sphinx search options
|
||||
*
|
||||
* @event core.search_sphinx_keywords_modify_options
|
||||
* @var string type Searching type ('posts', 'topics')
|
||||
* @var string fields Searching fields ('titleonly', 'msgonly', 'firstpost', 'all')
|
||||
* @var string terms Searching terms ('all', 'any')
|
||||
* @var int sort_days Time, in days, of the oldest possible post to list
|
||||
* @var string sort_key The sort type used from the possible sort types
|
||||
* @var int topic_id Limit the search to this topic_id only
|
||||
* @var array ex_fid_ary Which forums not to search on
|
||||
* @var string post_visibility Post visibility data
|
||||
* @var array author_ary Array of user_id containing the users to filter the results to
|
||||
* @var string author_name The username to search on
|
||||
* @var object sphinx The Sphinx searchd client object
|
||||
* @since 3.1.7-RC1
|
||||
*/
|
||||
$sphinx = $this->sphinx;
|
||||
$vars = array(
|
||||
'type',
|
||||
'fields',
|
||||
'terms',
|
||||
'sort_days',
|
||||
'sort_key',
|
||||
'topic_id',
|
||||
'ex_fid_ary',
|
||||
'post_visibility',
|
||||
'author_ary',
|
||||
'author_name',
|
||||
'sphinx',
|
||||
);
|
||||
extract($this->phpbb_dispatcher->trigger_event('core.search_sphinx_keywords_modify_options', compact($vars)));
|
||||
$this->sphinx = $sphinx;
|
||||
unset($sphinx);
|
||||
|
||||
$search_query_prefix = '';
|
||||
|
||||
switch ($fields)
|
||||
{
|
||||
case 'titleonly':
|
||||
// Only search the title
|
||||
if ($terms == 'all')
|
||||
{
|
||||
$search_query_prefix = '@title ';
|
||||
}
|
||||
// Weight for the title
|
||||
$this->sphinx->SetFieldWeights(array("title" => 5, "data" => 1));
|
||||
// 1 is first_post, 0 is not first post
|
||||
$this->sphinx->SetFilter('topic_first_post', array(1));
|
||||
break;
|
||||
|
||||
case 'msgonly':
|
||||
// Only search the body
|
||||
if ($terms == 'all')
|
||||
{
|
||||
$search_query_prefix = '@data ';
|
||||
}
|
||||
// Weight for the body
|
||||
$this->sphinx->SetFieldWeights(array("title" => 1, "data" => 5));
|
||||
break;
|
||||
|
||||
case 'firstpost':
|
||||
// More relative weight for the title, also search the body
|
||||
$this->sphinx->SetFieldWeights(array("title" => 5, "data" => 1));
|
||||
// 1 is first_post, 0 is not first post
|
||||
$this->sphinx->SetFilter('topic_first_post', array(1));
|
||||
break;
|
||||
|
||||
default:
|
||||
// More relative weight for the title, also search the body
|
||||
$this->sphinx->SetFieldWeights(array("title" => 5, "data" => 1));
|
||||
break;
|
||||
}
|
||||
|
||||
if (count($author_ary))
|
||||
{
|
||||
$this->sphinx->SetFilter('poster_id', $author_ary);
|
||||
}
|
||||
|
||||
// As this is not simply possible at the moment, we limit the result to approved posts.
|
||||
// This will make it impossible for moderators to search unapproved and softdeleted posts,
|
||||
// but at least it will also cause the same for normal users.
|
||||
$this->sphinx->SetFilter('post_visibility', array(ITEM_APPROVED));
|
||||
|
||||
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 (count($search_forums))
|
||||
{
|
||||
$this->sphinx->SetFilter('forum_id', $search_forums);
|
||||
}
|
||||
}
|
||||
|
||||
$this->sphinx->SetFilter('deleted', array(0));
|
||||
|
||||
$this->sphinx->SetLimits((int) $start, (int) $per_page, SPHINX_MAX_MATCHES);
|
||||
$result = $this->sphinx->Query($search_query_prefix . $this->sphinx->EscapeString(str_replace('"', '"', $this->search_query)), $this->indexes);
|
||||
|
||||
// Could be connection to localhost:9312 failed (errno=111,
|
||||
// msg=Connection refused) during rotate, retry if so
|
||||
$retries = SPHINX_CONNECT_RETRIES;
|
||||
while (!$result && (strpos($this->sphinx->GetLastError(), "errno=111,") !== false) && $retries--)
|
||||
{
|
||||
usleep(SPHINX_CONNECT_WAIT_TIME);
|
||||
$result = $this->sphinx->Query($search_query_prefix . $this->sphinx->EscapeString(str_replace('"', '"', $this->search_query)), $this->indexes);
|
||||
}
|
||||
|
||||
if ($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()));
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error($this->user->lang('SPHINX_SEARCH_FAILED_LOG'));
|
||||
}
|
||||
}
|
||||
|
||||
$result_count = $result['total_found'];
|
||||
|
||||
if ($result_count && $start >= $result_count)
|
||||
{
|
||||
$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 . $this->sphinx->EscapeString(str_replace('"', '"', $this->search_query)), $this->indexes);
|
||||
|
||||
// Could be connection to localhost:9312 failed (errno=111,
|
||||
// msg=Connection refused) during rotate, retry if so
|
||||
$retries = SPHINX_CONNECT_RETRIES;
|
||||
while (!$result && (strpos($this->sphinx->GetLastError(), "errno=111,") !== false) && $retries--)
|
||||
{
|
||||
usleep(SPHINX_CONNECT_WAIT_TIME);
|
||||
$result = $this->sphinx->Query($search_query_prefix . $this->sphinx->EscapeString(str_replace('"', '"', $this->search_query)), $this->indexes);
|
||||
}
|
||||
}
|
||||
|
||||
$id_ary = array();
|
||||
if (isset($result['matches']))
|
||||
{
|
||||
if ($type == 'posts')
|
||||
{
|
||||
$id_ary = array_keys($result['matches']);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($result['matches'] as $key => $value)
|
||||
{
|
||||
$id_ary[] = $value['attrs']['topic_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$id_ary = array_slice($id_ary, 0, (int) $per_page);
|
||||
|
||||
return $result_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a search on an author's posts without caring about message contents. Depends on display specific params
|
||||
*
|
||||
* @param string $type contains either posts or topics depending on what should be searched for
|
||||
* @param boolean $firstpost_only if true, only topic starting posts will be considered
|
||||
* @param array $sort_by_sql contains SQL code for the ORDER BY part of a query
|
||||
* @param string $sort_key is the key of $sort_by_sql for the selected sorting
|
||||
* @param string $sort_dir is either a or d representing ASC and DESC
|
||||
* @param string $sort_days specifies the maximum amount of days a post may be old
|
||||
* @param array $ex_fid_ary specifies an array of forum ids which should not be searched
|
||||
* @param string $post_visibility specifies which types of posts the user can view in which forums
|
||||
* @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
|
||||
* @param array $author_ary an array of author ids
|
||||
* @param string $author_name specifies the author match, when ANONYMOUS is also a search-match
|
||||
* @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 boolean|int total number of results
|
||||
*/
|
||||
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)
|
||||
{
|
||||
$this->search_query = '';
|
||||
|
||||
$this->sphinx->SetMatchMode(SPH_MATCH_FULLSCAN);
|
||||
$fields = ($firstpost_only) ? 'firstpost' : 'all';
|
||||
$terms = 'all';
|
||||
return $this->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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates wordlist and wordmatch tables when a message is posted or changed
|
||||
*
|
||||
* @param string $mode Contains the post mode: edit, post, reply, quote
|
||||
* @param int $post_id The id of the post which is modified/created
|
||||
* @param string &$message New or updated post content
|
||||
* @param string &$subject New or updated post subject
|
||||
* @param int $poster_id Post author's user id
|
||||
* @param int $forum_id The id of the forum in which the post is located
|
||||
*/
|
||||
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)));
|
||||
}
|
||||
else if ($mode != 'post' && $post_id)
|
||||
{
|
||||
// Update topic_last_post_time for full topic
|
||||
$sql_array = array(
|
||||
'SELECT' => 'p1.post_id',
|
||||
'FROM' => array(
|
||||
POSTS_TABLE => 'p1',
|
||||
),
|
||||
'LEFT_JOIN' => array(array(
|
||||
'FROM' => array(
|
||||
POSTS_TABLE => 'p2'
|
||||
),
|
||||
'ON' => 'p1.topic_id = p2.topic_id',
|
||||
)),
|
||||
'WHERE' => 'p2.post_id = ' . ((int) $post_id),
|
||||
);
|
||||
|
||||
$sql = $this->db->sql_build_query('SELECT', $sql_array);
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
$post_updates = array();
|
||||
$post_time = time();
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$post_updates[(int) $row['post_id']] = array($post_time);
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if (count($post_updates))
|
||||
{
|
||||
$this->sphinx->UpdateAttributes($this->indexes, array('topic_last_post_time'), $post_updates);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a post from the index after it was deleted
|
||||
*/
|
||||
public function index_remove($post_ids, $author_ids, $forum_ids)
|
||||
{
|
||||
$values = array();
|
||||
foreach ($post_ids as $post_id)
|
||||
{
|
||||
$values[$post_id] = array(1);
|
||||
}
|
||||
|
||||
$this->sphinx->UpdateAttributes($this->indexes, array('deleted'), $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Nothing needs to be destroyed
|
||||
*/
|
||||
public function tidy($create = false)
|
||||
{
|
||||
$this->config->set('search_last_gc', time(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create sphinx table
|
||||
*
|
||||
* @return string|bool error string is returned incase of errors otherwise false
|
||||
*/
|
||||
public function create_index($acp_module, $u_action)
|
||||
{
|
||||
if (!$this->index_created())
|
||||
{
|
||||
$table_data = array(
|
||||
'COLUMNS' => array(
|
||||
'counter_id' => array('UINT', 0),
|
||||
'max_doc_id' => array('UINT', 0),
|
||||
),
|
||||
'PRIMARY_KEY' => 'counter_id',
|
||||
);
|
||||
$this->db_tools->sql_create_table(SPHINX_TABLE, $table_data);
|
||||
|
||||
$sql = 'TRUNCATE TABLE ' . SPHINX_TABLE;
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
$data = array(
|
||||
'counter_id' => '1',
|
||||
'max_doc_id' => '0',
|
||||
);
|
||||
$sql = 'INSERT INTO ' . SPHINX_TABLE . ' ' . $this->db->sql_build_array('INSERT', $data);
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop sphinx table
|
||||
*
|
||||
* @return string|bool error string is returned incase of errors otherwise false
|
||||
*/
|
||||
public function delete_index($acp_module, $u_action)
|
||||
{
|
||||
if (!$this->index_created())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->db_tools->sql_table_drop(SPHINX_TABLE);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the sphinx table was created
|
||||
*
|
||||
* @return bool true if sphinx table was created
|
||||
*/
|
||||
public function index_created($allow_new_files = true)
|
||||
{
|
||||
$created = false;
|
||||
|
||||
if ($this->db_tools->sql_table_exists(SPHINX_TABLE))
|
||||
{
|
||||
$created = true;
|
||||
}
|
||||
|
||||
return $created;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an associative array containing information about the indexes
|
||||
*
|
||||
* @return string|bool Language string of error false otherwise
|
||||
*/
|
||||
public function index_stats()
|
||||
{
|
||||
if (empty($this->stats))
|
||||
{
|
||||
$this->get_stats();
|
||||
}
|
||||
|
||||
return array(
|
||||
$this->user->lang['FULLTEXT_SPHINX_MAIN_POSTS'] => ($this->index_created()) ? $this->stats['main_posts'] : 0,
|
||||
$this->user->lang['FULLTEXT_SPHINX_DELTA_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] - $this->stats['main_posts'] : 0,
|
||||
$this->user->lang['FULLTEXT_MYSQL_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects stats that can be displayed on the index maintenance page
|
||||
*/
|
||||
protected function get_stats()
|
||||
{
|
||||
if ($this->index_created())
|
||||
{
|
||||
$sql = 'SELECT COUNT(post_id) as total_posts
|
||||
FROM ' . POSTS_TABLE;
|
||||
$result = $this->db->sql_query($sql);
|
||||
$this->stats['total_posts'] = (int) $this->db->sql_fetchfield('total_posts');
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
$sql = 'SELECT COUNT(p.post_id) as main_posts
|
||||
FROM ' . POSTS_TABLE . ' p, ' . SPHINX_TABLE . ' m
|
||||
WHERE p.post_id <= m.max_doc_id
|
||||
AND m.counter_id = 1';
|
||||
$result = $this->db->sql_query($sql);
|
||||
$this->stats['main_posts'] = (int) $this->db->sql_fetchfield('main_posts');
|
||||
$this->db->sql_freeresult($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of options for the ACP to display
|
||||
*
|
||||
* @return associative array containing template and config variables
|
||||
*/
|
||||
public function acp()
|
||||
{
|
||||
$config_vars = array(
|
||||
'fulltext_sphinx_data_path' => 'string',
|
||||
'fulltext_sphinx_host' => 'string',
|
||||
'fulltext_sphinx_port' => 'string',
|
||||
'fulltext_sphinx_indexer_mem_limit' => 'int',
|
||||
);
|
||||
|
||||
$tpl = '
|
||||
<span class="error">' . $this->user->lang['FULLTEXT_SPHINX_CONFIGURE']. '</span>
|
||||
<dl>
|
||||
<dt><label for="fulltext_sphinx_data_path">' . $this->user->lang['FULLTEXT_SPHINX_DATA_PATH'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_DATA_PATH_EXPLAIN'] . '</span></dt>
|
||||
<dd><input id="fulltext_sphinx_data_path" type="text" size="40" maxlength="255" name="config[fulltext_sphinx_data_path]" value="' . $this->config['fulltext_sphinx_data_path'] . '" /></dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><label for="fulltext_sphinx_host">' . $this->user->lang['FULLTEXT_SPHINX_HOST'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_HOST_EXPLAIN'] . '</span></dt>
|
||||
<dd><input id="fulltext_sphinx_host" type="text" size="40" maxlength="255" name="config[fulltext_sphinx_host]" value="' . $this->config['fulltext_sphinx_host'] . '" /></dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><label for="fulltext_sphinx_port">' . $this->user->lang['FULLTEXT_SPHINX_PORT'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_PORT_EXPLAIN'] . '</span></dt>
|
||||
<dd><input id="fulltext_sphinx_port" type="number" min="0" max="9999999999" name="config[fulltext_sphinx_port]" value="' . $this->config['fulltext_sphinx_port'] . '" /></dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><label for="fulltext_sphinx_indexer_mem_limit">' . $this->user->lang['FULLTEXT_SPHINX_INDEXER_MEM_LIMIT'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_INDEXER_MEM_LIMIT_EXPLAIN'] . '</span></dt>
|
||||
<dd><input id="fulltext_sphinx_indexer_mem_limit" type="number" min="0" max="9999999999" name="config[fulltext_sphinx_indexer_mem_limit]" value="' . $this->config['fulltext_sphinx_indexer_mem_limit'] . '" /> ' . $this->user->lang['MIB'] . '</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><label for="fulltext_sphinx_config_file">' . $this->user->lang['FULLTEXT_SPHINX_CONFIG_FILE'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_CONFIG_FILE_EXPLAIN'] . '</span></dt>
|
||||
<dd>' . (($this->config_generate()) ? '<textarea readonly="readonly" rows="6" id="sphinx_config_data">' . htmlspecialchars($this->config_file_data) . '</textarea>' : $this->config_file_data) . '</dd>
|
||||
<dl>
|
||||
';
|
||||
|
||||
// These are fields required in the config table
|
||||
return array(
|
||||
'tpl' => $tpl,
|
||||
'config' => $config_vars
|
||||
);
|
||||
}
|
||||
}
|
10
msd2/phpBB3/phpbb/search/index.htm
Normal file
10
msd2/phpBB3/phpbb/search/index.htm
Normal file
@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
</body>
|
||||
</html>
|
284
msd2/phpBB3/phpbb/search/sphinx/config.php
Normal file
284
msd2/phpBB3/phpbb/search/sphinx/config.php
Normal file
@ -0,0 +1,284 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search\sphinx;
|
||||
|
||||
/**
|
||||
* An object representing the sphinx configuration
|
||||
* Can read it from file and write it back out after modification
|
||||
*/
|
||||
class config
|
||||
{
|
||||
private $sections = array();
|
||||
|
||||
/**
|
||||
* Constructor which optionally loads data from a variable
|
||||
*
|
||||
* @param string $config_data Variable containing the sphinx configuration data
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function __construct($config_data)
|
||||
{
|
||||
if ($config_data != '')
|
||||
{
|
||||
$this->read($config_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a section object by its name
|
||||
*
|
||||
* @param string $name The name of the section that shall be returned
|
||||
* @return \phpbb\search\sphinx\config_section The section object or null if none was found
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function get_section_by_name($name)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return $this->sections[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a new empty section to the end of the config
|
||||
*
|
||||
* @param string $name The name for the new section
|
||||
* @return \phpbb\search\sphinx\config_section The newly created section object
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function add_section($name)
|
||||
{
|
||||
$this->sections[] = new \phpbb\search\sphinx\config_section($name, '');
|
||||
return $this->sections[count($this->sections) - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the config file data
|
||||
*
|
||||
* @param string $config_data The config file data
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
function read($config_data)
|
||||
{
|
||||
$this->sections = array();
|
||||
|
||||
$section = null;
|
||||
$found_opening_bracket = false;
|
||||
$in_value = false;
|
||||
|
||||
foreach ($config_data as $i => $line)
|
||||
{
|
||||
// If the value of a variable continues to the next line because the line
|
||||
// break was escaped then we don't trim leading space but treat it as a part of the value
|
||||
if ($in_value)
|
||||
{
|
||||
$line = rtrim($line);
|
||||
}
|
||||
else
|
||||
{
|
||||
$line = trim($line);
|
||||
}
|
||||
|
||||
// If we're not inside a section look for one
|
||||
if (!$section)
|
||||
{
|
||||
// Add empty lines and comments as comment objects to the section list
|
||||
// that way they're not deleted when reassembling the file from the sections
|
||||
if (!$line || $line[0] == '#')
|
||||
{
|
||||
$this->sections[] = new \phpbb\search\sphinx\config_comment($config_file[$i]);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise we scan the line reading the section name until we find
|
||||
// an opening curly bracket or a comment
|
||||
$section_name = '';
|
||||
$section_name_comment = '';
|
||||
$found_opening_bracket = false;
|
||||
for ($j = 0, $length = strlen($line); $j < $length; $j++)
|
||||
{
|
||||
if ($line[$j] == '#')
|
||||
{
|
||||
$section_name_comment = substr($line, $j);
|
||||
break;
|
||||
}
|
||||
|
||||
if ($found_opening_bracket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($line[$j] == '{')
|
||||
{
|
||||
$found_opening_bracket = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$section_name .= $line[$j];
|
||||
}
|
||||
|
||||
// And then we create the new section object
|
||||
$section_name = trim($section_name);
|
||||
$section = new \phpbb\search\sphinx\config_section($section_name, $section_name_comment);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we're looking for variables inside a section
|
||||
$skip_first = false;
|
||||
|
||||
// If we're not in a value continuing over the line feed
|
||||
if (!$in_value)
|
||||
{
|
||||
// Then add empty lines and comments as comment objects to the variable list
|
||||
// of this section so they're not deleted on reassembly
|
||||
if (!$line || $line[0] == '#')
|
||||
{
|
||||
$section->add_variable(new \phpbb\search\sphinx\config_comment($config_file[$i]));
|
||||
continue;
|
||||
}
|
||||
|
||||
// As long as we haven't yet actually found an opening bracket for this section
|
||||
// we treat everything as comments so it's not deleted either
|
||||
if (!$found_opening_bracket)
|
||||
{
|
||||
if ($line[0] == '{')
|
||||
{
|
||||
$skip_first = true;
|
||||
$line = substr($line, 1);
|
||||
$found_opening_bracket = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$section->add_variable(new \phpbb\search\sphinx\config_comment($config_file[$i]));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we did not find a comment in this line or still add to the previous
|
||||
// line's value ...
|
||||
if ($line || $in_value)
|
||||
{
|
||||
if (!$in_value)
|
||||
{
|
||||
$name = '';
|
||||
$value = '';
|
||||
$comment = '';
|
||||
$found_assignment = false;
|
||||
}
|
||||
$in_value = false;
|
||||
$end_section = false;
|
||||
|
||||
/* ... then we should prase this line char by char:
|
||||
- first there's the variable name
|
||||
- then an equal sign
|
||||
- the variable value
|
||||
- possibly a backslash before the linefeed in this case we need to continue
|
||||
parsing the value in the next line
|
||||
- a # indicating that the rest of the line is a comment
|
||||
- a closing curly bracket indicating the end of this section*/
|
||||
for ($j = 0, $length = strlen($line); $j < $length; $j++)
|
||||
{
|
||||
if ($line[$j] == '#')
|
||||
{
|
||||
$comment = substr($line, $j);
|
||||
break;
|
||||
}
|
||||
else if ($line[$j] == '}')
|
||||
{
|
||||
$comment = substr($line, $j + 1);
|
||||
$end_section = true;
|
||||
break;
|
||||
}
|
||||
else if (!$found_assignment)
|
||||
{
|
||||
if ($line[$j] == '=')
|
||||
{
|
||||
$found_assignment = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$name .= $line[$j];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($line[$j] == '\\' && $j == $length - 1)
|
||||
{
|
||||
$value .= "\n";
|
||||
$in_value = true;
|
||||
// Go to the next line and keep processing the value in there
|
||||
continue 2;
|
||||
}
|
||||
$value .= $line[$j];
|
||||
}
|
||||
}
|
||||
|
||||
// If a name and an equal sign were found then we have append a
|
||||
// new variable object to the section
|
||||
if ($name && $found_assignment)
|
||||
{
|
||||
$section->add_variable(new \phpbb\search\sphinx\config_variable(trim($name), trim($value), ($end_section) ? '' : $comment));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we found a closing curly bracket this section has been completed
|
||||
and we can append it to the section list and continue with looking for
|
||||
the next section */
|
||||
if ($end_section)
|
||||
{
|
||||
$section->set_end_comment($comment);
|
||||
$this->sections[] = $section;
|
||||
$section = null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If we did not find anything meaningful up to here, then just treat it
|
||||
// as a comment
|
||||
$comment = ($skip_first) ? "\t" . substr(ltrim($config_file[$i]), 1) : $config_file[$i];
|
||||
$section->add_variable(new \phpbb\search\sphinx\config_comment($comment));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the config data
|
||||
*
|
||||
* @return string $data The config data that is generated
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function get_data()
|
||||
{
|
||||
$data = "";
|
||||
foreach ($this->sections as $section)
|
||||
{
|
||||
$data .= $section->to_string();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
47
msd2/phpBB3/phpbb/search/sphinx/config_comment.php
Normal file
47
msd2/phpBB3/phpbb/search/sphinx/config_comment.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search\sphinx;
|
||||
|
||||
/**
|
||||
* \phpbb\search\sphinx\config_comment
|
||||
* Represents a comment inside the sphinx configuration
|
||||
*/
|
||||
class config_comment
|
||||
{
|
||||
private $exact_string;
|
||||
|
||||
/**
|
||||
* Create a new comment
|
||||
*
|
||||
* @param string $exact_string The content of the comment including newlines, leading whitespace, etc.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function __construct($exact_string)
|
||||
{
|
||||
$this->exact_string = $exact_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply returns the comment as it was created
|
||||
*
|
||||
* @return string The exact string that was specified in the constructor
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function to_string()
|
||||
{
|
||||
return $this->exact_string;
|
||||
}
|
||||
}
|
160
msd2/phpBB3/phpbb/search/sphinx/config_section.php
Normal file
160
msd2/phpBB3/phpbb/search/sphinx/config_section.php
Normal file
@ -0,0 +1,160 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search\sphinx;
|
||||
|
||||
/**
|
||||
* \phpbb\search\sphinx\config_section
|
||||
* Represents a single section inside the sphinx configuration
|
||||
*/
|
||||
class config_section
|
||||
{
|
||||
private $name;
|
||||
private $comment;
|
||||
private $end_comment;
|
||||
private $variables = array();
|
||||
|
||||
/**
|
||||
* Construct a new section
|
||||
*
|
||||
* @param string $name Name of the section
|
||||
* @param string $comment Comment that should be appended after the name in the
|
||||
* textual format.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function __construct($name, $comment)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->comment = $comment;
|
||||
$this->end_comment = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a variable object to the list of variables in this section
|
||||
*
|
||||
* @param \phpbb\search\sphinx\config_variable $variable The variable object
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function add_variable($variable)
|
||||
{
|
||||
$this->variables[] = $variable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a comment after the closing bracket in the textual representation
|
||||
*
|
||||
* @param string $end_comment
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function set_end_comment($end_comment)
|
||||
{
|
||||
$this->end_comment = $end_comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the name of this section
|
||||
*
|
||||
* @return string Section's name
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function get_name()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a variable object by its name
|
||||
*
|
||||
* @param string $name The name of the variable that shall be returned
|
||||
* @return \phpbb\search\sphinx\config_section The first variable object from this section with the
|
||||
* given name or null if none was found
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function get_variable_by_name($name)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return $this->variables[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all variables with the given name
|
||||
*
|
||||
* @param string $name The name of the variable objects that are supposed to be removed
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function delete_variables_by_name($name)
|
||||
{
|
||||
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)
|
||||
{
|
||||
array_splice($this->variables, $i, 1);
|
||||
$i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new variable object and append it to the variable list of this section
|
||||
*
|
||||
* @param string $name The name for the new variable
|
||||
* @param string $value The value for the new variable
|
||||
* @return \phpbb\search\sphinx\config_variable Variable object that was created
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function create_variable($name, $value)
|
||||
{
|
||||
$this->variables[] = new \phpbb\search\sphinx\config_variable($name, $value, '');
|
||||
return $this->variables[count($this->variables) - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns this object into a string which can be written to a config file
|
||||
*
|
||||
* @return string Config data in textual form, parsable for sphinx
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function to_string()
|
||||
{
|
||||
$content = $this->name . ' ' . $this->comment . "\n{\n";
|
||||
|
||||
// Make sure we don't get too many newlines after the opening bracket
|
||||
while (trim($this->variables[0]->to_string()) == '')
|
||||
{
|
||||
array_shift($this->variables);
|
||||
}
|
||||
|
||||
foreach ($this->variables as $variable)
|
||||
{
|
||||
$content .= $variable->to_string();
|
||||
}
|
||||
$content .= '}' . $this->end_comment . "\n";
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
78
msd2/phpBB3/phpbb/search/sphinx/config_variable.php
Normal file
78
msd2/phpBB3/phpbb/search/sphinx/config_variable.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search\sphinx;
|
||||
|
||||
/**
|
||||
* \phpbb\search\sphinx\config_variable
|
||||
* Represents a single variable inside the sphinx configuration
|
||||
*/
|
||||
class config_variable
|
||||
{
|
||||
private $name;
|
||||
private $value;
|
||||
private $comment;
|
||||
|
||||
/**
|
||||
* Constructs a new variable object
|
||||
*
|
||||
* @param string $name Name of the variable
|
||||
* @param string $value Value of the variable
|
||||
* @param string $comment Optional comment after the variable in the
|
||||
* config file
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function __construct($name, $value, $comment)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->value = $value;
|
||||
$this->comment = $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the variable's name
|
||||
*
|
||||
* @return string The variable object's name
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function get_name()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows changing the variable's value
|
||||
*
|
||||
* @param string $value New value for this variable
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function set_value($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns this object into a string readable by sphinx
|
||||
*
|
||||
* @return string Config data in textual form
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function to_string()
|
||||
{
|
||||
return "\t" . $this->name . ' = ' . str_replace("\n", " \\\n", $this->value) . ' ' . $this->comment . "\n";
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user