From 2aabf560b4a1b89b097cf8b23de79f19c7325b50 Mon Sep 17 00:00:00 2001 From: Ruben Calvo Date: Wed, 7 Nov 2018 06:21:46 +0000 Subject: [PATCH 01/22] [ticket/15540] Refactor search backend classes to Symfony services PHPBB3-15540 --- phpBB/config/default/container/services.yml | 1 + .../default/container/services_search.yml | 69 ++++++++ phpBB/develop/search_fill.php | 12 +- phpBB/includes/acp/acp_main.php | 7 +- phpBB/includes/acp/acp_search.php | 70 ++------ phpBB/includes/functions_admin.php | 18 +- phpBB/includes/functions_posting.php | 17 +- phpBB/includes/mcp/mcp_main.php | 11 +- phpBB/includes/mcp/mcp_post.php | 16 +- phpBB/includes/mcp/mcp_topic.php | 18 +- phpBB/install/convert/convertor.php | 10 +- phpBB/install/schemas/schema_data.sql | 2 +- .../data/v330/search_backend_update.php | 39 +++++ phpBB/phpbb/search/{ => backend}/base.php | 10 +- .../search/{ => backend}/fulltext_mysql.php | 110 ++++-------- .../search/{ => backend}/fulltext_native.php | 109 ++++-------- .../{ => backend}/fulltext_postgres.php | 108 +++--------- .../search/{ => backend}/fulltext_sphinx.php | 110 +++--------- .../backend/search_backend_interface.php | 156 ++++++++++++++++++ .../search/{ => backend}/sphinx/config.php | 2 +- .../{ => backend}/sphinx/config_comment.php | 2 +- .../{ => backend}/sphinx/config_section.php | 2 +- .../{ => backend}/sphinx/config_variable.php | 2 +- phpBB/phpbb/search/index.htm | 10 -- phpBB/phpbb/search/search_backend_factory.php | 64 +++++++ phpBB/search.php | 16 +- tests/functional/search/base.php | 2 +- tests/functional/search/mysql_test.php | 2 +- tests/functional/search/native_test.php | 2 +- tests/functional/search/postgres_test.php | 2 +- tests/functional/search/sphinx_test.php | 2 +- tests/functions_user/delete_user_test.php | 2 +- tests/mock/search.php | 71 +++++++- tests/search/mysql_test.php | 5 +- tests/search/native_test.php | 5 +- tests/search/postgres_test.php | 5 +- 36 files changed, 567 insertions(+), 522 deletions(-) create mode 100644 phpBB/config/default/container/services_search.yml create mode 100644 phpBB/phpbb/db/migration/data/v330/search_backend_update.php rename phpBB/phpbb/search/{ => backend}/base.php (98%) rename phpBB/phpbb/search/{ => backend}/fulltext_mysql.php (87%) rename phpBB/phpbb/search/{ => backend}/fulltext_native.php (92%) rename phpBB/phpbb/search/{ => backend}/fulltext_postgres.php (87%) rename phpBB/phpbb/search/{ => backend}/fulltext_sphinx.php (86%) create mode 100644 phpBB/phpbb/search/backend/search_backend_interface.php rename phpBB/phpbb/search/{ => backend}/sphinx/config.php (99%) rename phpBB/phpbb/search/{ => backend}/sphinx/config_comment.php (95%) rename phpBB/phpbb/search/{ => backend}/sphinx/config_section.php (98%) rename phpBB/phpbb/search/{ => backend}/sphinx/config_variable.php (97%) delete mode 100644 phpBB/phpbb/search/index.htm create mode 100644 phpBB/phpbb/search/search_backend_factory.php diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index b34e5306e3..9c0ba58a19 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -24,6 +24,7 @@ imports: - { resource: services_profilefield.yml } - { resource: services_report.yml } - { resource: services_routing.yml } + - { resource: services_search.yml } - { resource: services_storage.yml } - { resource: services_text_formatter.yml } - { resource: services_text_reparser.yml } diff --git a/phpBB/config/default/container/services_search.yml b/phpBB/config/default/container/services_search.yml new file mode 100644 index 0000000000..0ceb7e06c3 --- /dev/null +++ b/phpBB/config/default/container/services_search.yml @@ -0,0 +1,69 @@ +services: + +# Search backends + search.fulltext.native: + class: phpbb\search\backend\fulltext_native + arguments: + - '@auth' + - '@config' + - '@dbal.conn' + - '@dispatcher' + - '@user' + - '%core.root_path%' + - '%core.php_ext%' + tags: + - { name: search.backend } + + search.fulltext.mysql: + class: phpbb\search\backend\fulltext_mysql + arguments: + - '@auth' + - '@config' + - '@dbal.conn' + - '@dispatcher' + - '@user' + - '%core.root_path%' + - '%core.php_ext%' + tags: + - { name: search.backend } + + search.fulltext.postgres: + class: phpbb\search\backend\fulltext_postgres + arguments: + - '@auth' + - '@config' + - '@dbal.conn' + - '@dispatcher' + - '@user' + - '%core.root_path%' + - '%core.php_ext%' + tags: + - { name: search.backend } + + search.fulltext.sphinx: + class: phpbb\search\backend\fulltext_sphinx + arguments: + - '@auth' + - '@config' + - '@dbal.conn' + - '@dispatcher' + - '@user' + - '%core.root_path%' + - '%core.php_ext%' + tags: + - { name: search.backend } + +# Factory + search.backend_factory: + class: phpbb\search\search_backend_factory + arguments: + - '@config' + - '@search.backend_collection' + +# Collections + search.backend_collection: + class: phpbb\di\service_collection + arguments: + - '@service_container' + tags: + - { name: service_collection, tag: search.backend, class_name_aware: true } diff --git a/phpBB/develop/search_fill.php b/phpBB/develop/search_fill.php index 4f684b5b27..1dcdcdace6 100644 --- a/phpBB/develop/search_fill.php +++ b/phpBB/develop/search_fill.php @@ -39,13 +39,7 @@ if (!class_exists($search_type)) trigger_error('NO_SUCH_SEARCH_MODULE'); } -$error = false; -$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); - -if ($error) -{ - trigger_error($error); -} +$search = new $search_type($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); print "\n\n"; @@ -74,7 +68,7 @@ for(;$postcounter <= $max_post_id; $postcounter += $batchsize) $batchstart = $postcounter + 1; $batchend = $postcounter + $batchsize; $batchcount++; - + $sql = "SELECT * FROM " . POSTS_TABLE . " WHERE post_id @@ -90,7 +84,7 @@ for(;$postcounter <= $max_post_id; $postcounter += $batchsize) $db->sql_freeresult($result); $post_rows = count($rowset); - + if( $post_rows ) { diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index fcbb736eb6..d65958dfd0 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -646,11 +646,10 @@ class acp_main } // Warn if no search index is created - if ($config['num_posts'] && class_exists($config['search_type'])) + if ($config['num_posts']) { - $error = false; - $search_type = $config['search_type']; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); if (!$search->index_created()) { diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 3b6febd566..2bdd456967 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -52,6 +52,7 @@ class acp_search { global $user, $template, $phpbb_log, $request; global $config, $phpbb_admin_path, $phpEx; + global $phpbb_container; $submit = $request->is_set_post('submit'); @@ -60,7 +61,7 @@ class acp_search trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } - $search_types = $this->get_search_types(); + $search_types = $phpbb_container->get('search.backend_collection'); $settings = [ 'search_interval' => 'float', @@ -74,14 +75,11 @@ class acp_search ]; $search = null; - $error = false; $search_options = ''; - foreach ($search_types as $type) + + foreach ($search_types as $search) { - if ($this->init_search($type, $search, $error)) - { - continue; - } + $type = get_class($search); $name = $search->get_name(); @@ -108,7 +106,6 @@ class acp_search } } unset($search); - unset($error); $cfg_array = (isset($_REQUEST['config'])) ? $request->variable('config', array('' => ''), true) : array(); $updated = $request->variable('updated', false); @@ -240,7 +237,7 @@ class acp_search function index($id, $mode) { global $db, $user, $template, $phpbb_log, $request; - global $config, $phpbb_admin_path, $phpEx; + global $config, $phpbb_admin_path, $phpEx, $phpbb_container; $action = $request->variable('action', ''); $this->state = explode(',', $config['search_indexing_state']); @@ -285,12 +282,11 @@ class acp_search $this->state[0] = $request->variable('search_type', ''); } - $this->search = null; $error = false; - if ($this->init_search($this->state[0], $this->search, $error)) - { - trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); - } + + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $this->search = $search_backend_factory->get($this->state[0]); + $name = $this->search->get_name(); $action = &$this->state[1]; @@ -454,16 +450,13 @@ class acp_search } } - $search_types = $this->get_search_types(); + $search_types = $phpbb_container->get('search.backend_collection'); $search = null; - $error = false; - foreach ($search_types as $type) + + foreach ($search_types as $search) { - if ($this->init_search($type, $search, $error) || !method_exists($search, 'index_created')) - { - continue; - } + $type = get_class($search); $name = $search->get_name(); @@ -508,7 +501,6 @@ class acp_search } } unset($search); - unset($error); unset($statistics); unset($data); @@ -562,19 +554,6 @@ class acp_search "\n"; } - function get_search_types() - { - global $phpbb_extension_manager; - - $finder = $phpbb_extension_manager->get_finder(); - - return $finder - ->extension_suffix('_backend') - ->extension_directory('/search') - ->core_path('phpbb/search/') - ->get_classes(); - } - function get_max_post_id() { global $db; @@ -601,25 +580,4 @@ class acp_search $config->set('search_indexing_state', implode(',', $this->state), true); } - - /** - * Initialises a search backend object - * - * @return false if no error occurred else an error message - */ - function init_search($type, &$search, &$error) - { - global $phpbb_root_path, $phpEx, $user, $auth, $config, $db, $phpbb_dispatcher; - - if (!class_exists($type) || !method_exists($type, 'keyword_search')) - { - $error = $user->lang['NO_SUCH_SEARCH_MODULE']; - return $error; - } - - $error = false; - $search = new $type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); - - return $error; - } } diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 42b360b17a..73d025ae7f 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -904,7 +904,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s */ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = true, $post_count_sync = true, $call_delete_topics = true) { - global $db, $config, $phpbb_root_path, $phpEx, $auth, $user, $phpbb_container, $phpbb_dispatcher; + global $db, $config, $phpbb_container, $phpbb_dispatcher; // Notifications types to delete $delete_notifications_types = array( @@ -1086,20 +1086,8 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = } // Remove the message from the search index - $search_type = $config['search_type']; - - if (!class_exists($search_type)) - { - trigger_error('NO_SUCH_SEARCH_MODULE'); - } - - $error = false; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); - - if ($error) - { - trigger_error($error); - } + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); $search->index_remove($post_ids, $poster_ids, $forum_ids); diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index fade2a54a7..6cdbb2f8a0 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -2291,21 +2291,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data // Index message contents if ($update_search_index && $data_ary['enable_indexing']) { - // Select the search method and do some additional checks to ensure it can actually be utilised - $search_type = $config['search_type']; - - if (!class_exists($search_type)) - { - trigger_error('NO_SUCH_SEARCH_MODULE'); - } - - $error = false; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); - - if ($error) - { - trigger_error($error); - } + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); $search->index($mode, $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, $data_ary['forum_id']); } diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 9cf4ca9c96..966be7cd91 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -1401,15 +1401,8 @@ function mcp_fork_topic($topic_ids) if (!isset($search_type) && $topic_row['enable_indexing']) { // Select the search method and do some additional checks to ensure it can actually be utilised - $search_type = $config['search_type']; - - if (!class_exists($search_type)) - { - trigger_error('NO_SUCH_SEARCH_MODULE'); - } - - $error = false; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); $search_mode = 'post'; if ($error) diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index 5ae1f8ff40..e75f2f8111 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -561,7 +561,7 @@ function phpbb_get_num_ips_for_poster(\phpbb\db\driver\driver_interface $db, $po */ function change_poster(&$post_info, $userdata) { - global $auth, $db, $config, $phpbb_root_path, $phpEx, $user, $phpbb_log, $phpbb_dispatcher; + global $db, $config, $user, $phpbb_log, $phpbb_dispatcher; if (empty($userdata) || $userdata['user_id'] == $post_info['user_id']) { @@ -632,18 +632,12 @@ function change_poster(&$post_info, $userdata) } // refresh search cache of this post - $search_type = $config['search_type']; + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); - if (class_exists($search_type)) + if (method_exists($search, 'destroy_cache')) { - // We do some additional checks in the module to ensure it can actually be utilised - $error = false; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); - - if (!$error && method_exists($search, 'destroy_cache')) - { - $search->destroy_cache(array(), array($post_info['user_id'], $userdata['user_id'])); - } + $search->destroy_cache(array(), array($post_info['user_id'], $userdata['user_id'])); } $from_username = $post_info['username']; diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index e47ae47d9b..3c37fa4d66 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -428,7 +428,7 @@ function mcp_topic_view($id, $mode, $action) */ function split_topic($action, $topic_id, $to_forum_id, $subject) { - global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config, $phpbb_log, $request, $phpbb_dispatcher; + global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config, $phpbb_log, $request; $post_id_list = $request->variable('post_id_list', array(0)); $forum_id = $request->variable('forum_id', 0); @@ -625,20 +625,8 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) if ($first_post_data['enable_indexing']) { // Select the search method and do some additional checks to ensure it can actually be utilised - $search_type = $config['search_type']; - - if (!class_exists($search_type)) - { - trigger_error('NO_SUCH_SEARCH_MODULE'); - } - - $error = false; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); - - if ($error) - { - trigger_error($error); - } + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); $search->index('edit', $first_post_data['post_id'], $first_post_data['post_text'], $subject, $first_post_data['poster_id'], $first_post_data['forum_id']); } diff --git a/phpBB/install/convert/convertor.php b/phpBB/install/convert/convertor.php index f8196d73a1..54ec85fd21 100644 --- a/phpBB/install/convert/convertor.php +++ b/phpBB/install/convert/convertor.php @@ -215,7 +215,7 @@ class convertor // For conversions we are a bit less strict and set to a search backend we know exist... if (!class_exists($search_type)) { - $search_type = '\phpbb\search\fulltext_native'; + $search_type = 'phpbb\search\backend\fulltext_native'; $config->set('search_type', $search_type); } @@ -224,13 +224,7 @@ class convertor trigger_error('NO_SUCH_SEARCH_MODULE'); } - $error = false; - $convert->fulltext_search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); - - if ($error) - { - trigger_error($error); - } + $convert->fulltext_search = new $search_type($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx); $message_parser = new \parse_message(); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index e6a3187a79..9fa5b2524e 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -275,7 +275,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_block_size' INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_gc', '7200'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_interval', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_store_results', '1800'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_type', '\phpbb\search\fulltext_native'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_type', '\phpbb\search\backend\fulltext_native'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_allow_deny', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_allow_empty_referer', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_downloads', '0'); diff --git a/phpBB/phpbb/db/migration/data/v330/search_backend_update.php b/phpBB/phpbb/db/migration/data/v330/search_backend_update.php new file mode 100644 index 0000000000..f7c979fc5e --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/search_backend_update.php @@ -0,0 +1,39 @@ + +* @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\db\migration\data\v330; + +class search_backend_update extends \phpbb\db\migration\migration +{ + public function update_data() + { + switch ($this->config['search_type']) + { + case '\\phpbb\\search\\fulltext_mysql': + $new_search_type = 'phpbb\\search\\backend\\fulltext_mysql'; + break; + case '\\phpbb\\search\\fulltext_postgres': + $new_search_type = 'phpbb\\search\\backend\\fulltext_postgres'; + break; + case '\\phpbb\\search\\fulltext_sphinx': + $new_search_type = 'phpbb\\search\\backend\\fulltext_sphinx'; + break; + default: + $new_search_type = 'phpbb\\search\\backend\\fulltext_native'; + } + + return [ + ['config.update', ['search_type', $new_search_type]], + ]; + } +} diff --git a/phpBB/phpbb/search/base.php b/phpBB/phpbb/search/backend/base.php similarity index 98% rename from phpBB/phpbb/search/base.php rename to phpBB/phpbb/search/backend/base.php index e7d0774b6c..281e4da3a8 100644 --- a/phpBB/phpbb/search/base.php +++ b/phpBB/phpbb/search/backend/base.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\search; +namespace phpbb\search\backend; /** * @ignore @@ -24,18 +24,12 @@ 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 +abstract 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 * diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php similarity index 87% rename from phpBB/phpbb/search/fulltext_mysql.php rename to phpBB/phpbb/search/backend/fulltext_mysql.php index b493ccf326..f71c9d21e9 100644 --- a/phpBB/phpbb/search/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -11,12 +11,12 @@ * */ -namespace phpbb\search; +namespace phpbb\search\backend; /** * Fulltext search for MySQL */ -class fulltext_mysql extends \phpbb\search\base +class fulltext_mysql extends base implements search_backend_interface { /** * Associative array holding index stats @@ -76,7 +76,7 @@ class fulltext_mysql extends \phpbb\search\base /** * Constructor - * Creates a new \phpbb\search\fulltext_mysql, which is used as a search backend + * Creates a new \phpbb\search\backend\fulltext_mysql, 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 @@ -87,7 +87,7 @@ class fulltext_mysql extends \phpbb\search\base * @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) + public function __construct($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) { $this->config = $config; $this->db = $db; @@ -103,24 +103,18 @@ class fulltext_mysql extends \phpbb\search\base { include($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); } - - $error = false; } /** - * Returns the name of this search backend to be displayed to administrators - * - * @return string Name - */ + * {@inheritdoc} + */ public function get_name() { return 'MySQL Fulltext'; } /** - * Returns the search_query - * - * @return string search query + * {@inheritdoc} */ public function get_search_query() { @@ -128,9 +122,7 @@ class fulltext_mysql extends \phpbb\search\base } /** - * Returns the common_words array - * - * @return array common words that are ignored by search backend + * {@inheritdoc} */ public function get_common_words() { @@ -138,9 +130,7 @@ class fulltext_mysql extends \phpbb\search\base } /** - * Returns the word_length array - * - * @return array min and max word length for searching + * {@inheritdoc} */ public function get_word_length() { @@ -214,13 +204,8 @@ class fulltext_mysql extends \phpbb\search\base } /** - * Splits keywords entered by a user into an array of words stored in $this->split_words - * Stores the tidied search query in $this->search_query - * - * @param string &$keywords Contains the keyword as entered by the user - * @param string $terms is either 'all' or 'any' - * @return bool false if no valid keywords were found and otherwise true - */ + * {@inheritdoc} + */ public function split_keywords(&$keywords, $terms) { if ($terms == 'all') @@ -383,25 +368,8 @@ class fulltext_mysql extends \phpbb\search\base } /** - * 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 - */ + * {@inheritdoc} + */ 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) { // No keywords? No posts @@ -648,24 +616,8 @@ class fulltext_mysql extends \phpbb\search\base } /** - * 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 - */ + * {@inheritdoc} + */ 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 @@ -965,16 +917,16 @@ class fulltext_mysql extends \phpbb\search\base } /** - * Destroy cached results, that might be outdated after deleting a post - */ + * {@inheritdoc} + */ public function index_remove($post_ids, $author_ids, $forum_ids) { $this->destroy_cache(array(), array_unique($author_ids)); } /** - * Destroy old cache entries - */ + * {@inheritdoc} + */ public function tidy() { // destroy too old cached search results @@ -984,10 +936,8 @@ class fulltext_mysql extends \phpbb\search\base } /** - * Create fulltext index - * - * @return string|bool error string is returned incase of errors otherwise false - */ + * {@inheritdoc} + */ public function create_index($acp_module, $u_action) { // Make sure we can actually use MySQL with fulltext indexes @@ -1058,10 +1008,8 @@ class fulltext_mysql extends \phpbb\search\base } /** - * Drop fulltext index - * - * @return string|bool error string is returned incase of errors otherwise false - */ + * {@inheritdoc} + */ public function delete_index($acp_module, $u_action) { // Make sure we can actually use MySQL with fulltext indexes @@ -1126,7 +1074,7 @@ class fulltext_mysql extends \phpbb\search\base } /** - * Returns true if both FULLTEXT indexes exist + * {@inheritdoc} */ public function index_created() { @@ -1139,8 +1087,8 @@ class fulltext_mysql extends \phpbb\search\base } /** - * Returns an associative array containing information about the indexes - */ + * {@inheritdoc} + */ public function index_stats() { if (empty($this->stats)) @@ -1195,10 +1143,8 @@ class fulltext_mysql extends \phpbb\search\base } /** - * Display a note, that UTF-8 support is not available with certain versions of PHP - * - * @return associative array containing template and config variables - */ + * {@inheritdoc} + */ public function acp() { $tpl = ' diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php similarity index 92% rename from phpBB/phpbb/search/fulltext_native.php rename to phpBB/phpbb/search/backend/fulltext_native.php index 2246dc0aef..b85a5ecceb 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -11,12 +11,12 @@ * */ -namespace phpbb\search; +namespace phpbb\search\backend; /** * phpBB's own db driven fulltext search, version 2 */ -class fulltext_native extends \phpbb\search\base +class fulltext_native extends base implements search_backend_interface { const UTF8_HANGUL_FIRST = "\xEA\xB0\x80"; const UTF8_HANGUL_LAST = "\xED\x9E\xA3"; @@ -117,15 +117,16 @@ class fulltext_native extends \phpbb\search\base * @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) + public function __construct($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) { - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $phpEx; $this->config = $config; $this->db = $db; $this->phpbb_dispatcher = $phpbb_dispatcher; $this->user = $user; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $phpEx; + $this->word_length = array('min' => (int) $this->config['fulltext_native_min_chars'], 'max' => (int) $this->config['fulltext_native_max_chars']); /** @@ -135,14 +136,10 @@ class fulltext_native extends \phpbb\search\base { include($this->phpbb_root_path . 'includes/utf/utf_tools.' . $this->php_ext); } - - $error = false; } /** - * Returns the name of this search backend to be displayed to administrators - * - * @return string Name + * {@inheritdoc} */ public function get_name() { @@ -150,9 +147,7 @@ class fulltext_native extends \phpbb\search\base } /** - * Returns the search_query - * - * @return string search query + * {@inheritdoc} */ public function get_search_query() { @@ -160,9 +155,7 @@ class fulltext_native extends \phpbb\search\base } /** - * Returns the common_words array - * - * @return array common words that are ignored by search backend + * {@inheritdoc} */ public function get_common_words() { @@ -170,9 +163,7 @@ class fulltext_native extends \phpbb\search\base } /** - * Returns the word_length array - * - * @return array min and max word length for searching + * {@inheritdoc} */ public function get_word_length() { @@ -194,7 +185,7 @@ class fulltext_native extends \phpbb\search\base * or 'any' (find all posts containing at least one of the given words) * @return boolean false if no valid keywords were found and otherwise true */ - public function split_keywords($keywords, $terms) + public function split_keywords(&$keywords, $terms) { $tokens = '+-|()* '; @@ -514,25 +505,8 @@ class fulltext_native extends \phpbb\search\base } /** - * 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 - */ + * {@inheritdoc} + */ 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) { // No keywords? No posts. @@ -1016,24 +990,8 @@ class fulltext_native extends \phpbb\search\base } /** - * 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 - */ + * {@inheritdoc} + */ 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 @@ -1401,14 +1359,7 @@ class fulltext_native extends \phpbb\search\base } /** - * 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 + * {@inheritdoc} */ public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) { @@ -1597,8 +1548,8 @@ class fulltext_native extends \phpbb\search\base } /** - * Removes entries from the wordmatch table for the specified post_ids - */ + * {@inheritdoc} + */ public function index_remove($post_ids, $author_ids, $forum_ids) { if (count($post_ids)) @@ -1654,9 +1605,8 @@ class fulltext_native extends \phpbb\search\base } /** - * Tidy up indexes: Tag 'common words' and remove - * words no longer referenced in the match table - */ + * {@inheritdoc} + */ public function tidy() { // Is the fulltext indexer disabled? If yes then we need not @@ -1718,8 +1668,8 @@ class fulltext_native extends \phpbb\search\base } /** - * Deletes all words from the index - */ + * {@inheritdoc} + */ public function delete_index($acp_module, $u_action) { $sql_queries = []; @@ -1762,7 +1712,7 @@ class fulltext_native extends \phpbb\search\base } /** - * Returns true if both FULLTEXT indexes exist + * {@inheritdoc} */ public function index_created() { @@ -1775,8 +1725,8 @@ class fulltext_native extends \phpbb\search\base } /** - * Returns an associative array containing information about the indexes - */ + * {@inheritdoc} + */ public function index_stats() { if (!count($this->stats)) @@ -1788,7 +1738,10 @@ class fulltext_native extends \phpbb\search\base $this->user->lang['TOTAL_WORDS'] => $this->stats['total_words'], $this->user->lang['TOTAL_MATCHES'] => $this->stats['total_matches']); } - + + /** + * Computes the stats and store them in the $this->stats associative array + */ protected function get_stats() { $this->stats['total_words'] = $this->db->get_estimated_row_count(SEARCH_WORDLIST_TABLE); @@ -2032,8 +1985,8 @@ class fulltext_native extends \phpbb\search\base } /** - * Returns a list of options for the ACP to display - */ + * {@inheritdoc} + */ public function acp() { /** diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php similarity index 87% rename from phpBB/phpbb/search/fulltext_postgres.php rename to phpBB/phpbb/search/backend/fulltext_postgres.php index 0b7b32a6c6..b0652a361d 100644 --- a/phpBB/phpbb/search/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -11,12 +11,12 @@ * */ -namespace phpbb\search; +namespace phpbb\search\backend; /** * Fulltext search for PostgreSQL */ -class fulltext_postgres extends \phpbb\search\base +class fulltext_postgres extends base implements search_backend_interface { /** * Associative array holding index stats @@ -89,7 +89,7 @@ class fulltext_postgres extends \phpbb\search\base /** * Constructor - * Creates a new \phpbb\search\fulltext_postgres, which is used as a search backend + * Creates a new \phpbb\search\backend\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 @@ -100,7 +100,7 @@ class fulltext_postgres extends \phpbb\search\base * @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) + public function __construct($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) { $this->config = $config; $this->db = $db; @@ -116,24 +116,18 @@ class fulltext_postgres extends \phpbb\search\base { include($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); } - - $error = false; } /** - * Returns the name of this search backend to be displayed to administrators - * - * @return string Name - */ + * {@inheritdoc} + */ public function get_name() { return 'PostgreSQL Fulltext'; } /** - * Returns the search_query - * - * @return string search query + * {@inheritdoc} */ public function get_search_query() { @@ -141,9 +135,7 @@ class fulltext_postgres extends \phpbb\search\base } /** - * Returns the common_words array - * - * @return array common words that are ignored by search backend + * {@inheritdoc} */ public function get_common_words() { @@ -151,9 +143,7 @@ class fulltext_postgres extends \phpbb\search\base } /** - * Returns the word_length array - * - * @return array min and max word length for searching + * {@inheritdoc} */ public function get_word_length() { @@ -186,13 +176,8 @@ class fulltext_postgres extends \phpbb\search\base } /** - * Splits keywords entered by a user into an array of words stored in $this->split_words - * Stores the tidied search query in $this->search_query - * - * @param string &$keywords Contains the keyword as entered by the user - * @param string $terms is either 'all' or 'any' - * @return bool false if no valid keywords were found and otherwise true - */ + * {@inheritdoc} + */ public function split_keywords(&$keywords, $terms) { if ($terms == 'all') @@ -307,25 +292,8 @@ class fulltext_postgres extends \phpbb\search\base } /** - * 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 - */ + * {@inheritdoc} + */ 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) { // No keywords? No posts @@ -588,24 +556,8 @@ class fulltext_postgres extends \phpbb\search\base } /** - * 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 - */ + * {@inheritdoc} + */ 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 @@ -927,16 +879,16 @@ class fulltext_postgres extends \phpbb\search\base } /** - * Destroy cached results, that might be outdated after deleting a post - */ + * {@inheritdoc} + */ public function index_remove($post_ids, $author_ids, $forum_ids) { $this->destroy_cache(array(), $author_ids); } /** - * Destroy old cache entries - */ + * {@inheritdoc} + */ public function tidy() { // destroy too old cached search results @@ -946,10 +898,8 @@ class fulltext_postgres extends \phpbb\search\base } /** - * Create fulltext index - * - * @return string|bool error string is returned incase of errors otherwise false - */ + * {@inheritdoc} + */ public function create_index($acp_module, $u_action) { // Make sure we can actually use PostgreSQL with fulltext indexes @@ -1007,10 +957,8 @@ class fulltext_postgres extends \phpbb\search\base } /** - * Drop fulltext index - * - * @return string|bool error string is returned incase of errors otherwise false - */ + * {@inheritdoc} + */ public function delete_index($acp_module, $u_action) { // Make sure we can actually use PostgreSQL with fulltext indexes @@ -1068,7 +1016,7 @@ class fulltext_postgres extends \phpbb\search\base } /** - * Returns true if both FULLTEXT indexes exist + * {@inheritdoc} */ public function index_created() { @@ -1081,7 +1029,7 @@ class fulltext_postgres extends \phpbb\search\base } /** - * Returns an associative array containing information about the indexes + * {@inheritdoc} */ public function index_stats() { @@ -1139,10 +1087,8 @@ class fulltext_postgres extends \phpbb\search\base } /** - * Display various options that can be configured for the backend from the acp - * - * @return associative array containing template and config variables - */ + * {@inheritdoc} + */ public function acp() { $tpl = ' diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php similarity index 86% rename from phpBB/phpbb/search/fulltext_sphinx.php rename to phpBB/phpbb/search/backend/fulltext_sphinx.php index 8f24f970da..9715754a01 100644 --- a/phpBB/phpbb/search/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\search; +namespace phpbb\search\backend; define('SPHINX_MAX_MATCHES', 20000); define('SPHINX_CONNECT_RETRIES', 3); @@ -20,7 +20,7 @@ define('SPHINX_CONNECT_WAIT_TIME', 300); /** * Fulltext search based on the sphinx search daemon */ -class fulltext_sphinx +class fulltext_sphinx implements search_backend_interface { /** * Associative array holding index stats @@ -122,7 +122,7 @@ class fulltext_sphinx /** * Constructor - * Creates a new \phpbb\search\fulltext_postgres, which is used as a search backend + * Creates a new \phpbb\search\backend\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 @@ -133,15 +133,16 @@ class fulltext_sphinx * @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) + public function __construct($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) { - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $phpEx; + $this->auth = $auth; $this->config = $config; + $this->db = $db; $this->phpbb_dispatcher = $phpbb_dispatcher; $this->user = $user; - $this->db = $db; - $this->auth = $auth; + + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $phpEx; // Initialize \phpbb\db\tools\tools object global $phpbb_container; // TODO inject into object @@ -163,24 +164,18 @@ class fulltext_sphinx $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 - */ + * {@inheritdoc} + */ public function get_name() { return 'Sphinx Fulltext'; } /** - * Returns the search_query - * - * @return string search query + * {@inheritdoc} */ public function get_search_query() { @@ -188,9 +183,7 @@ class fulltext_sphinx } /** - * Returns false as there is no word_len array - * - * @return false + * {@inheritdoc} */ public function get_word_length() { @@ -198,9 +191,7 @@ class fulltext_sphinx } /** - * Returns an empty array as there are no common_words - * - * @return array common words that are ignored by search backend + * {@inheritdoc} */ public function get_common_words() { @@ -426,13 +417,8 @@ class fulltext_sphinx } /** - * 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 - */ + * {@inheritdoc} + */ public function split_keywords(&$keywords, $terms) { // Keep quotes and new lines @@ -521,25 +507,8 @@ class fulltext_sphinx } /** - * 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 - */ + * {@inheritdoc} + */ 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; @@ -780,24 +749,8 @@ class fulltext_sphinx } /** - * 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 - */ + * {@inheritdoc} + */ 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 = ''; @@ -809,14 +762,7 @@ class fulltext_sphinx } /** - * 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 + * {@inheritdoc} */ public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) { @@ -882,8 +828,8 @@ class fulltext_sphinx } /** - * Delete a post from the index after it was deleted - */ + * {@inheritdoc} + */ public function index_remove($post_ids, $author_ids, $forum_ids) { $values = array(); @@ -989,8 +935,8 @@ class fulltext_sphinx } /** - * Collects stats that can be displayed on the index maintenance page - */ + * Computes the stats and store them in the $this->stats associative array + */ protected function get_stats() { if ($this->index_created()) @@ -1012,10 +958,8 @@ class fulltext_sphinx } /** - * Returns a list of options for the ACP to display - * - * @return associative array containing template and config variables - */ + * {@inheritdoc} + */ public function acp() { $config_vars = array( diff --git a/phpBB/phpbb/search/backend/search_backend_interface.php b/phpBB/phpbb/search/backend/search_backend_interface.php new file mode 100644 index 0000000000..24ff56a0a0 --- /dev/null +++ b/phpBB/phpbb/search/backend/search_backend_interface.php @@ -0,0 +1,156 @@ + + * @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\backend; + +interface search_backend_interface +{ + /** + * Returns the name of this search backend to be displayed to administrators + * + * @return string Name + */ + public function get_name(); + + /** + * Returns the search_query + * + * @return string search query + */ + public function get_search_query(); + + /** + * Returns the common_words array + * + * @return array common words that are ignored by search backend + */ + public function get_common_words(); + + /** + * Returns the word_length array + * + * @return array min and max word length for searching + */ + public function get_word_length(); + + //public function init(); + + /** + * Splits keywords entered by a user into an array of words stored in $this->split_words + * Stores the tidied search query in $this->search_query + * + * @param string &$keywords Contains the keyword as entered by the user + * @param string $terms is either 'all' or 'any' + * @return bool false if no valid keywords were found and otherwise true + */ + public function split_keywords(&$keywords, $terms); + + /** + * 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); + + /** + * 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); + + /** + * 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 contains the post id of the post to index + * @param string $message contains the post text of the post + * @param string $subject contains the subject of the post to index + * @param int $poster_id contains the user id of the poster + * @param int $forum_id contains the forum id of parent forum of the post + */ + public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id); + + /** + * Destroy cached results, that might be outdated after deleting a post + */ + public function index_remove($post_ids, $author_ids, $forum_ids); + + /** + * Destroy old cache entries + */ + public function tidy(); + + /** + * Create fulltext index + * + * @return string|bool error string is returned incase of errors otherwise false + */ + // This method isn't present in fulltext_native, because it's implementation is hardcoded in acp_search + //public function create_index($acp_module, $u_action); + + /** + * Drop fulltext index + * + * @return string|bool error string is returned incase of errors otherwise false + */ + public function delete_index($acp_module, $u_action); + + /** + * Returns true if both FULLTEXT indexes exist + */ + public function index_created(); + + /** + * Returns an associative array containing information about the indexes + * + * @return array|bool Language string of error false otherwise + */ + public function index_stats(); + + /** + * Display various options that can be configured for the backend from the acp + * + * @return associative array containing template and config variables + */ + public function acp(); +} diff --git a/phpBB/phpbb/search/sphinx/config.php b/phpBB/phpbb/search/backend/sphinx/config.php similarity index 99% rename from phpBB/phpbb/search/sphinx/config.php rename to phpBB/phpbb/search/backend/sphinx/config.php index 3205574b45..68a6c8684c 100644 --- a/phpBB/phpbb/search/sphinx/config.php +++ b/phpBB/phpbb/search/backend/sphinx/config.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\search\sphinx; +namespace phpbb\search\backend\sphinx; /** * An object representing the sphinx configuration diff --git a/phpBB/phpbb/search/sphinx/config_comment.php b/phpBB/phpbb/search/backend/sphinx/config_comment.php similarity index 95% rename from phpBB/phpbb/search/sphinx/config_comment.php rename to phpBB/phpbb/search/backend/sphinx/config_comment.php index b5cd0a3db5..b49b9f903f 100644 --- a/phpBB/phpbb/search/sphinx/config_comment.php +++ b/phpBB/phpbb/search/backend/sphinx/config_comment.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\search\sphinx; +namespace phpbb\search\backend\sphinx; /** * \phpbb\search\sphinx\config_comment diff --git a/phpBB/phpbb/search/sphinx/config_section.php b/phpBB/phpbb/search/backend/sphinx/config_section.php similarity index 98% rename from phpBB/phpbb/search/sphinx/config_section.php rename to phpBB/phpbb/search/backend/sphinx/config_section.php index 2fc8b2da17..56409809f4 100644 --- a/phpBB/phpbb/search/sphinx/config_section.php +++ b/phpBB/phpbb/search/backend/sphinx/config_section.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\search\sphinx; +namespace phpbb\search\backend\sphinx; /** * \phpbb\search\sphinx\config_section diff --git a/phpBB/phpbb/search/sphinx/config_variable.php b/phpBB/phpbb/search/backend/sphinx/config_variable.php similarity index 97% rename from phpBB/phpbb/search/sphinx/config_variable.php rename to phpBB/phpbb/search/backend/sphinx/config_variable.php index 85cee20b62..8ff237d676 100644 --- a/phpBB/phpbb/search/sphinx/config_variable.php +++ b/phpBB/phpbb/search/backend/sphinx/config_variable.php @@ -11,7 +11,7 @@ * */ -namespace phpbb\search\sphinx; +namespace phpbb\search\backend\sphinx; /** * \phpbb\search\sphinx\config_variable diff --git a/phpBB/phpbb/search/index.htm b/phpBB/phpbb/search/index.htm deleted file mode 100644 index ee1f723a7d..0000000000 --- a/phpBB/phpbb/search/index.htm +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/phpBB/phpbb/search/search_backend_factory.php b/phpBB/phpbb/search/search_backend_factory.php new file mode 100644 index 0000000000..636c8f823f --- /dev/null +++ b/phpBB/phpbb/search/search_backend_factory.php @@ -0,0 +1,64 @@ + + * @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; + +use phpbb\config\config; +use phpbb\di\service_collection; + +class search_backend_factory +{ + /** + * @var \phpbb\config\config + */ + protected $config; + + /** + * @var \phpbb\di\service_collection + */ + protected $search_backends; + + /** + * Constructor + * + * @param \phpbb\config\config $config + * @param \phpbb\di\service_collection $search_backends + */ + public function __construct(config $config, service_collection $search_backends) + { + $this->config = $config; + $this->search_backends = $search_backends; + } + + /** + * Obtains a specified search backend + * + * @param string $class + * + * @return \phpbb\search\backend\search_backend_interface + */ + public function get($class) + { + return $this->search_backends->get_by_class($class); + } + + /** + * Obtains active search backend + * + * @return \phpbb\search\backend\search_backend_interface + */ + public function get_active() + { + return $this->get($this->config['search_type']); + } +} diff --git a/phpBB/search.php b/phpBB/search.php index 048985b023..bd7532fc07 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -294,20 +294,8 @@ if ($keywords || $author || $author_id || $search_id || $submit) } // Select which method we'll use to obtain the post_id or topic_id information - $search_type = $config['search_type']; - - if (!class_exists($search_type)) - { - trigger_error('NO_SUCH_SEARCH_MODULE'); - } - // We do some additional checks in the module to ensure it can actually be utilised - $error = false; - $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); - - if ($error) - { - trigger_error($error); - } + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_search(); // let the search module split up the keywords if ($keywords) diff --git a/tests/functional/search/base.php b/tests/functional/search/base.php index 9e49ba93ab..0558c8e8de 100644 --- a/tests/functional/search/base.php +++ b/tests/functional/search/base.php @@ -38,7 +38,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case $this->login(); $this->admin_login(); - $this->create_search_index('\phpbb\search\fulltext_native'); + $this->create_search_index('\phpbb\search\backend\fulltext_native'); $post = $this->create_topic(2, 'Test Topic 1 foosubject', 'This is a test topic posted by the barsearch testing framework.'); diff --git a/tests/functional/search/mysql_test.php b/tests/functional/search/mysql_test.php index 0f857e9167..43e5c5cab2 100644 --- a/tests/functional/search/mysql_test.php +++ b/tests/functional/search/mysql_test.php @@ -18,7 +18,7 @@ require_once __DIR__ . '/base.php'; */ class phpbb_functional_search_mysql_test extends phpbb_functional_search_base { - protected $search_backend = '\phpbb\search\fulltext_mysql'; + protected $search_backend = '\phpbb\search\backend\fulltext_mysql'; protected function create_search_index($backend = null) { diff --git a/tests/functional/search/native_test.php b/tests/functional/search/native_test.php index 52a653d585..f95ce3184d 100644 --- a/tests/functional/search/native_test.php +++ b/tests/functional/search/native_test.php @@ -18,5 +18,5 @@ require_once __DIR__ . '/base.php'; */ class phpbb_functional_search_native_test extends phpbb_functional_search_base { - protected $search_backend = '\phpbb\search\fulltext_native'; + protected $search_backend = '\phpbb\search\backend\fulltext_native'; } diff --git a/tests/functional/search/postgres_test.php b/tests/functional/search/postgres_test.php index 6f5e7e48c2..ae8f717232 100644 --- a/tests/functional/search/postgres_test.php +++ b/tests/functional/search/postgres_test.php @@ -18,6 +18,6 @@ require_once __DIR__ . '/base.php'; */ class phpbb_functional_search_postgres_test extends phpbb_functional_search_base { - protected $search_backend = '\phpbb\search\fulltext_postgres'; + protected $search_backend = '\phpbb\search\backend\fulltext_postgres'; } diff --git a/tests/functional/search/sphinx_test.php b/tests/functional/search/sphinx_test.php index 926f1c6424..6a8907ed03 100644 --- a/tests/functional/search/sphinx_test.php +++ b/tests/functional/search/sphinx_test.php @@ -18,7 +18,7 @@ require_once __DIR__ . '/base.php'; */ class phpbb_functional_search_sphinx_test extends phpbb_functional_search_base { - protected $search_backend = '\phpbb\search\fulltext_sphinx'; + protected $search_backend = '\phpbb\search\backend\fulltext_sphinx'; public function test_search_backend() { diff --git a/tests/functions_user/delete_user_test.php b/tests/functions_user/delete_user_test.php index f18a8091be..a96817c67c 100644 --- a/tests/functions_user/delete_user_test.php +++ b/tests/functions_user/delete_user_test.php @@ -33,7 +33,7 @@ class phpbb_functions_user_delete_user_test extends phpbb_database_test_case $config = new \phpbb\config\config(array( 'load_online_time' => 5, - 'search_type' => '\phpbb\search\fulltext_mysql', + 'search_type' => '\phpbb\search\backend\fulltext_mysql', )); $cache = new phpbb_mock_null_cache(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); diff --git a/tests/mock/search.php b/tests/mock/search.php index f30876b4da..6aa9c52a80 100644 --- a/tests/mock/search.php +++ b/tests/mock/search.php @@ -13,15 +13,78 @@ /** */ -class phpbb_mock_search +class phpbb_mock_search implements \phpbb\search\backend\search_backend_interface { - public function __construct($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user) + public function __construct($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) { } - public function index_remove($post_ids, $poster_ids, $forum_ids) + public function get_name() + { + } + + public function get_search_query() + { + } + + public function get_common_words() + { + } + + public function get_word_length() + { + } + + public function init() + { + } + + public function split_keywords(&$keywords, $terms) + { + } + + 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) + { + } + + 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) + { + } + + public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) + { + } + + public function index_remove($post_ids, $author_ids, $forum_ids) + { + } + + public function tidy() + { + } + + public function create_index($acp_module, $u_action) + { + } + + public function delete_index($acp_module, $u_action) + { + } + + public function index_created() + { + } + + public function index_stats() + { + } + + protected function get_stats() + { + } + + public function acp() { } } - diff --git a/tests/search/mysql_test.php b/tests/search/mysql_test.php index 9ff0b7d518..b0f99ea9c2 100644 --- a/tests/search/mysql_test.php +++ b/tests/search/mysql_test.php @@ -37,8 +37,7 @@ class phpbb_search_mysql_test extends phpbb_search_common_test_case $this->db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $error = null; - $class = self::get_search_wrapper('\phpbb\search\fulltext_mysql'); - $this->search = new $class($error, $phpbb_root_path, $phpEx, null, $config, $this->db, $user, $phpbb_dispatcher); + $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_mysql'); + $this->search = new $class($auth, $config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); } } diff --git a/tests/search/native_test.php b/tests/search/native_test.php index e0b8a86f4b..e342dd21c5 100644 --- a/tests/search/native_test.php +++ b/tests/search/native_test.php @@ -33,11 +33,10 @@ class phpbb_search_native_test extends phpbb_search_test_case $this->db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $error = null; - $class = self::get_search_wrapper('\phpbb\search\fulltext_native'); + $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_native'); $config['fulltext_native_min_chars'] = 2; $config['fulltext_native_max_chars'] = 14; - $this->search = new $class($error, $phpbb_root_path, $phpEx, null, $config, $this->db, $user, $phpbb_dispatcher); + $this->search = new $class($auth, $config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); } public function keywords() diff --git a/tests/search/postgres_test.php b/tests/search/postgres_test.php index b4edd974ac..c08fb1de5d 100644 --- a/tests/search/postgres_test.php +++ b/tests/search/postgres_test.php @@ -37,8 +37,7 @@ class phpbb_search_postgres_test extends phpbb_search_common_test_case $this->db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); - $error = null; - $class = self::get_search_wrapper('\phpbb\search\fulltext_postgres'); - $this->search = new $class($error, $phpbb_root_path, $phpEx, null, $config, $this->db, $user, $phpbb_dispatcher); + $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_postgres'); + $this->search = new $class($auth, $config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); } } From 5805a6906ecf823abe9ca208b8e925cae09f54e3 Mon Sep 17 00:00:00 2001 From: rubencm Date: Sun, 16 Dec 2018 14:52:24 +0000 Subject: [PATCH 02/22] [ticket/15540] Pass variable by reference PHPBB3-15540 --- phpBB/phpbb/search/backend/fulltext_sphinx.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index 9715754a01..7a21878303 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -751,7 +751,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - 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) + 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 = ''; From cc0d4efc8fae0f6cbcc982ad0888472ed00627f4 Mon Sep 17 00:00:00 2001 From: rubencm Date: Thu, 24 Oct 2019 21:59:27 +0000 Subject: [PATCH 03/22] [ticket/15540] Remove delete_index and move create_index to fulltext_native PHPBB3-15540 --- phpBB/includes/acp/acp_search.php | 129 ++---------------- .../phpbb/search/backend/fulltext_native.php | 74 +++++++++- .../backend/search_backend_interface.php | 3 +- 3 files changed, 82 insertions(+), 124 deletions(-) diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 2bdd456967..d136994ba9 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -300,55 +300,12 @@ class acp_search switch ($action) { case 'delete': - if (method_exists($this->search, 'delete_index')) + // pass a reference to myself so the $search object can make use of save_state() and attributes + if ($error = $this->search->delete_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=delete&hash=" . generate_link_hash('acp_search'), false))) { - // pass a reference to myself so the $search object can make use of save_state() and attributes - if ($error = $this->search->delete_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=delete&hash=" . generate_link_hash('acp_search'), false))) - { - $this->state = array(''); - $this->save_state(); - trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); - } - } - else - { - $starttime = microtime(true); - $row_count = 0; - while (still_on_time() && $post_counter <= $this->max_post_id) - { - $sql = 'SELECT post_id, poster_id, forum_id - FROM ' . POSTS_TABLE . ' - WHERE post_id >= ' . (int) ($post_counter + 1) . ' - AND post_id <= ' . (int) ($post_counter + $this->batch_size); - $result = $db->sql_query($sql); - - $ids = $posters = $forum_ids = array(); - while ($row = $db->sql_fetchrow($result)) - { - $ids[] = $row['post_id']; - $posters[] = $row['poster_id']; - $forum_ids[] = $row['forum_id']; - } - $db->sql_freeresult($result); - $row_count += count($ids); - - if (count($ids)) - { - $this->search->index_remove($ids, $posters, $forum_ids); - } - - $post_counter += $this->batch_size; - } - // save the current state + $this->state = array(''); $this->save_state(); - - if ($post_counter <= $this->max_post_id) - { - $totaltime = microtime(true) - $starttime; - $rows_per_second = $row_count / $totaltime; - meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search'))); - trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_DELETE_REDIRECT_RATE', $rows_per_second)); - } + trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); } $this->search->tidy(); @@ -361,82 +318,12 @@ class acp_search break; case 'create': - if (method_exists($this->search, 'create_index')) + // pass a reference to acp_search so the $search object can make use of save_state() and attributes + if ($error = $this->search->create_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=create", false))) { - // pass a reference to acp_search so the $search object can make use of save_state() and attributes - if ($error = $this->search->create_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=create", false))) - { - $this->state = array(''); - $this->save_state(); - trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); - } - } - else - { - $sql = 'SELECT forum_id, enable_indexing - FROM ' . FORUMS_TABLE; - $result = $db->sql_query($sql, 3600); - - while ($row = $db->sql_fetchrow($result)) - { - $forums[$row['forum_id']] = (bool) $row['enable_indexing']; - } - $db->sql_freeresult($result); - - $starttime = microtime(true); - $row_count = 0; - while (still_on_time() && $post_counter <= $this->max_post_id) - { - $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id - FROM ' . POSTS_TABLE . ' - WHERE post_id >= ' . (int) ($post_counter + 1) . ' - AND post_id <= ' . (int) ($post_counter + $this->batch_size); - $result = $db->sql_query($sql); - - $buffer = $db->sql_buffer_nested_transactions(); - - if ($buffer) - { - $rows = $db->sql_fetchrowset($result); - $rows[] = false; // indicate end of array for while loop below - - $db->sql_freeresult($result); - } - - $i = 0; - while ($row = ($buffer ? $rows[$i++] : $db->sql_fetchrow($result))) - { - // Indexing enabled for this forum - if (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']]) - { - $this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); - } - $row_count++; - } - if (!$buffer) - { - $db->sql_freeresult($result); - } - - $post_counter += $this->batch_size; - } - // save the current state + $this->state = array(''); $this->save_state(); - - // pretend the number of posts was as big as the number of ids we indexed so far - // just an estimation as it includes deleted posts - $num_posts = $config['num_posts']; - $config['num_posts'] = min($config['num_posts'], $post_counter); - $this->search->tidy(); - $config['num_posts'] = $num_posts; - - if ($post_counter <= $this->max_post_id) - { - $totaltime = microtime(true) - $starttime; - $rows_per_second = $row_count / $totaltime; - meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search'))); - trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); - } + trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); } $this->search->tidy(); diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index b85a5ecceb..42c5bc7679 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -1667,6 +1667,78 @@ class fulltext_native extends base implements search_backend_interface $this->config->set('search_last_gc', time(), false); } + /** + * {@inheritdoc} + */ + public function create_index($acp_module, $u_action) + { + $sql = 'SELECT forum_id, enable_indexing + FROM ' . FORUMS_TABLE; + $result = $this->db->sql_query($sql, 3600); + + while ($row = $this->db->sql_fetchrow($result)) + { + $forums[$row['forum_id']] = (bool) $row['enable_indexing']; + } + $this->db->sql_freeresult($result); + + $starttime = microtime(true); + $row_count = 0; + $post_counter = $acp_module->state[2]; + while (still_on_time() && $post_counter <= $acp_module->max_post_id) + { + $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id + FROM ' . POSTS_TABLE . ' + WHERE post_id >= ' . (int) ($post_counter + 1) . ' + AND post_id <= ' . (int) ($post_counter + $acp_module->batch_size); + $result = $this->db->sql_query($sql); + + $buffer = $this->db->sql_buffer_nested_transactions(); + + if ($buffer) + { + $rows = $this->db->sql_fetchrowset($result); + $rows[] = false; // indicate end of array for while loop below + + $this->db->sql_freeresult($result); + } + + $i = 0; + while ($row = ($buffer ? $rows[$i++] : $this->db->sql_fetchrow($result))) + { + // Indexing enabled for this forum + if (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']]) + { + $this->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); + } + $row_count++; + } + if (!$buffer) + { + $this->db->sql_freeresult($result); + } + + $post_counter += $acp_module->batch_size; + } + // save the current state + $acp_module->save_state(); + + // pretend the number of posts was as big as the number of ids we indexed so far + // just an estimation as it includes deleted posts + $num_posts = $this->config['num_posts']; + $this->config['num_posts'] = min($this->config['num_posts'], $post_counter); + $this->tidy(); + $this->config['num_posts'] = $num_posts; + + if ($post_counter <= $acp_module->max_post_id) + { + $totaltime = microtime(true) - $starttime; + $rows_per_second = $row_count / $totaltime; + meta_refresh(1, $u_action); + trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); + } + } + /** * {@inheritdoc} */ @@ -1738,7 +1810,7 @@ class fulltext_native extends base implements search_backend_interface $this->user->lang['TOTAL_WORDS'] => $this->stats['total_words'], $this->user->lang['TOTAL_MATCHES'] => $this->stats['total_matches']); } - + /** * Computes the stats and store them in the $this->stats associative array */ diff --git a/phpBB/phpbb/search/backend/search_backend_interface.php b/phpBB/phpbb/search/backend/search_backend_interface.php index 24ff56a0a0..7c7b60cb12 100644 --- a/phpBB/phpbb/search/backend/search_backend_interface.php +++ b/phpBB/phpbb/search/backend/search_backend_interface.php @@ -125,8 +125,7 @@ interface search_backend_interface * * @return string|bool error string is returned incase of errors otherwise false */ - // This method isn't present in fulltext_native, because it's implementation is hardcoded in acp_search - //public function create_index($acp_module, $u_action); + public function create_index($acp_module, $u_action); /** * Drop fulltext index From 5fd2c51ca879a4374eea5597e287b7c3a1176fff Mon Sep 17 00:00:00 2001 From: rubencm Date: Sat, 15 Aug 2020 12:48:23 +0000 Subject: [PATCH 04/22] [ticket/15540] Fix tests and small fixes PHPBB3-15540 --- phpBB/develop/search_fill.php | 121 ------------------ phpBB/includes/acp/acp_search.php | 59 +++------ phpBB/install/schemas/schema_data.sql | 2 +- .../phpbb/search/backend/fulltext_native.php | 2 +- phpBB/phpbb/search/search_backend_factory.php | 13 +- phpBB/search.php | 2 +- tests/content_visibility/delete_post_test.php | 5 + tests/functions_user/delete_user_test.php | 7 + 8 files changed, 43 insertions(+), 168 deletions(-) delete mode 100644 phpBB/develop/search_fill.php diff --git a/phpBB/develop/search_fill.php b/phpBB/develop/search_fill.php deleted file mode 100644 index 1dcdcdace6..0000000000 --- a/phpBB/develop/search_fill.php +++ /dev/null @@ -1,121 +0,0 @@ -session_begin(); -$auth->acl($user->data); -$user->setup(); - -$search_type = $config['search_type']; - -if (!class_exists($search_type)) -{ - trigger_error('NO_SUCH_SEARCH_MODULE'); -} - -$search = new $search_type($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); - -print "\n\n"; - -// -// Fetch a batch of posts_text entries -// -$sql = "SELECT COUNT(*) as total, MAX(post_id) as max_post_id - FROM ". POSTS_TABLE; -if ( !($result = $db->sql_query($sql)) ) -{ - $error = $db->sql_error(); - die("Couldn't get maximum post ID :: " . $sql . " :: " . $error['message']); -} - -$max_post_id = $db->sql_fetchrow($result); - -$totalposts = $max_post_id['total']; -$max_post_id = $max_post_id['max_post_id']; - -$postcounter = (!isset($HTTP_GET_VARS['batchstart'])) ? 0 : $HTTP_GET_VARS['batchstart']; - -$batchsize = 200; // Process this many posts per loop -$batchcount = 0; -for(;$postcounter <= $max_post_id; $postcounter += $batchsize) -{ - $batchstart = $postcounter + 1; - $batchend = $postcounter + $batchsize; - $batchcount++; - - $sql = "SELECT * - FROM " . POSTS_TABLE . " - WHERE post_id - BETWEEN $batchstart - AND $batchend"; - if( !($result = $db->sql_query($sql)) ) - { - $error = $db->sql_error(); - die("Couldn't get post_text :: " . $sql . " :: " . $error['message']); - } - - $rowset = $db->sql_fetchrowset($result); - $db->sql_freeresult($result); - - $post_rows = count($rowset); - - if( $post_rows ) - { - - // $sql = "LOCK TABLES ".POST_TEXT_TABLE." WRITE"; - // $result = $db->sql_query($sql); - print "\n

\nRestart from posting $batchstart
\n"; - - // For every post in the batch: - for($post_nr = 0; $post_nr < $post_rows; $post_nr++ ) - { - print "."; - flush(); - - $post_id = $rowset[$post_nr]['post_id']; - - $search->index('post', $rowset[$post_nr]['post_id'], $rowset[$post_nr]['post_text'], $rowset[$post_nr]['post_subject'], $rowset[$post_nr]['poster_id']); - } - // $sql = "UNLOCK TABLES"; - // $result = $db->sql_query($sql); - - } -} - -print "
Removing common words (words that appear in more than 50% of the posts)
\n"; -flush(); -$search->tidy(); -print "Removed words that where too common.
"; - -echo "
Done"; - -?> - - - diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index d136994ba9..deaa28e743 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -149,66 +149,49 @@ class acp_search $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH'); } - if (isset($cfg_array['search_type']) && in_array($cfg_array['search_type'], $search_types, true) && ($cfg_array['search_type'] != $config['search_type'])) + if (isset($cfg_array['search_type']) && ($cfg_array['search_type'] != $config['search_type'])) { - $search = null; - $error = false; - - if (!$this->init_search($cfg_array['search_type'], $search, $error)) + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get($cfg_array['search_type']); + if (confirm_box(true)) { - if (confirm_box(true)) + if (!method_exists($search, 'init') || !($error = $search->init())) { - if (!method_exists($search, 'init') || !($error = $search->init())) - { - $config->set('search_type', $cfg_array['search_type']); + $config->set('search_type', $cfg_array['search_type']); - if (!$updated) - { - $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH'); - } - $extra_message = '
' . $user->lang['SWITCHED_SEARCH_BACKEND'] . '
» ' . $user->lang['GO_TO_SEARCH_INDEX'] . ''; - } - else + if (!$updated) { - trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH'); } + $extra_message = '
' . $user->lang['SWITCHED_SEARCH_BACKEND'] . '
» ' . $user->lang['GO_TO_SEARCH_INDEX'] . ''; } else { - confirm_box(false, $user->lang['CONFIRM_SEARCH_BACKEND'], build_hidden_fields(array( - 'i' => $id, - 'mode' => $mode, - 'submit' => true, - 'updated' => $updated, - 'config' => array('search_type' => $cfg_array['search_type']), - ))); + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); } } else { - trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + confirm_box(false, $user->lang['CONFIRM_SEARCH_BACKEND'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'submit' => true, + 'updated' => $updated, + 'config' => array('search_type' => $cfg_array['search_type']), + ))); } } - $search = null; - $error = false; - if (!$this->init_search($config['search_type'], $search, $error)) + if ($updated) { - if ($updated) + if (method_exists($search, 'config_updated')) { - if (method_exists($search, 'config_updated')) + if ($search->config_updated()) { - if ($search->config_updated()) - { - trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); - } + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); } } } - else - { - trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); - } trigger_error($user->lang['CONFIG_UPDATED'] . $extra_message . adm_back_link($this->u_action)); } diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 9fa5b2524e..b835dff45a 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -275,7 +275,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_block_size' INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_gc', '7200'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_interval', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_store_results', '1800'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_type', '\phpbb\search\backend\fulltext_native'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_type', 'phpbb\search\backend\fulltext_native'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_allow_deny', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_allow_empty_referer', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_downloads', '0'); diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index 42c5bc7679..99f47f8b9c 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -1735,7 +1735,7 @@ class fulltext_native extends base implements search_backend_interface $totaltime = microtime(true) - $starttime; $rows_per_second = $row_count / $totaltime; meta_refresh(1, $u_action); - trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); + trigger_error($this->user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $this->user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); } } diff --git a/phpBB/phpbb/search/search_backend_factory.php b/phpBB/phpbb/search/search_backend_factory.php index 636c8f823f..ab103cae73 100644 --- a/phpBB/phpbb/search/search_backend_factory.php +++ b/phpBB/phpbb/search/search_backend_factory.php @@ -15,24 +15,25 @@ namespace phpbb\search; use phpbb\config\config; use phpbb\di\service_collection; +use phpbb\search\backend\search_backend_interface; class search_backend_factory { /** - * @var \phpbb\config\config + * @var config */ protected $config; /** - * @var \phpbb\di\service_collection + * @var service_collection */ protected $search_backends; /** * Constructor * - * @param \phpbb\config\config $config - * @param \phpbb\di\service_collection $search_backends + * @param config $config + * @param service_collection $search_backends */ public function __construct(config $config, service_collection $search_backends) { @@ -45,7 +46,7 @@ class search_backend_factory * * @param string $class * - * @return \phpbb\search\backend\search_backend_interface + * @return search_backend_interface */ public function get($class) { @@ -55,7 +56,7 @@ class search_backend_factory /** * Obtains active search backend * - * @return \phpbb\search\backend\search_backend_interface + * @return search_backend_interface */ public function get_active() { diff --git a/phpBB/search.php b/phpBB/search.php index bd7532fc07..3eac7391ed 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -295,7 +295,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) // Select which method we'll use to obtain the post_id or topic_id information $search_backend_factory = $phpbb_container->get('search.backend_factory'); - $search = $search_backend_factory->get_search(); + $search = $search_backend_factory->get_active(); // let the search module split up the keywords if ($keywords) diff --git a/tests/content_visibility/delete_post_test.php b/tests/content_visibility/delete_post_test.php index 5a646bb57e..009a817766 100644 --- a/tests/content_visibility/delete_post_test.php +++ b/tests/content_visibility/delete_post_test.php @@ -323,6 +323,11 @@ class phpbb_content_visibility_delete_post_test extends phpbb_database_test_case // Works as a workaround for tests $phpbb_container->set('attachment.manager', $attachment_delete); + $search_backend = $this->createMock(\phpbb\search\backend\search_backend_interface::class); + $search_backend_factory = $this->createMock(\phpbb\search\search_backend_factory::class); + $search_backend_factory->method('get_active')->willReturn($search_backend); + $phpbb_container->set('search.backend_factory', $search_backend_factory); + delete_post($forum_id, $topic_id, $post_id, $data, $is_soft, $reason); $result = $db->sql_query('SELECT post_id, post_visibility, post_delete_reason diff --git a/tests/functions_user/delete_user_test.php b/tests/functions_user/delete_user_test.php index a96817c67c..76a0aa50ce 100644 --- a/tests/functions_user/delete_user_test.php +++ b/tests/functions_user/delete_user_test.php @@ -54,6 +54,13 @@ class phpbb_functions_user_delete_user_test extends phpbb_database_test_case 'auth.provider_collection', $provider_collection ); + + $search_backend = $this->createMock(\phpbb\search\backend\search_backend_interface::class); + $search_backend_factory = $this->createMock(\phpbb\search\search_backend_factory::class); + $search_backend_factory->method('get_active')->willReturn($search_backend); + $phpbb_container->set('search.backend_factory', $search_backend_factory); + + $phpbb_container->setParameter('tables.auth_provider_oauth_token_storage', 'phpbb_oauth_tokens'); $phpbb_container->setParameter('tables.auth_provider_oauth_states', 'phpbb_oauth_states'); $phpbb_container->setParameter('tables.auth_provider_oauth_account_assoc', 'phpbb_oauth_accounts'); From ee9ea98a018aa64178d041608dc55b1ee2875f96 Mon Sep 17 00:00:00 2001 From: rubencm Date: Sat, 15 Aug 2020 12:56:02 +0000 Subject: [PATCH 05/22] [ticket/15540] Remove unused variable PHPBB3-15540 --- phpBB/includes/acp/acp_search.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index deaa28e743..a01ebaa606 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -265,8 +265,6 @@ class acp_search $this->state[0] = $request->variable('search_type', ''); } - $error = false; - $search_backend_factory = $phpbb_container->get('search.backend_factory'); $this->search = $search_backend_factory->get($this->state[0]); From 1bc9cbefb2e4ca30744002c4e8de0fab15920def Mon Sep 17 00:00:00 2001 From: rubencm Date: Sat, 15 Aug 2020 13:05:54 +0000 Subject: [PATCH 06/22] [ticket/15540] Fix tests PHPBB3-15540 --- .../default/container/services_search.yml | 3 - phpBB/includes/mcp/mcp_main.php | 2 +- phpBB/includes/mcp/mcp_topic.php | 2 +- phpBB/phpbb/search/backend/fulltext_mysql.php | 10 +-- .../phpbb/search/backend/fulltext_native.php | 35 ++++---- .../search/backend/fulltext_postgres.php | 23 ++--- .../phpbb/search/backend/fulltext_sphinx.php | 25 +++--- tests/content_visibility/delete_post_test.php | 2 +- tests/functional/search/base.php | 2 +- tests/functional/search/mysql_test.php | 2 +- tests/functional/search/native_test.php | 2 +- tests/functional/search/postgres_test.php | 2 +- tests/functional/search/sphinx_test.php | 2 +- tests/mock/search.php | 90 ------------------- tests/search/mysql_test.php | 2 +- tests/search/native_test.php | 2 +- tests/search/postgres_test.php | 2 +- 17 files changed, 62 insertions(+), 146 deletions(-) delete mode 100644 tests/mock/search.php diff --git a/phpBB/config/default/container/services_search.yml b/phpBB/config/default/container/services_search.yml index 0ceb7e06c3..0ec01e187e 100644 --- a/phpBB/config/default/container/services_search.yml +++ b/phpBB/config/default/container/services_search.yml @@ -4,7 +4,6 @@ services: search.fulltext.native: class: phpbb\search\backend\fulltext_native arguments: - - '@auth' - '@config' - '@dbal.conn' - '@dispatcher' @@ -17,7 +16,6 @@ services: search.fulltext.mysql: class: phpbb\search\backend\fulltext_mysql arguments: - - '@auth' - '@config' - '@dbal.conn' - '@dispatcher' @@ -30,7 +28,6 @@ services: search.fulltext.postgres: class: phpbb\search\backend\fulltext_postgres arguments: - - '@auth' - '@config' - '@dbal.conn' - '@dispatcher' diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 966be7cd91..5d61ac640d 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -1330,7 +1330,7 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', */ function mcp_fork_topic($topic_ids) { - global $auth, $user, $db, $template, $config; + global $auth, $user, $db, $template, $config, $phpbb_container; global $phpEx, $phpbb_root_path, $phpbb_log, $request, $phpbb_dispatcher; if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 3c37fa4d66..0aa6160831 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -428,7 +428,7 @@ function mcp_topic_view($id, $mode, $action) */ function split_topic($action, $topic_id, $to_forum_id, $subject) { - global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config, $phpbb_log, $request; + global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config, $phpbb_log, $request, $phpbb_container; $post_id_list = $request->variable('post_id_list', array(0)); $forum_id = $request->variable('forum_id', 0); diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index f71c9d21e9..2da5ab2221 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -78,16 +78,14 @@ class fulltext_mysql extends base implements search_backend_interface * Constructor * Creates a new \phpbb\search\backend\fulltext_mysql, 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 $db Database object + * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object * @param \phpbb\user $user User object - * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object + * @param string $phpbb_root_path Relative path to phpBB root + * @param string $phpEx PHP file extension */ - public function __construct($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) + public function __construct($config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) { $this->config = $config; $this->db = $db; diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index 99f47f8b9c..7341c77ba1 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -13,6 +13,11 @@ namespace phpbb\search\backend; +use phpbb\config\config; +use phpbb\db\driver\driver_interface; +use phpbb\event\dispatcher_interface; +use phpbb\user; + /** * phpBB's own db driven fulltext search, version 2 */ @@ -83,41 +88,39 @@ class fulltext_native extends base implements search_backend_interface /** * Config object - * @var \phpbb\config\config + * @var config */ protected $config; /** * Database connection - * @var \phpbb\db\driver\driver_interface + * @var driver_interface */ protected $db; /** * phpBB event dispatcher object - * @var \phpbb\event\dispatcher_interface + * @var dispatcher_interface */ protected $phpbb_dispatcher; /** * User object - * @var \phpbb\user + * @var user */ protected $user; /** - * 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 string $phpbb_root_path phpBB root path - * @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 $db Database object - * @param \phpbb\user $user User object - * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object - */ - public function __construct($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) + * Initialises the fulltext_native search backend with min/max word length + * + * @param config $config Config object + * @param driver_interface $db Database object + * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object + * @param user $user User object + * @param string $phpbb_root_path phpBB root path + * @param string $phpEx PHP file extension + */ + public function __construct($config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) { $this->config = $config; $this->db = $db; diff --git a/phpBB/phpbb/search/backend/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php index b0652a361d..087f76559b 100644 --- a/phpBB/phpbb/search/backend/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -13,6 +13,11 @@ namespace phpbb\search\backend; +use phpbb\config\config; +use phpbb\db\driver\driver_interface; +use phpbb\event\dispatcher_interface; +use phpbb\user; + /** * Fulltext search for PostgreSQL */ @@ -45,7 +50,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * Config object - * @var \phpbb\config\config + * @var config */ protected $config; @@ -57,13 +62,13 @@ class fulltext_postgres extends base implements search_backend_interface /** * phpBB event dispatcher object - * @var \phpbb\event\dispatcher_interface + * @var dispatcher_interface */ protected $phpbb_dispatcher; /** * User object - * @var \phpbb\user + * @var user */ protected $user; @@ -91,16 +96,14 @@ class fulltext_postgres extends base implements search_backend_interface * Constructor * Creates a new \phpbb\search\backend\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 config $config Config object + * @param driver_interface $db Database object + * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object + * @param user $user User object * @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($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) + public function __construct($config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) { $this->config = $config; $this->db = $db; diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index 7a21878303..4212eddfb1 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -13,6 +13,11 @@ namespace phpbb\search\backend; +use phpbb\auth\auth; +use phpbb\config\config; +use phpbb\event\dispatcher_interface; +use phpbb\user; + define('SPHINX_MAX_MATCHES', 20000); define('SPHINX_CONNECT_RETRIES', 3); define('SPHINX_CONNECT_WAIT_TIME', 300); @@ -67,13 +72,13 @@ class fulltext_sphinx implements search_backend_interface /** * Auth object - * @var \phpbb\auth\auth + * @var auth */ protected $auth; /** * Config object - * @var \phpbb\config\config + * @var config */ protected $config; @@ -97,13 +102,13 @@ class fulltext_sphinx implements search_backend_interface /** * phpBB event dispatcher object - * @var \phpbb\event\dispatcher_interface + * @var dispatcher_interface */ protected $phpbb_dispatcher; /** * User object - * @var \phpbb\user + * @var user */ protected $user; @@ -124,14 +129,14 @@ class fulltext_sphinx implements search_backend_interface * Constructor * Creates a new \phpbb\search\backend\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 auth $auth Auth object + * @param config $config Config object + * @param $db + * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object + * @param user $user User object * @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 + * @throws \Exception */ public function __construct($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) { diff --git a/tests/content_visibility/delete_post_test.php b/tests/content_visibility/delete_post_test.php index 009a817766..bba1281551 100644 --- a/tests/content_visibility/delete_post_test.php +++ b/tests/content_visibility/delete_post_test.php @@ -292,7 +292,7 @@ class phpbb_content_visibility_delete_post_test extends phpbb_database_test_case $config = new \phpbb\config\config(array( 'num_posts' => 3, 'num_topics' => 1, - 'search_type' => 'phpbb_mock_search', + 'search_type' => 'foo', )); $cache = new phpbb_mock_cache; $db = $this->new_dbal(); diff --git a/tests/functional/search/base.php b/tests/functional/search/base.php index 0558c8e8de..b849724bf9 100644 --- a/tests/functional/search/base.php +++ b/tests/functional/search/base.php @@ -38,7 +38,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case $this->login(); $this->admin_login(); - $this->create_search_index('\phpbb\search\backend\fulltext_native'); + $this->create_search_index('phpbb\search\backend\fulltext_native'); $post = $this->create_topic(2, 'Test Topic 1 foosubject', 'This is a test topic posted by the barsearch testing framework.'); diff --git a/tests/functional/search/mysql_test.php b/tests/functional/search/mysql_test.php index 43e5c5cab2..50b2d6487b 100644 --- a/tests/functional/search/mysql_test.php +++ b/tests/functional/search/mysql_test.php @@ -18,7 +18,7 @@ require_once __DIR__ . '/base.php'; */ class phpbb_functional_search_mysql_test extends phpbb_functional_search_base { - protected $search_backend = '\phpbb\search\backend\fulltext_mysql'; + protected $search_backend = 'phpbb\search\backend\fulltext_mysql'; protected function create_search_index($backend = null) { diff --git a/tests/functional/search/native_test.php b/tests/functional/search/native_test.php index f95ce3184d..5b8d8f2206 100644 --- a/tests/functional/search/native_test.php +++ b/tests/functional/search/native_test.php @@ -18,5 +18,5 @@ require_once __DIR__ . '/base.php'; */ class phpbb_functional_search_native_test extends phpbb_functional_search_base { - protected $search_backend = '\phpbb\search\backend\fulltext_native'; + protected $search_backend = 'phpbb\search\backend\fulltext_native'; } diff --git a/tests/functional/search/postgres_test.php b/tests/functional/search/postgres_test.php index ae8f717232..4389705d66 100644 --- a/tests/functional/search/postgres_test.php +++ b/tests/functional/search/postgres_test.php @@ -18,6 +18,6 @@ require_once __DIR__ . '/base.php'; */ class phpbb_functional_search_postgres_test extends phpbb_functional_search_base { - protected $search_backend = '\phpbb\search\backend\fulltext_postgres'; + protected $search_backend = 'phpbb\search\backend\fulltext_postgres'; } diff --git a/tests/functional/search/sphinx_test.php b/tests/functional/search/sphinx_test.php index 6a8907ed03..6e42da0e86 100644 --- a/tests/functional/search/sphinx_test.php +++ b/tests/functional/search/sphinx_test.php @@ -18,7 +18,7 @@ require_once __DIR__ . '/base.php'; */ class phpbb_functional_search_sphinx_test extends phpbb_functional_search_base { - protected $search_backend = '\phpbb\search\backend\fulltext_sphinx'; + protected $search_backend = 'phpbb\search\backend\fulltext_sphinx'; public function test_search_backend() { diff --git a/tests/mock/search.php b/tests/mock/search.php deleted file mode 100644 index 6aa9c52a80..0000000000 --- a/tests/mock/search.php +++ /dev/null @@ -1,90 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -/** -*/ -class phpbb_mock_search implements \phpbb\search\backend\search_backend_interface -{ - - public function __construct($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) - { - } - - public function get_name() - { - } - - public function get_search_query() - { - } - - public function get_common_words() - { - } - - public function get_word_length() - { - } - - public function init() - { - } - - public function split_keywords(&$keywords, $terms) - { - } - - 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) - { - } - - 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) - { - } - - public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) - { - } - - public function index_remove($post_ids, $author_ids, $forum_ids) - { - } - - public function tidy() - { - } - - public function create_index($acp_module, $u_action) - { - } - - public function delete_index($acp_module, $u_action) - { - } - - public function index_created() - { - } - - public function index_stats() - { - } - - protected function get_stats() - { - } - - public function acp() - { - } -} diff --git a/tests/search/mysql_test.php b/tests/search/mysql_test.php index b0f99ea9c2..75f534c328 100644 --- a/tests/search/mysql_test.php +++ b/tests/search/mysql_test.php @@ -38,6 +38,6 @@ class phpbb_search_mysql_test extends phpbb_search_common_test_case $this->db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_mysql'); - $this->search = new $class($auth, $config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); + $this->search = new $class($config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); } } diff --git a/tests/search/native_test.php b/tests/search/native_test.php index e342dd21c5..652206e1b4 100644 --- a/tests/search/native_test.php +++ b/tests/search/native_test.php @@ -36,7 +36,7 @@ class phpbb_search_native_test extends phpbb_search_test_case $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_native'); $config['fulltext_native_min_chars'] = 2; $config['fulltext_native_max_chars'] = 14; - $this->search = new $class($auth, $config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); + $this->search = new $class($config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); } public function keywords() diff --git a/tests/search/postgres_test.php b/tests/search/postgres_test.php index c08fb1de5d..5f2466a76b 100644 --- a/tests/search/postgres_test.php +++ b/tests/search/postgres_test.php @@ -38,6 +38,6 @@ class phpbb_search_postgres_test extends phpbb_search_common_test_case $this->db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_postgres'); - $this->search = new $class($auth, $config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); + $this->search = new $class($config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); } } From f2d5f31f99a69ddfccb23aa5858f6e55f7d72e4b Mon Sep 17 00:00:00 2001 From: rubencm Date: Sat, 15 Aug 2020 13:52:09 +0000 Subject: [PATCH 07/22] [ticket/15540] Remove argument PHPBB3-15540 --- phpBB/install/convert/convertor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/install/convert/convertor.php b/phpBB/install/convert/convertor.php index 54ec85fd21..ab87243952 100644 --- a/phpBB/install/convert/convertor.php +++ b/phpBB/install/convert/convertor.php @@ -224,7 +224,7 @@ class convertor trigger_error('NO_SUCH_SEARCH_MODULE'); } - $convert->fulltext_search = new $search_type($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); + $convert->fulltext_search = new $search_type($config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx); $message_parser = new \parse_message(); From a56bfdee8ae7034cb834873800d23e29d76b0223 Mon Sep 17 00:00:00 2001 From: rubencm Date: Wed, 19 Aug 2020 05:08:39 +0000 Subject: [PATCH 08/22] [ticket/15540] Send hash PHPBB3-15540 --- phpBB/includes/acp/acp_search.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index a01ebaa606..f03439d265 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -300,7 +300,7 @@ class acp_search case 'create': // pass a reference to acp_search so the $search object can make use of save_state() and attributes - if ($error = $this->search->create_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=create", false))) + if ($error = $this->search->create_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=create&hash=" . generate_link_hash('acp_search'), false))) { $this->state = array(''); $this->save_state(); From d78896d581ea566d3727bce916218f4bee9d2e34 Mon Sep 17 00:00:00 2001 From: rubencm Date: Wed, 19 Aug 2020 16:41:42 +0000 Subject: [PATCH 09/22] [ticket/15540] Fix post counter PHPBB3-15540 --- phpBB/includes/acp/acp_search.php | 2 -- phpBB/phpbb/search/backend/fulltext_native.php | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index f03439d265..a2f3b97186 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -274,8 +274,6 @@ class acp_search $this->max_post_id = $this->get_max_post_id(); - $post_counter = (isset($this->state[2])) ? $this->state[2] : 0; - $this->state[2] = &$post_counter; $this->save_state(); switch ($action) diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index 7341c77ba1..538498f3b6 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -1687,7 +1687,8 @@ class fulltext_native extends base implements search_backend_interface $starttime = microtime(true); $row_count = 0; - $post_counter = $acp_module->state[2]; + + $post_counter = &$acp_module->state[2]; while (still_on_time() && $post_counter <= $acp_module->max_post_id) { $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id @@ -1723,6 +1724,7 @@ class fulltext_native extends base implements search_backend_interface $post_counter += $acp_module->batch_size; } + // save the current state $acp_module->save_state(); From 9b8ddc269872f6bc42f95c3b3957df5028338ddb Mon Sep 17 00:00:00 2001 From: rubencm Date: Sun, 30 Aug 2020 22:31:17 +0000 Subject: [PATCH 10/22] [ticket/15540] Move create_index and add delete_index to base PHPBB3-15540 --- phpBB/phpbb/search/backend/base.php | 120 ++++++++++++++++++ .../phpbb/search/backend/fulltext_native.php | 74 ----------- 2 files changed, 120 insertions(+), 74 deletions(-) diff --git a/phpBB/phpbb/search/backend/base.php b/phpBB/phpbb/search/backend/base.php index 281e4da3a8..019226a8cc 100644 --- a/phpBB/phpbb/search/backend/base.php +++ b/phpBB/phpbb/search/backend/base.php @@ -283,4 +283,124 @@ abstract class base WHERE search_time < ' . (time() - (int) $config['search_store_results']); $db->sql_query($sql); } + + /** + * {@inheritdoc} + */ + public function create_index($acp_module, $u_action) + { + $sql = 'SELECT forum_id, enable_indexing + FROM ' . FORUMS_TABLE; + $result = $this->db->sql_query($sql, 3600); + + while ($row = $this->db->sql_fetchrow($result)) + { + $forums[$row['forum_id']] = (bool) $row['enable_indexing']; + } + $this->db->sql_freeresult($result); + + $starttime = microtime(true); + $row_count = 0; + + $post_counter = &$acp_module->state[2]; + while (still_on_time() && $post_counter <= $acp_module->max_post_id) + { + $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id + FROM ' . POSTS_TABLE . ' + WHERE post_id >= ' . (int) ($post_counter + 1) . ' + AND post_id <= ' . (int) ($post_counter + $acp_module->batch_size); + $result = $this->db->sql_query($sql); + + $buffer = $this->db->sql_buffer_nested_transactions(); + + if ($buffer) + { + $rows = $this->db->sql_fetchrowset($result); + $rows[] = false; // indicate end of array for while loop below + + $this->db->sql_freeresult($result); + } + + $i = 0; + while ($row = ($buffer ? $rows[$i++] : $this->db->sql_fetchrow($result))) + { + // Indexing enabled for this forum + if (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']]) + { + $this->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); + } + $row_count++; + } + if (!$buffer) + { + $this->db->sql_freeresult($result); + } + + $post_counter += $acp_module->batch_size; + } + + // save the current state + $acp_module->save_state(); + + // pretend the number of posts was as big as the number of ids we indexed so far + // just an estimation as it includes deleted posts + $num_posts = $this->config['num_posts']; + $this->config['num_posts'] = min($this->config['num_posts'], $post_counter); + $this->tidy(); + $this->config['num_posts'] = $num_posts; + + if ($post_counter <= $acp_module->max_post_id) + { + $totaltime = microtime(true) - $starttime; + $rows_per_second = $row_count / $totaltime; + meta_refresh(1, $u_action); + trigger_error($this->user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $this->user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); + } + } + + /** + * {@inheritdoc} + */ + public function delete_index($acp_module, $u_action) + { + $starttime = microtime(true); + $row_count = 0; + $post_counter = &$acp_module->state[2]; + while (still_on_time() && $post_counter <= $acp_module->max_post_id) + { + $sql = 'SELECT post_id, poster_id, forum_id + FROM ' . POSTS_TABLE . ' + WHERE post_id >= ' . (int) ($post_counter + 1) . ' + AND post_id <= ' . (int) ($post_counter + $acp_module->batch_size); + $result = $this->db->sql_query($sql); + + $ids = $posters = $forum_ids = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $ids[] = $row['post_id']; + $posters[] = $row['poster_id']; + $forum_ids[] = $row['forum_id']; + } + $db->sql_freeresult($result); + $row_count += count($ids); + + if (count($ids)) + { + $this->index_remove($ids, $posters, $forum_ids); + } + + $post_counter += $acp_module->batch_size; + } + + // save the current state + $acp_module->save_state(); + + if ($post_counter <= $acp_module->max_post_id) + { + $totaltime = microtime(true) - $starttime; + $rows_per_second = $row_count / $totaltime; + meta_refresh(1, append_sid($u_action)); + trigger_error($this->user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter) . $this->user->lang('SEARCH_INDEX_DELETE_REDIRECT_RATE', $rows_per_second)); + } + } } diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index 538498f3b6..6bf3224fed 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -1670,80 +1670,6 @@ class fulltext_native extends base implements search_backend_interface $this->config->set('search_last_gc', time(), false); } - /** - * {@inheritdoc} - */ - public function create_index($acp_module, $u_action) - { - $sql = 'SELECT forum_id, enable_indexing - FROM ' . FORUMS_TABLE; - $result = $this->db->sql_query($sql, 3600); - - while ($row = $this->db->sql_fetchrow($result)) - { - $forums[$row['forum_id']] = (bool) $row['enable_indexing']; - } - $this->db->sql_freeresult($result); - - $starttime = microtime(true); - $row_count = 0; - - $post_counter = &$acp_module->state[2]; - while (still_on_time() && $post_counter <= $acp_module->max_post_id) - { - $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id - FROM ' . POSTS_TABLE . ' - WHERE post_id >= ' . (int) ($post_counter + 1) . ' - AND post_id <= ' . (int) ($post_counter + $acp_module->batch_size); - $result = $this->db->sql_query($sql); - - $buffer = $this->db->sql_buffer_nested_transactions(); - - if ($buffer) - { - $rows = $this->db->sql_fetchrowset($result); - $rows[] = false; // indicate end of array for while loop below - - $this->db->sql_freeresult($result); - } - - $i = 0; - while ($row = ($buffer ? $rows[$i++] : $this->db->sql_fetchrow($result))) - { - // Indexing enabled for this forum - if (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']]) - { - $this->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); - } - $row_count++; - } - if (!$buffer) - { - $this->db->sql_freeresult($result); - } - - $post_counter += $acp_module->batch_size; - } - - // save the current state - $acp_module->save_state(); - - // pretend the number of posts was as big as the number of ids we indexed so far - // just an estimation as it includes deleted posts - $num_posts = $this->config['num_posts']; - $this->config['num_posts'] = min($this->config['num_posts'], $post_counter); - $this->tidy(); - $this->config['num_posts'] = $num_posts; - - if ($post_counter <= $acp_module->max_post_id) - { - $totaltime = microtime(true) - $starttime; - $rows_per_second = $row_count / $totaltime; - meta_refresh(1, $u_action); - trigger_error($this->user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $this->user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); - } - } - /** * {@inheritdoc} */ From 53dce77b493f12e30a7ea6c242c1034442bdc4a5 Mon Sep 17 00:00:00 2001 From: rubencm Date: Sun, 30 Aug 2020 22:40:43 +0000 Subject: [PATCH 11/22] [ticket/15540] More fixes PHPBB3-15540 --- .../install_data/task/create_search_index.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/phpBB/phpbb/install/module/install_data/task/create_search_index.php b/phpBB/phpbb/install/module/install_data/task/create_search_index.php index b673367944..ce74b220d8 100644 --- a/phpBB/phpbb/install/module/install_data/task/create_search_index.php +++ b/phpBB/phpbb/install/module/install_data/task/create_search_index.php @@ -23,7 +23,7 @@ use phpbb\install\helper\container_factory; use phpbb\install\helper\database; use phpbb\install\helper\iohandler\iohandler_interface; use phpbb\install\sequential_task; -use phpbb\search\fulltext_native; +use phpbb\search\backend\fulltext_native; use phpbb\user; class create_search_index extends database_task @@ -127,16 +127,14 @@ class create_search_index extends database_task $this->posts_table = $container->get_parameter('tables.posts'); - $this->error = false; + // Esto se cargara por servicio abajo $this->search_indexer = new fulltext_native( - $this->error, - $this->phpbb_root_path, - $this->php_ext, - $this->auth, $this->config, $this->db, + $this->phpbb_dispatcher, $this->user, - $this->phpbb_dispatcher + $this->phpbb_root_path, + $this->php_ext ); parent::__construct($this->conn, $iohandler, true); @@ -150,6 +148,7 @@ class create_search_index extends database_task // Make sure fulltext native load update is set $this->config->set('fulltext_native_load_upd', 1); + // TODO: Replace this with create_index() when it don't depend on acp try { $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id FROM ' . $this->posts_table; From 911a31d898c86e612f15315efc27faf9349ac33d Mon Sep 17 00:00:00 2001 From: rubencm Date: Mon, 22 Mar 2021 16:57:40 +0100 Subject: [PATCH 12/22] [ticket/15540] Add types and phpdoc PHPBB3-15540 --- .../{v330 => v400}/search_backend_update.php | 28 ++++-- phpBB/phpbb/search/backend/base.php | 96 +++++++++---------- phpBB/phpbb/search/backend/fulltext_mysql.php | 51 +++++----- .../phpbb/search/backend/fulltext_native.php | 6 +- .../search/backend/fulltext_postgres.php | 6 +- .../phpbb/search/backend/fulltext_sphinx.php | 25 ++--- phpBB/phpbb/search/search_backend_factory.php | 4 +- 7 files changed, 115 insertions(+), 101 deletions(-) rename phpBB/phpbb/db/migration/data/{v330 => v400}/search_backend_update.php (55%) diff --git a/phpBB/phpbb/db/migration/data/v330/search_backend_update.php b/phpBB/phpbb/db/migration/data/v400/search_backend_update.php similarity index 55% rename from phpBB/phpbb/db/migration/data/v330/search_backend_update.php rename to phpBB/phpbb/db/migration/data/v400/search_backend_update.php index f7c979fc5e..f94bd67107 100644 --- a/phpBB/phpbb/db/migration/data/v330/search_backend_update.php +++ b/phpBB/phpbb/db/migration/data/v400/search_backend_update.php @@ -11,25 +11,37 @@ * */ -namespace phpbb\db\migration\data\v330; +namespace phpbb\db\migration\data\v400; + +use phpbb\search\backend\fulltext_mysql; +use phpbb\search\backend\fulltext_postgres; +use phpbb\search\backend\fulltext_sphinx; +use phpbb\search\backend\fulltext_native; class search_backend_update extends \phpbb\db\migration\migration { + static public function depends_on() + { + return [ + '\phpbb\db\migration\data\v400\dev', + ]; + } + public function update_data() { switch ($this->config['search_type']) { case '\\phpbb\\search\\fulltext_mysql': - $new_search_type = 'phpbb\\search\\backend\\fulltext_mysql'; - break; + $new_search_type = fulltext_mysql::class; + break; case '\\phpbb\\search\\fulltext_postgres': - $new_search_type = 'phpbb\\search\\backend\\fulltext_postgres'; - break; + $new_search_type = fulltext_postgres::class; + break; case '\\phpbb\\search\\fulltext_sphinx': - $new_search_type = 'phpbb\\search\\backend\\fulltext_sphinx'; - break; + $new_search_type = fulltext_sphinx::class; + break; default: - $new_search_type = 'phpbb\\search\\backend\\fulltext_native'; + $new_search_type = fulltext_native::class; } return [ diff --git a/phpBB/phpbb/search/backend/base.php b/phpBB/phpbb/search/backend/base.php index 019226a8cc..c6e0934da5 100644 --- a/phpBB/phpbb/search/backend/base.php +++ b/phpBB/phpbb/search/backend/base.php @@ -13,43 +13,36 @@ namespace phpbb\search\backend; -/** -* @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 */ -abstract class base +abstract class base implements search_backend_interface { - var $ignore_words = array(); - var $match_synonym = array(); - var $replace_synonym = array(); + public const SEARCH_RESULT_NOT_IN_CACHE = 0; + public const SEARCH_RESULT_IN_CACHE = 1; + public const SEARCH_RESULT_INCOMPLETE = 2; /** - * 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) + * 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 self::SEARCH_RESULT_NOT_IN_CACHE or self::SEARCH_RESULT_IN_CACHE or self::SEARCH_RESULT_INCOMPLETE + */ + public function obtain_ids(string $search_key, &$result_count, &$id_ary, &$start, $per_page, string $sort_dir): int { 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; + return self::SEARCH_RESULT_NOT_IN_CACHE; } else { @@ -79,7 +72,7 @@ abstract class base // the user requested a page past the last index if ($start < 0) { - return SEARCH_RESULT_NOT_IN_CACHE; + return self::SEARCH_RESULT_NOT_IN_CACHE; } } @@ -103,27 +96,27 @@ abstract class base if (!$complete) { - return SEARCH_RESULT_INCOMPLETE; + return self::SEARCH_RESULT_INCOMPLETE; } - return SEARCH_RESULT_IN_CACHE; + return self::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) + * 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 + */ + public function save_ids(string $search_key, string $keywords, $author_ary, int $result_count, &$id_ary, int $start, string $sort_dir) { global $cache, $config, $db, $user; @@ -224,15 +217,16 @@ abstract class base $db->sql_query($sql); } - unset($store); - unset($store_ids); - unset($id_range); + unset($store, $store_ids, $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) + * Removes old entries from the search results table and removes searches with keywords that contain a word in $words. + * + * @param array $words + * @param array|bool $authors + */ + public function destroy_cache($words, $authors = false): void { global $db, $cache, $config; @@ -369,9 +363,9 @@ abstract class base while (still_on_time() && $post_counter <= $acp_module->max_post_id) { $sql = 'SELECT post_id, poster_id, forum_id - FROM ' . POSTS_TABLE . ' - WHERE post_id >= ' . (int) ($post_counter + 1) . ' - AND post_id <= ' . (int) ($post_counter + $acp_module->batch_size); + FROM ' . POSTS_TABLE . ' + WHERE post_id >= ' . (int) ($post_counter + 1) . ' + AND post_id <= ' . (int) ($post_counter + $acp_module->batch_size); $result = $this->db->sql_query($sql); $ids = $posters = $forum_ids = array(); @@ -381,7 +375,7 @@ abstract class base $posters[] = $row['poster_id']; $forum_ids[] = $row['forum_id']; } - $db->sql_freeresult($result); + $result->sql_freeresult($result); $row_count += count($ids); if (count($ids)) diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index 2da5ab2221..116ab67201 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -13,6 +13,11 @@ namespace phpbb\search\backend; +use phpbb\config\config; +use phpbb\db\driver\driver_interface; +use phpbb\event\dispatcher_interface; +use phpbb\user; + /** * Fulltext search for MySQL */ @@ -32,25 +37,25 @@ class fulltext_mysql extends base implements search_backend_interface /** * Config object - * @var \phpbb\config\config + * @var config */ protected $config; /** * Database connection - * @var \phpbb\db\driver\driver_interface + * @var driver_interface */ protected $db; /** * phpBB event dispatcher object - * @var \phpbb\event\dispatcher_interface + * @var dispatcher_interface */ protected $phpbb_dispatcher; /** * User object - * @var \phpbb\user + * @var user */ protected $user; @@ -78,14 +83,14 @@ class fulltext_mysql extends base implements search_backend_interface * Constructor * Creates a new \phpbb\search\backend\fulltext_mysql, which is used as a search backend * - * @param \phpbb\config\config $config Config object - * @param \phpbb\db\driver\driver_interface $db Database object - * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object - * @param \phpbb\user $user User object + * @param config $config Config object + * @param driver_interface $db Database object + * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object + * @param user $user User object * @param string $phpbb_root_path Relative path to phpBB root * @param string $phpEx PHP file extension */ - public function __construct($config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) + public function __construct(config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, user $user, string $phpbb_root_path, string $phpEx) { $this->config = $config; $this->db = $db; @@ -106,7 +111,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_name() + public function get_name(): string { return 'MySQL Fulltext'; } @@ -114,7 +119,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_search_query() + public function get_search_query(): string { return $this->search_query; } @@ -122,7 +127,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_common_words() + public function get_common_words(): array { return $this->common_words; } @@ -130,7 +135,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_word_length() + public function get_word_length(): array { return $this->word_length; } @@ -168,8 +173,8 @@ class fulltext_mysql extends base implements search_backend_interface * We also require https://bugs.mysql.com/bug.php?id=67004 to be * fixed for proper overall operation. Hence we require 5.6.8. */ - || $engine === 'InnoDB' - && phpbb_version_compare($this->db->sql_server_info(true), '5.6.8', '>='); + || ($engine === 'InnoDB' + && phpbb_version_compare($this->db->sql_server_info(true), '5.6.8', '>=')); if (!$fulltext_supported) { @@ -204,7 +209,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function split_keywords(&$keywords, $terms) + public function split_keywords(&$keywords, $terms): bool { if ($terms == 'all') { @@ -340,10 +345,12 @@ class fulltext_mysql extends base implements search_backend_interface } /** - * Turns text into an array of words - * @param string $text contains post text/subject - */ - public function split_message($text) + * Turns text into an array of words + * @param string $text contains post text/subject + * + * @return array + */ + public function split_message($text): array { // Split words $text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text))); @@ -429,7 +436,7 @@ class fulltext_mysql extends base implements search_backend_interface // try reading the results from cache $result_count = 0; - if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) + if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == self::SEARCH_RESULT_IN_CACHE) { return $result_count; } @@ -679,7 +686,7 @@ class fulltext_mysql extends base implements search_backend_interface // try reading the results from cache $result_count = 0; - if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) + if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == self::SEARCH_RESULT_IN_CACHE) { return $result_count; } diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index 6bf3224fed..b7105f8cd6 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -120,7 +120,7 @@ class fulltext_native extends base implements search_backend_interface * @param string $phpbb_root_path phpBB root path * @param string $phpEx PHP file extension */ - public function __construct($config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) + public function __construct(config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, user $user, string $phpbb_root_path, string $phpEx) { $this->config = $config; $this->db = $db; @@ -589,7 +589,7 @@ class fulltext_native extends base implements search_backend_interface // try reading the results from cache $total_results = 0; - if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) + if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == self::SEARCH_RESULT_IN_CACHE) { return $total_results; } @@ -1053,7 +1053,7 @@ class fulltext_native extends base implements search_backend_interface // try reading the results from cache $total_results = 0; - if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) + if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == self::SEARCH_RESULT_IN_CACHE) { return $total_results; } diff --git a/phpBB/phpbb/search/backend/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php index 087f76559b..41b28bff61 100644 --- a/phpBB/phpbb/search/backend/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -103,7 +103,7 @@ class fulltext_postgres extends base implements search_backend_interface * @param string $phpbb_root_path Relative path to phpBB root * @param string $phpEx PHP file extension */ - public function __construct($config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) + public function __construct(config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, user $user, string $phpbb_root_path, string $phpEx) { $this->config = $config; $this->db = $db; @@ -364,7 +364,7 @@ class fulltext_postgres extends base implements search_backend_interface // try reading the results from cache $result_count = 0; - if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) + if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == self::SEARCH_RESULT_IN_CACHE) { return $result_count; } @@ -624,7 +624,7 @@ class fulltext_postgres extends base implements search_backend_interface // try reading the results from cache $result_count = 0; - if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) + if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == self::SEARCH_RESULT_IN_CACHE) { return $result_count; } diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index 4212eddfb1..da8c949b56 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -15,18 +15,19 @@ namespace phpbb\search\backend; use phpbb\auth\auth; use phpbb\config\config; +use phpbb\db\driver\driver_interface; use phpbb\event\dispatcher_interface; use phpbb\user; -define('SPHINX_MAX_MATCHES', 20000); -define('SPHINX_CONNECT_RETRIES', 3); -define('SPHINX_CONNECT_WAIT_TIME', 300); - /** * Fulltext search based on the sphinx search daemon */ class fulltext_sphinx implements search_backend_interface { + protected const SPHINX_MAX_MATCHES = 20000; + protected const SPHINX_CONNECT_RETRIES = 3; + protected const SPHINX_CONNECT_WAIT_TIME = 300; + /** * Associative array holding index stats * @var array @@ -131,14 +132,14 @@ class fulltext_sphinx implements search_backend_interface * * @param auth $auth Auth object * @param config $config Config object - * @param $db + * @param driver_interface $db Database object * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object * @param user $user User object * @param string $phpbb_root_path Relative path to phpBB root * @param string $phpEx PHP file extension * @throws \Exception */ - public function __construct($auth, $config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx) + public function __construct(auth $auth, config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, user $user, string $phpbb_root_path, string $phpEx) { $this->auth = $auth; $this->config = $config; @@ -684,15 +685,15 @@ class fulltext_sphinx implements search_backend_interface $this->sphinx->SetFilter('deleted', array(0)); - $this->sphinx->SetLimits((int) $start, (int) $per_page, max(SPHINX_MAX_MATCHES, (int) $start + $per_page)); + $this->sphinx->SetLimits((int) $start, (int) $per_page, max(self::SPHINX_MAX_MATCHES, (int) $start + $per_page)); $result = $this->sphinx->Query($search_query_prefix . $this->sphinx_clean_search_string(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; + $retries = self::SPHINX_CONNECT_RETRIES; while (!$result && (strpos($this->sphinx->GetLastError(), "errno=111,") !== false) && $retries--) { - usleep(SPHINX_CONNECT_WAIT_TIME); + usleep(self::SPHINX_CONNECT_WAIT_TIME); $result = $this->sphinx->Query($search_query_prefix . $this->sphinx_clean_search_string(str_replace('"', '"', $this->search_query)), $this->indexes); } @@ -715,15 +716,15 @@ class fulltext_sphinx implements search_backend_interface { $start = floor(($result_count - 1) / $per_page) * $per_page; - $this->sphinx->SetLimits((int) $start, (int) $per_page, max(SPHINX_MAX_MATCHES, (int) $start + $per_page)); + $this->sphinx->SetLimits((int) $start, (int) $per_page, max(self::SPHINX_MAX_MATCHES, (int) $start + $per_page)); $result = $this->sphinx->Query($search_query_prefix . $this->sphinx_clean_search_string(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; + $retries = self::SPHINX_CONNECT_RETRIES; while (!$result && (strpos($this->sphinx->GetLastError(), "errno=111,") !== false) && $retries--) { - usleep(SPHINX_CONNECT_WAIT_TIME); + usleep(self::SPHINX_CONNECT_WAIT_TIME); $result = $this->sphinx->Query($search_query_prefix . $this->sphinx_clean_search_string(str_replace('"', '"', $this->search_query)), $this->indexes); } } diff --git a/phpBB/phpbb/search/search_backend_factory.php b/phpBB/phpbb/search/search_backend_factory.php index ab103cae73..5ab6bce8af 100644 --- a/phpBB/phpbb/search/search_backend_factory.php +++ b/phpBB/phpbb/search/search_backend_factory.php @@ -48,7 +48,7 @@ class search_backend_factory * * @return search_backend_interface */ - public function get($class) + public function get($class): search_backend_interface { return $this->search_backends->get_by_class($class); } @@ -58,7 +58,7 @@ class search_backend_factory * * @return search_backend_interface */ - public function get_active() + public function get_active(): search_backend_interface { return $this->get($this->config['search_type']); } From 457c750773a66d97b75dbd1e8654cf855e9d4b29 Mon Sep 17 00:00:00 2001 From: rubencm Date: Mon, 22 Mar 2021 17:51:51 +0100 Subject: [PATCH 13/22] [ticket/15540] Display only available search backends PHPBB3-15540 --- phpBB/includes/acp/acp_search.php | 38 +++++++++---------- phpBB/phpbb/search/backend/fulltext_mysql.php | 10 ++++- .../phpbb/search/backend/fulltext_native.php | 20 +++++++--- .../search/backend/fulltext_postgres.php | 14 +++++-- .../phpbb/search/backend/fulltext_sphinx.php | 19 +++++++--- .../backend/search_backend_interface.php | 9 ++++- 6 files changed, 74 insertions(+), 36 deletions(-) diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index a2f3b97186..53fc6f5925 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -79,29 +79,29 @@ class acp_search foreach ($search_types as $search) { - $type = get_class($search); + // Only show available search backends + if($search->is_available()) { - $name = $search->get_name(); + $name = $search->get_name(); - $selected = ($config['search_type'] == $type) ? ' selected="selected"' : ''; - $identifier = substr($type, strrpos($type, '\\') + 1); - $search_options .= ""; + $type = get_class($search); - if (method_exists($search, 'acp')) - { - $vars = $search->acp(); + $selected = ($config['search_type'] == $type) ? ' selected="selected"' : ''; + $identifier = substr($type, strrpos($type, '\\') + 1); + $search_options .= ""; - if (!$submit) - { - $template->assign_block_vars('backend', array( - 'NAME' => $name, - 'SETTINGS' => $vars['tpl'], - 'IDENTIFIER' => $identifier, - )); - } - else if (is_array($vars['config'])) - { - $settings = array_merge($settings, $vars['config']); + if (method_exists($search, 'acp')) { + $vars = $search->acp(); + + if (!$submit) { + $template->assign_block_vars('backend', array( + 'NAME' => $name, + 'SETTINGS' => $vars['tpl'], + 'IDENTIFIER' => $identifier, + )); + } else if (is_array($vars['config'])) { + $settings = array_merge($settings, $vars['config']); + } } } } diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index 116ab67201..e95596022b 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -116,6 +116,14 @@ class fulltext_mysql extends base implements search_backend_interface return 'MySQL Fulltext'; } + /** + * {@inheritdoc} + */ + public function is_available(): bool + { + return $this->db->get_sql_layer() == 'mysqli'; + } + /** * {@inheritdoc} */ @@ -147,7 +155,7 @@ class fulltext_mysql extends base implements search_backend_interface */ public function init() { - if ($this->db->get_sql_layer() != 'mysqli') + if (!$this->is_available()) { return $this->user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE']; } diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index b7105f8cd6..81541930a7 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -23,12 +23,12 @@ use phpbb\user; */ class fulltext_native extends base implements search_backend_interface { - 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"; + protected const UTF8_HANGUL_FIRST = "\xEA\xB0\x80"; + protected const UTF8_HANGUL_LAST = "\xED\x9E\xA3"; + protected const UTF8_CJK_FIRST = "\xE4\xB8\x80"; + protected const UTF8_CJK_LAST = "\xE9\xBE\xBB"; + protected const UTF8_CJK_B_FIRST = "\xF0\xA0\x80\x80"; + protected const UTF8_CJK_B_LAST = "\xF0\xAA\x9B\x96"; /** * Associative array holding index stats @@ -149,6 +149,14 @@ class fulltext_native extends base implements search_backend_interface return 'phpBB Native Fulltext'; } + /** + * {@inheritdoc} + */ + public function is_available(): bool + { + return true; + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/search/backend/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php index 41b28bff61..234b820f29 100644 --- a/phpBB/phpbb/search/backend/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -56,7 +56,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * Database connection - * @var \phpbb\db\driver\driver_interface + * @var driver_interface */ protected $db; @@ -129,6 +129,14 @@ class fulltext_postgres extends base implements search_backend_interface return 'PostgreSQL Fulltext'; } + /** + * {@inheritdoc} + */ + public function is_available(): bool + { + return $this->db->get_sql_layer() == 'postgres'; + } + /** * {@inheritdoc} */ @@ -170,7 +178,7 @@ class fulltext_postgres extends base implements search_backend_interface */ public function init() { - if ($this->db->get_sql_layer() != 'postgres') + if (!$this->is_available()) { return $this->user->lang['FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE']; } @@ -1047,7 +1055,7 @@ class fulltext_postgres extends base implements search_backend_interface } /** - * Computes the stats and store them in the $this->stats associative array + * {@inheritdoc} */ protected function get_stats() { diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index da8c949b56..c53116af71 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -16,6 +16,7 @@ namespace phpbb\search\backend; use phpbb\auth\auth; use phpbb\config\config; use phpbb\db\driver\driver_interface; +use phpbb\db\tools\tools_interface; use phpbb\event\dispatcher_interface; use phpbb\user; @@ -85,13 +86,13 @@ class fulltext_sphinx implements search_backend_interface /** * Database connection - * @var \phpbb\db\driver\driver_interface + * @var driver_interface */ protected $db; /** * Database Tools object - * @var \phpbb\db\tools\tools_interface + * @var tools_interface */ protected $db_tools; @@ -180,6 +181,14 @@ class fulltext_sphinx implements search_backend_interface return 'Sphinx Fulltext'; } + /** + * {@inheritdoc} + */ + public function is_available(): bool + { + return ($this->db->get_sql_layer() == 'mysqli' || $this->db->get_sql_layer() == 'postgres') && class_exists('SphinxClient'); + } + /** * {@inheritdoc} */ @@ -211,7 +220,7 @@ class fulltext_sphinx implements search_backend_interface */ public function init() { - if ($this->db->get_sql_layer() != 'mysqli' && $this->db->get_sql_layer() != 'postgres') + if (!$this->is_available()) { return $this->user->lang['FULLTEXT_SPHINX_WRONG_DATABASE']; } @@ -922,9 +931,7 @@ class fulltext_sphinx implements search_backend_interface } /** - * Returns an associative array containing information about the indexes - * - * @return string|bool Language string of error false otherwise + * {@inheritdoc} */ public function index_stats() { diff --git a/phpBB/phpbb/search/backend/search_backend_interface.php b/phpBB/phpbb/search/backend/search_backend_interface.php index 7c7b60cb12..26c87909b9 100644 --- a/phpBB/phpbb/search/backend/search_backend_interface.php +++ b/phpBB/phpbb/search/backend/search_backend_interface.php @@ -22,6 +22,13 @@ interface search_backend_interface */ public function get_name(); + /** + * Returns if the search engine is available + * + * @return bool + */ + public function is_available(); + /** * Returns the search_query * @@ -142,7 +149,7 @@ interface search_backend_interface /** * Returns an associative array containing information about the indexes * - * @return array|bool Language string of error false otherwise + * @return array|false Language string of error false otherwise */ public function index_stats(); From fd45ce1e91b65358dd6ff40865ed2bfdad9720df Mon Sep 17 00:00:00 2001 From: rubencm Date: Mon, 22 Mar 2021 18:46:58 +0100 Subject: [PATCH 14/22] [ticket/15540] Method init PHPBB3-15540 --- phpBB/includes/acp/acp_search.php | 3 +- phpBB/phpbb/search/backend/fulltext_mysql.php | 70 +++++++++---------- .../phpbb/search/backend/fulltext_native.php | 8 +++ .../search/backend/fulltext_postgres.php | 28 ++++---- .../phpbb/search/backend/fulltext_sphinx.php | 4 +- .../backend/search_backend_interface.php | 9 +++ 6 files changed, 66 insertions(+), 56 deletions(-) diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 53fc6f5925..2c7e36d6e3 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -155,7 +155,8 @@ class acp_search $search = $search_backend_factory->get($cfg_array['search_type']); if (confirm_box(true)) { - if (!method_exists($search, 'init') || !($error = $search->init())) + // Initialize search backend, if $error is false means that everything is ok + if (!($error = $search->init())) { $config->set('search_type', $cfg_array['search_type']); diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index e95596022b..ef06911c65 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -121,38 +121,18 @@ class fulltext_mysql extends base implements search_backend_interface */ public function is_available(): bool { - return $this->db->get_sql_layer() == 'mysqli'; + // Check if we are using mysql + if($this->db->get_sql_layer() != 'mysqli') + { + return false; + } + + return true; } /** * {@inheritdoc} */ - public function get_search_query(): string - { - return $this->search_query; - } - - /** - * {@inheritdoc} - */ - public function get_common_words(): array - { - return $this->common_words; - } - - /** - * {@inheritdoc} - */ - public function get_word_length(): array - { - return $this->word_length; - } - - /** - * Checks for correct MySQL version and stores min/max word length in the config - * - * @return string|bool Language key of the error/incompatibility occurred - */ public function init() { if (!$this->is_available()) @@ -164,15 +144,7 @@ class fulltext_mysql extends base implements search_backend_interface $info = $this->db->sql_fetchrow($result); $this->db->sql_freeresult($result); - $engine = ''; - if (isset($info['Engine'])) - { - $engine = $info['Engine']; - } - else if (isset($info['Type'])) - { - $engine = $info['Type']; - } + $engine = $info['Engine'] ?? $info['Type'] ?? ''; $fulltext_supported = $engine === 'Aria' || $engine === 'MyISAM' /** @@ -182,7 +154,7 @@ class fulltext_mysql extends base implements search_backend_interface * fixed for proper overall operation. Hence we require 5.6.8. */ || ($engine === 'InnoDB' - && phpbb_version_compare($this->db->sql_server_info(true), '5.6.8', '>=')); + && phpbb_version_compare($this->db->sql_server_info(true), '5.6.8', '>=')); if (!$fulltext_supported) { @@ -214,6 +186,30 @@ class fulltext_mysql extends base implements search_backend_interface return false; } + /** + * {@inheritdoc} + */ + public function get_search_query(): string + { + return $this->search_query; + } + + /** + * {@inheritdoc} + */ + public function get_common_words(): array + { + return $this->common_words; + } + + /** + * {@inheritdoc} + */ + public function get_word_length(): array + { + return $this->word_length; + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index 81541930a7..ad042a545a 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -157,6 +157,14 @@ class fulltext_native extends base implements search_backend_interface return true; } + /** + * {@inheritdoc} + */ + public function init() + { + return false; + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/search/backend/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php index 234b820f29..ad0ad220fc 100644 --- a/phpBB/phpbb/search/backend/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -137,6 +137,19 @@ class fulltext_postgres extends base implements search_backend_interface return $this->db->get_sql_layer() == 'postgres'; } + /** + * {@inheritdoc} + */ + public function init() + { + if (!$this->is_available()) + { + return $this->user->lang['FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE']; + } + + return false; + } + /** * {@inheritdoc} */ @@ -171,21 +184,6 @@ class fulltext_postgres extends base implements search_backend_interface return $this->phrase_search; } - /** - * Checks for correct PostgreSQL version and stores min/max word length in the config - * - * @return string|bool Language key of the error/incompatibility occurred - */ - public function init() - { - if (!$this->is_available()) - { - return $this->user->lang['FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE']; - } - - return false; - } - /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index c53116af71..4a65aa944a 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -214,9 +214,7 @@ class fulltext_sphinx implements search_backend_interface } /** - * Checks permissions and paths, if everything is correct it generates the config file - * - * @return string|bool Language key of the error/incompatibility encountered, or false if successful + * {@inheritdoc} */ public function init() { diff --git a/phpBB/phpbb/search/backend/search_backend_interface.php b/phpBB/phpbb/search/backend/search_backend_interface.php index 26c87909b9..a22c4bda46 100644 --- a/phpBB/phpbb/search/backend/search_backend_interface.php +++ b/phpBB/phpbb/search/backend/search_backend_interface.php @@ -29,6 +29,15 @@ interface search_backend_interface */ public function is_available(); + /** + * Method executed when a search backend is set from acp. + * + * Checks permissions and paths, if everything is correct it generates the config file + * + * @return string|false False if everything was ok or string with error message + */ + public function init(); + /** * Returns the search_query * From 9dac66071ebb5272c1ae395a7de598acd5ca9a7a Mon Sep 17 00:00:00 2001 From: rubencm Date: Mon, 22 Mar 2021 19:56:48 +0100 Subject: [PATCH 15/22] [ticket/15540] Check method signatures, visibility, etc PHPBB3-15540 --- phpBB/develop/create_search_index.php | 140 ----- phpBB/includes/mcp/mcp_post.php | 5 +- phpBB/phpbb/search/backend/base.php | 6 +- phpBB/phpbb/search/backend/fulltext_mysql.php | 79 +-- .../phpbb/search/backend/fulltext_native.php | 156 ++--- .../search/backend/fulltext_postgres.php | 177 +++--- .../phpbb/search/backend/fulltext_sphinx.php | 556 +++++++++--------- .../backend/search_backend_interface.php | 171 +++--- phpBB/search.php | 2 +- 9 files changed, 585 insertions(+), 707 deletions(-) delete mode 100644 phpBB/develop/create_search_index.php diff --git a/phpBB/develop/create_search_index.php b/phpBB/develop/create_search_index.php deleted file mode 100644 index 6ef200699c..0000000000 --- a/phpBB/develop/create_search_index.php +++ /dev/null @@ -1,140 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -if (php_sapi_name() != 'cli') -{ - die("This program must be run from the command line.\n"); -} - -if ($argc < 2) -{ - echo 'Usage: php ' . basename(__FILE__) . " index_type [batch_size]\n"; - exit(1); -} - -$class_name = basename($argv[1]); - -define('IN_PHPBB', true); -$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : '../'; -$phpEx = substr(strrchr(__FILE__, '.'), 1); -require($phpbb_root_path . 'common.' . $phpEx); -require($phpbb_root_path . 'includes/acp/acp_search.' . $phpEx); - -$user->session_begin(); -$auth->acl($user->data); -$user->setup('acp/search'); - -$search_name = ucfirst(strtolower(str_replace('_', ' ', $class_name))); -$search_errors = array(); -$search = new $class_name($search_errors); - -$batch_size = isset($argv[2]) ? $argv[2] : 2000; - -if (method_exists($search, 'create_index')) -{ - if ($error = $search->create_index(null, '')) - { - var_dump($error); - exit(1); - } -} -else -{ - $sql = 'SELECT forum_id, enable_indexing - FROM ' . FORUMS_TABLE; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $forums[$row['forum_id']] = (bool) $row['enable_indexing']; - } - $db->sql_freeresult($result); - - $sql = 'SELECT post_id - FROM ' . POSTS_TABLE . ' - ORDER BY post_id DESC'; - $result = $db->sql_query_limit($sql, 1); - $max_post_id = (int) $db->sql_fetchfield('post_id'); - - $post_counter = 0; - while ($post_counter <= $max_post_id) - { - $row_count = 0; - $time = time(); - - printf("Processing posts with %d <= post_id <= %d\n", - $post_counter + 1, - $post_counter + $batch_size - ); - - $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id - FROM ' . POSTS_TABLE . ' - WHERE post_id >= ' . (int) ($post_counter + 1) . ' - AND post_id <= ' . (int) ($post_counter + $batch_size); - $result = $db->sql_query($sql); - - $buffer = $db->sql_buffer_nested_transactions(); - - if ($buffer) - { - $rows = $db->sql_fetchrowset($result); - $rows[] = false; // indicate end of array for while loop below - - $db->sql_freeresult($result); - } - - $i = 0; - while ($row = ($buffer ? $rows[$i++] : $db->sql_fetchrow($result))) - { - // Indexing enabled for this forum or global announcement? - // Global announcements get indexed by default. - if (!$row['forum_id'] || !empty($forums[$row['forum_id']])) - { - ++$row_count; - - $search->index('post', - $row['post_id'], - $row['post_text'], - $row['post_subject'], - $row['poster_id'], - $row['forum_id'] - ); - - if ($row_count % 10 == 0) - { - echo '.'; - } - } - } - - $delta = (time() - $time); - $delta = $delta <= 0 ? 1 : $delta; - printf(" %d posts/sec\n", $row_count / $delta); - - if (!$buffer) - { - $db->sql_freeresult($result); - } - - $post_counter += $batch_size; - } -} - -$search->tidy(); - -$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_CREATED', false, array($search_name)); - -echo $user->lang['SEARCH_INDEX_CREATED'] . "\n"; -echo 'Peak Memory Usage: ' . get_formatted_filesize(memory_get_peak_usage()) . "\n"; - -exit(0); diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index e75f2f8111..fb120577a3 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -635,10 +635,7 @@ function change_poster(&$post_info, $userdata) $search_backend_factory = $phpbb_container->get('search.backend_factory'); $search = $search_backend_factory->get_active(); - if (method_exists($search, 'destroy_cache')) - { - $search->destroy_cache(array(), array($post_info['user_id'], $userdata['user_id'])); - } + $search->index_remove([], [$post_info['user_id'], $userdata['user_id']], []); $from_username = $post_info['username']; $to_username = $userdata['username']; diff --git a/phpBB/phpbb/search/backend/base.php b/phpBB/phpbb/search/backend/base.php index c6e0934da5..4553ee0efb 100644 --- a/phpBB/phpbb/search/backend/base.php +++ b/phpBB/phpbb/search/backend/base.php @@ -35,7 +35,7 @@ abstract class base implements search_backend_interface * * @return int self::SEARCH_RESULT_NOT_IN_CACHE or self::SEARCH_RESULT_IN_CACHE or self::SEARCH_RESULT_INCOMPLETE */ - public function obtain_ids(string $search_key, &$result_count, &$id_ary, &$start, $per_page, string $sort_dir): int + protected function obtain_ids(string $search_key, &$result_count, &$id_ary, &$start, $per_page, string $sort_dir): int { global $cache; @@ -116,7 +116,7 @@ abstract class base implements search_backend_interface * * @return null */ - public function save_ids(string $search_key, string $keywords, $author_ary, int $result_count, &$id_ary, int $start, string $sort_dir) + protected function save_ids(string $search_key, string $keywords, $author_ary, int $result_count, &$id_ary, int $start, string $sort_dir) { global $cache, $config, $db, $user; @@ -226,7 +226,7 @@ abstract class base implements search_backend_interface * @param array $words * @param array|bool $authors */ - public function destroy_cache($words, $authors = false): void + protected function destroy_cache($words, $authors = false): void { global $db, $cache, $config; diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index ef06911c65..c42139138d 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -348,34 +348,6 @@ class fulltext_mysql extends base implements search_backend_interface return false; } - /** - * Turns text into an array of words - * @param string $text contains post text/subject - * - * @return array - */ - public function split_message($text): array - { - // Split words - $text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text))); - $matches = array(); - preg_match_all('#(?:[^\p{L}\p{N}*]|^)([+\-|]?(?:[\p{L}\p{N}*]+\'?)*[\p{L}\p{N}*])(?:[^\p{L}\p{N}*]|$)#u', $text, $matches); - $text = $matches[1]; - - // remove too short or too long words - $text = array_values($text); - 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']) - { - unset($text[$i]); - } - } - - return array_values($text); - } - /** * {@inheritdoc} */ @@ -871,15 +843,16 @@ class fulltext_mysql extends base implements search_backend_interface } /** - * Destroys cached search results, that contained one of the new words in a post so the results won't be outdated - * - * @param string $mode contains the post mode: edit, post, reply, quote ... - * @param int $post_id contains the post id of the post to index - * @param string $message contains the post text of the post - * @param string $subject contains the subject of the post to index - * @param int $poster_id contains the user id of the poster - * @param int $forum_id contains the forum id of parent forum of the post - */ + * {@inheritdoc} + */ + public function supports_phrase_search(): bool + { + return false; + } + + /** + * {@inheritdoc} + */ public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) { // Split old and new post/subject to obtain array of words @@ -930,7 +903,7 @@ class fulltext_mysql extends base implements search_backend_interface */ public function index_remove($post_ids, $author_ids, $forum_ids) { - $this->destroy_cache(array(), array_unique($author_ids)); + $this->destroy_cache([], array_unique($author_ids)); } /** @@ -939,7 +912,7 @@ class fulltext_mysql extends base implements search_backend_interface public function tidy() { // destroy too old cached search results - $this->destroy_cache(array()); + $this->destroy_cache([]); $this->config->set('search_last_gc', time(), false); } @@ -1151,6 +1124,34 @@ class fulltext_mysql extends base implements search_backend_interface $this->stats['total_posts'] = empty($this->stats) ? 0 : $this->db->get_estimated_row_count(POSTS_TABLE); } + /** + * Turns text into an array of words + * @param string $text contains post text/subject + * + * @return array + */ + protected function split_message($text): array + { + // Split words + $text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text))); + $matches = array(); + preg_match_all('#(?:[^\p{L}\p{N}*]|^)([+\-|]?(?:[\p{L}\p{N}*]+\'?)*[\p{L}\p{N}*])(?:[^\p{L}\p{N}*]|$)#u', $text, $matches); + $text = $matches[1]; + + // remove too short or too long words + $text = array_values($text); + 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']) + { + unset($text[$i]); + } + } + + return array_values($text); + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index ad042a545a..ec2c9dcf1c 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -1303,78 +1303,11 @@ class fulltext_native extends base implements search_backend_interface } /** - * Split a text into words of a given length - * - * The text is converted to UTF-8, cleaned up, and split. Then, words that - * conform to the defined length range are returned in an array. - * - * NOTE: duplicates are NOT removed from the return array - * - * @param string $text Text to split, encoded in UTF-8 - * @return array Array of UTF-8 words - */ - public function split_message($text) + * {@inheritdoc} + */ + public function supports_phrase_search(): bool { - $match = $words = array(); - - /** - * Taken from the original code - */ - // Do not index code - $match[] = '#\[code(?:=.*?)?(\:?[0-9a-z]{5,})\].*?\[\/code(\:?[0-9a-z]{5,})\]#is'; - // BBcode - $match[] = '#\[\/?[a-z0-9\*\+\-]+(?:=.*?)?(?::[a-z])?(\:?[0-9a-z]{5,})\]#'; - - $min = $this->word_length['min']; - - $isset_min = $min - 1; - - /** - * Clean up the string, remove HTML tags, remove BBCodes - */ - $word = strtok($this->cleanup(preg_replace($match, ' ', strip_tags($text)), -1), ' '); - - while (strlen($word)) - { - if (strlen($word) > 255 || strlen($word) <= $isset_min) - { - /** - * Words longer than 255 bytes are ignored. This will have to be - * changed whenever we change the length of search_wordlist.word_text - * - * Words shorter than $isset_min bytes are ignored, too - */ - $word = strtok(' '); - continue; - } - - $len = utf8_strlen($word); - - /** - * Test whether the word is too short to be indexed. - * - * Note that this limit does NOT apply to CJK and Hangul - */ - if ($len < $min) - { - /** - * 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, 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; - } - } - - $words[] = $word; - $word = strtok(' '); - } - - return $words; + return false; } /** @@ -1686,6 +1619,8 @@ class fulltext_native extends base implements search_backend_interface $this->config->set('search_last_gc', time(), false); } + // create_index is inherited from base.php + /** * {@inheritdoc} */ @@ -1733,14 +1668,14 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - public function index_created() + public function index_created(): bool { if (!count($this->stats)) { $this->get_stats(); } - return ($this->stats['total_words'] && $this->stats['total_matches']) ? true : false; + return $this->stats['total_words'] && $this->stats['total_matches']; } /** @@ -1767,6 +1702,81 @@ class fulltext_native extends base implements search_backend_interface $this->stats['total_matches'] = $this->db->get_estimated_row_count(SEARCH_WORDMATCH_TABLE); } + /** + * Split a text into words of a given length + * + * The text is converted to UTF-8, cleaned up, and split. Then, words that + * conform to the defined length range are returned in an array. + * + * NOTE: duplicates are NOT removed from the return array + * + * @param string $text Text to split, encoded in UTF-8 + * @return array Array of UTF-8 words + */ + protected function split_message($text) + { + $match = $words = array(); + + /** + * Taken from the original code + */ + // Do not index code + $match[] = '#\[code(?:=.*?)?(\:?[0-9a-z]{5,})\].*?\[\/code(\:?[0-9a-z]{5,})\]#is'; + // BBcode + $match[] = '#\[\/?[a-z0-9\*\+\-]+(?:=.*?)?(?::[a-z])?(\:?[0-9a-z]{5,})\]#'; + + $min = $this->word_length['min']; + + $isset_min = $min - 1; + + /** + * Clean up the string, remove HTML tags, remove BBCodes + */ + $word = strtok($this->cleanup(preg_replace($match, ' ', strip_tags($text)), -1), ' '); + + while (strlen($word)) + { + if (strlen($word) > 255 || strlen($word) <= $isset_min) + { + /** + * Words longer than 255 bytes are ignored. This will have to be + * changed whenever we change the length of search_wordlist.word_text + * + * Words shorter than $isset_min bytes are ignored, too + */ + $word = strtok(' '); + continue; + } + + $len = utf8_strlen($word); + + /** + * Test whether the word is too short to be indexed. + * + * Note that this limit does NOT apply to CJK and Hangul + */ + if ($len < $min) + { + /** + * 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, 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; + } + } + + $words[] = $word; + $word = strtok(' '); + } + + return $words; + } + /** * Clean up a text to remove non-alphanumeric characters * diff --git a/phpBB/phpbb/search/backend/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php index ad0ad220fc..8692683d96 100644 --- a/phpBB/phpbb/search/backend/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -174,16 +174,6 @@ class fulltext_postgres extends base implements search_backend_interface return $this->word_length; } - /** - * Returns if phrase search is supported or not - * - * @return bool - */ - public function supports_phrase_search() - { - return $this->phrase_search; - } - /** * {@inheritdoc} */ @@ -274,31 +264,6 @@ class fulltext_postgres extends base implements search_backend_interface return false; } - /** - * Turns text into an array of words - * @param string $text contains post text/subject - */ - public function split_message($text) - { - // Split words - $text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text))); - $matches = array(); - preg_match_all('#(?:[^\p{L}\p{N}*]|^)([+\-|]?(?:[\p{L}\p{N}*]+\'?)*[\p{L}\p{N}*])(?:[^\p{L}\p{N}*]|$)#u', $text, $matches); - $text = $matches[1]; - - // remove too short or too long words - $text = array_values($text); - 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']) - { - unset($text[$i]); - } - } - - return array_values($text); - } /** * {@inheritdoc} @@ -332,21 +297,21 @@ class fulltext_postgres extends base implements search_backend_interface ); /** - * Allow changing the search_key for cached results - * - * @event core.search_postgres_by_keyword_modify_search_key - * @var array search_key_array Array with search parameters to generate the search_key - * @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 - * @since 3.1.7-RC1 - */ + * Allow changing the search_key for cached results + * + * @event core.search_postgres_by_keyword_modify_search_key + * @var array search_key_array Array with search parameters to generate the search_key + * @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 + * @since 3.1.7-RC1 + */ $vars = array( 'search_key_array', 'type', @@ -388,16 +353,16 @@ class fulltext_postgres extends base implements search_backend_interface case 'u': $sql_sort_table = USERS_TABLE . ' u, '; $sql_sort_join = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster '; - break; + break; case 't': $join_topic = true; - break; + break; case 'f': $sql_sort_table = FORUMS_TABLE . ' f, '; $sql_sort_join = ' AND f.forum_id = p.forum_id '; - break; + break; } // Build some display specific sql strings @@ -407,53 +372,53 @@ class fulltext_postgres extends base implements search_backend_interface $sql_match = 'p.post_subject'; $sql_match_where = ' AND p.post_id = t.topic_first_post_id'; $join_topic = true; - break; + break; case 'msgonly': $sql_match = 'p.post_text'; $sql_match_where = ''; - break; + break; case 'firstpost': $sql_match = 'p.post_subject, p.post_text'; $sql_match_where = ' AND p.post_id = t.topic_first_post_id'; $join_topic = true; - break; + break; default: $sql_match = 'p.post_subject, p.post_text'; $sql_match_where = ''; - break; + break; } $tsearch_query = $this->tsearch_query; /** - * Allow changing the query used to search for posts using fulltext_postgres - * - * @event core.search_postgres_keywords_main_query_before - * @var string tsearch_query The parsed keywords used for this search - * @var int result_count The previous result count for the format of the query. - * Set to 0 to force a re-count - * @var bool join_topic Weather or not TOPICS_TABLE should be CROSS JOIN'ED - * @var array author_ary Array of user_id containing the users to filter the results to - * @var string author_name An extra username to search on (!empty(author_ary) must be true, to be relevant) - * @var array ex_fid_ary Which forums not to search on - * @var int topic_id Limit the search to this topic_id only - * @var string sql_sort_table Extra tables to include in the SQL query. - * Used in conjunction with sql_sort_join - * @var string sql_sort_join SQL conditions to join all the tables used together. - * Used in conjunction with sql_sort_table - * @var int sort_days Time, in days, of the oldest possible post to list - * @var string sql_match Which columns to do the search on. - * @var string sql_match_where Extra conditions to use to properly filter the matching process - * @var string sort_by_sql The possible predefined sort types - * @var string sort_key The sort type used from the possible sort types - * @var string sort_dir "a" for ASC or "d" dor DESC for the sort order used - * @var string sql_sort The result SQL when processing sort_by_sql + sort_key + sort_dir - * @var int start How many posts to skip in the search results (used for pagination) - * @since 3.1.5-RC1 - */ + * Allow changing the query used to search for posts using fulltext_postgres + * + * @event core.search_postgres_keywords_main_query_before + * @var string tsearch_query The parsed keywords used for this search + * @var int result_count The previous result count for the format of the query. + * Set to 0 to force a re-count + * @var bool join_topic Weather or not TOPICS_TABLE should be CROSS JOIN'ED + * @var array author_ary Array of user_id containing the users to filter the results to + * @var string author_name An extra username to search on (!empty(author_ary) must be true, to be relevant) + * @var array ex_fid_ary Which forums not to search on + * @var int topic_id Limit the search to this topic_id only + * @var string sql_sort_table Extra tables to include in the SQL query. + * Used in conjunction with sql_sort_join + * @var string sql_sort_join SQL conditions to join all the tables used together. + * Used in conjunction with sql_sort_table + * @var int sort_days Time, in days, of the oldest possible post to list + * @var string sql_match Which columns to do the search on. + * @var string sql_match_where Extra conditions to use to properly filter the matching process + * @var string sort_by_sql The possible predefined sort types + * @var string sort_key The sort type used from the possible sort types + * @var string sort_dir "a" for ASC or "d" dor DESC for the sort order used + * @var string sql_sort The result SQL when processing sort_by_sql + sort_key + sort_dir + * @var int start How many posts to skip in the search results (used for pagination) + * @since 3.1.5-RC1 + */ $vars = array( 'tsearch_query', 'result_count', @@ -833,15 +798,16 @@ class fulltext_postgres extends base implements search_backend_interface } /** - * Destroys cached search results, that contained one of the new words in a post so the results won't be outdated - * - * @param string $mode contains the post mode: edit, post, reply, quote ... - * @param int $post_id contains the post id of the post to index - * @param string $message contains the post text of the post - * @param string $subject contains the subject of the post to index - * @param int $poster_id contains the user id of the poster - * @param int $forum_id contains the forum id of parent forum of the post - */ + * {@inheritdoc} + */ + public function supports_phrase_search(): bool + { + return $this->phrase_search; + } + + /** + * {@inheritdoc} + */ public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) { // Split old and new post/subject to obtain array of words @@ -892,7 +858,7 @@ class fulltext_postgres extends base implements search_backend_interface */ public function index_remove($post_ids, $author_ids, $forum_ids) { - $this->destroy_cache(array(), $author_ids); + $this->destroy_cache([], $author_ids); } /** @@ -1095,6 +1061,33 @@ class fulltext_postgres extends base implements search_backend_interface $this->stats['total_posts'] = $this->config['num_posts']; } + /** + * Turns text into an array of words + * @param string $text contains post text/subject + * @return array + */ + protected function split_message($text) + { + // Split words + $text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text))); + $matches = array(); + preg_match_all('#(?:[^\p{L}\p{N}*]|^)([+\-|]?(?:[\p{L}\p{N}*]+\'?)*[\p{L}\p{N}*])(?:[^\p{L}\p{N}*]|$)#u', $text, $matches); + $text = $matches[1]; + + // remove too short or too long words + $text = array_values($text); + 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']) + { + unset($text[$i]); + } + } + + return array_values($text); + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index 4a65aa944a..680577d5c1 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -192,30 +192,6 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function get_search_query() - { - return $this->search_query; - } - - /** - * {@inheritdoc} - */ - public function get_word_length() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function get_common_words() - { - return array(); - } - - /** - * {@inheritdoc} - */ public function init() { if (!$this->is_available()) @@ -230,203 +206,27 @@ class fulltext_sphinx implements search_backend_interface } /** - * Generates content of sphinx.conf - * - * @return bool True if sphinx.conf content is correctly generated, false otherwise + * {@inheritdoc} */ - protected function config_generate() + public function get_search_query() { - // Check if Database is supported by Sphinx - if ($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; - } + return $this->search_query; + } - // 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; - } + /** + * {@inheritdoc} + */ + public function get_common_words() + { + return array(); + } - 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('wordforms', ' # optional, specify path to wordforms file. See ./docs/sphinx_wordforms.txt for example'), - array('exceptions', ' # optional, specify path to exceptions file. See ./docs/sphinx_exceptions.txt for example'), - 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('ignore_chars', 'U+0027, U+002C'), - array('min_prefix_len', '3 # Minimum number of characters for wildcard searches by prefix (min 1). Default is 3. If specified, set min_infix_len to 0'), - array('min_infix_len', '0 # Minimum number of characters for wildcard searches by infix (min 2). If specified, set min_prefix_len to 0'), - array('html_strip', '1'), - array('index_exact_words', '0 # Set to 1 to enable exact search operator. Requires wordforms or morphology'), - array('blend_chars', 'U+23, U+24, U+25, U+26, U+40'), - ), - '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; + /** + * {@inheritdoc} + */ + public function get_word_length() + { + return false; } /** @@ -463,62 +263,6 @@ class fulltext_sphinx implements search_backend_interface return false; } - /** - * Cleans search query passed into Sphinx search engine, as follows: - * 1. Hyphenated words are replaced with keyword search for either the exact phrase with spaces - * or as a single word without spaces eg search for "know-it-all" becomes ("know it all"|"knowitall*") - * 2. Words with apostrophes are contracted eg "it's" becomes "its" - * 3. <, >, " and & are decoded from HTML entities. - * 4. Following special characters used as search operators in Sphinx are preserved when used with correct syntax: - * (a) quorum matching: "the world is a wonderful place"/3 - * Finds 3 of the words within the phrase. Number must be between 1 and 9. - * (b) proximity search: "hello world"~10 - * Finds hello and world within 10 words of each other. Number can be between 1 and 99. - * (c) strict word order: aaa << bbb << ccc - * Finds "aaa" only where it appears before "bbb" and only where "bbb" appears before "ccc". - * (d) exact match operator: if lemmatizer or stemming enabled, - * search will find exact match only and ignore other grammatical forms of the same word stem. - * eg. raining =cats and =dogs - * will not return "raining cat and dog" - * eg. ="search this exact phrase" - * will not return "searched this exact phrase", "searching these exact phrases". - * 5. Special characters /, ~, << and = not complying with the correct syntax - * and other reserved operators are escaped and searched literally. - * Special characters not explicitly listed in charset_table or blend_chars in sphinx.conf - * will not be indexed and keywords containing them will be ignored by Sphinx. - * By default, only $, %, & and @ characters are indexed and searchable. - * String transformation is in backend only and not visible to the end user - * nor reflected in the results page URL or keyword highlighting. - * - * @param string $search_string - * @return string - */ - public function sphinx_clean_search_string($search_string) - { - $from = ['@', '^', '$', '!', '<', '>', '"', '&', '\'']; - $to = ['\@', '\^', '\$', '\!', '<', '>', '"', '&', '']; - - $search_string = str_replace($from, $to, $search_string); - - $search_string = strrev($search_string); - $search_string = preg_replace(['#\/(?!"[^"]+")#', '#~(?!"[^"]+")#'], ['/\\', '~\\'], $search_string); - $search_string = strrev($search_string); - - $match = ['#(/|\\\\/)(?![1-9](\s|$))#', '#(~|\\\\~)(?!\d{1,2}(\s|$))#', '#((?:\p{L}|\p{N})+)-((?:\p{L}|\p{N})+)(?:-((?:\p{L}|\p{N})+))?(?:-((?:\p{L}|\p{N})+))?#i', '#<<\s*$#', '#(\S\K=|=(?=\s)|=$)#']; - $replace = ['\/', '\~', '("$1 $2 $3 $4"|$1$2$3$4*)', '\<\<', '\=']; - - $search_string = preg_replace($match, $replace, $search_string); - $search_string = preg_replace('#\s+"\|#', '"|', $search_string); - - /** - * OPTIONAL: Thousands separator stripped from numbers, eg search for '90,000' is queried as '90000'. - * By default commas are stripped from search index so that '90,000' is indexed as '90000' - */ - // $search_string = preg_replace('#[0-9]{1,3}\K,(?=[0-9]{3})#', '', $search_string); - - return $search_string; - } - /** * {@inheritdoc} */ @@ -774,6 +518,14 @@ class fulltext_sphinx implements search_backend_interface 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); } + /** + * {@inheritdoc} + */ + public function supports_phrase_search(): bool + { + return false; + } + /** * {@inheritdoc} */ @@ -857,7 +609,7 @@ class fulltext_sphinx implements search_backend_interface /** * Nothing needs to be destroyed */ - public function tidy($create = false) + public function tidy() { $this->config->set('search_last_gc', time(), false); } @@ -968,6 +720,62 @@ class fulltext_sphinx implements search_backend_interface } } + /** + * Cleans search query passed into Sphinx search engine, as follows: + * 1. Hyphenated words are replaced with keyword search for either the exact phrase with spaces + * or as a single word without spaces eg search for "know-it-all" becomes ("know it all"|"knowitall*") + * 2. Words with apostrophes are contracted eg "it's" becomes "its" + * 3. <, >, " and & are decoded from HTML entities. + * 4. Following special characters used as search operators in Sphinx are preserved when used with correct syntax: + * (a) quorum matching: "the world is a wonderful place"/3 + * Finds 3 of the words within the phrase. Number must be between 1 and 9. + * (b) proximity search: "hello world"~10 + * Finds hello and world within 10 words of each other. Number can be between 1 and 99. + * (c) strict word order: aaa << bbb << ccc + * Finds "aaa" only where it appears before "bbb" and only where "bbb" appears before "ccc". + * (d) exact match operator: if lemmatizer or stemming enabled, + * search will find exact match only and ignore other grammatical forms of the same word stem. + * eg. raining =cats and =dogs + * will not return "raining cat and dog" + * eg. ="search this exact phrase" + * will not return "searched this exact phrase", "searching these exact phrases". + * 5. Special characters /, ~, << and = not complying with the correct syntax + * and other reserved operators are escaped and searched literally. + * Special characters not explicitly listed in charset_table or blend_chars in sphinx.conf + * will not be indexed and keywords containing them will be ignored by Sphinx. + * By default, only $, %, & and @ characters are indexed and searchable. + * String transformation is in backend only and not visible to the end user + * nor reflected in the results page URL or keyword highlighting. + * + * @param string $search_string + * @return string + */ + protected function sphinx_clean_search_string($search_string) + { + $from = ['@', '^', '$', '!', '<', '>', '"', '&', '\'']; + $to = ['\@', '\^', '\$', '\!', '<', '>', '"', '&', '']; + + $search_string = str_replace($from, $to, $search_string); + + $search_string = strrev($search_string); + $search_string = preg_replace(['#\/(?!"[^"]+")#', '#~(?!"[^"]+")#'], ['/\\', '~\\'], $search_string); + $search_string = strrev($search_string); + + $match = ['#(/|\\\\/)(?![1-9](\s|$))#', '#(~|\\\\~)(?!\d{1,2}(\s|$))#', '#((?:\p{L}|\p{N})+)-((?:\p{L}|\p{N})+)(?:-((?:\p{L}|\p{N})+))?(?:-((?:\p{L}|\p{N})+))?#i', '#<<\s*$#', '#(\S\K=|=(?=\s)|=$)#']; + $replace = ['\/', '\~', '("$1 $2 $3 $4"|$1$2$3$4*)', '\<\<', '\=']; + + $search_string = preg_replace($match, $replace, $search_string); + $search_string = preg_replace('#\s+"\|#', '"|', $search_string); + + /** + * OPTIONAL: Thousands separator stripped from numbers, eg search for '90,000' is queried as '90000'. + * By default commas are stripped from search index so that '90,000' is indexed as '90000' + */ + // $search_string = preg_replace('#[0-9]{1,3}\K,(?=[0-9]{3})#', '', $search_string); + + return $search_string; + } + /** * {@inheritdoc} */ @@ -1010,4 +818,204 @@ class fulltext_sphinx implements search_backend_interface 'config' => $config_vars ); } + + /** + * 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() == '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('wordforms', ' # optional, specify path to wordforms file. See ./docs/sphinx_wordforms.txt for example'), + array('exceptions', ' # optional, specify path to exceptions file. See ./docs/sphinx_exceptions.txt for example'), + 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('ignore_chars', 'U+0027, U+002C'), + array('min_prefix_len', '3 # Minimum number of characters for wildcard searches by prefix (min 1). Default is 3. If specified, set min_infix_len to 0'), + array('min_infix_len', '0 # Minimum number of characters for wildcard searches by infix (min 2). If specified, set min_prefix_len to 0'), + array('html_strip', '1'), + array('index_exact_words', '0 # Set to 1 to enable exact search operator. Requires wordforms or morphology'), + array('blend_chars', 'U+23, U+24, U+25, U+26, U+40'), + ), + '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; + } } diff --git a/phpBB/phpbb/search/backend/search_backend_interface.php b/phpBB/phpbb/search/backend/search_backend_interface.php index a22c4bda46..21b8b4dff7 100644 --- a/phpBB/phpbb/search/backend/search_backend_interface.php +++ b/phpBB/phpbb/search/backend/search_backend_interface.php @@ -15,11 +15,14 @@ namespace phpbb\search\backend; interface search_backend_interface { + // TODO: comprobar los pasos pr referencia + // TODO: eliminar acp_module de create index y delete index + /** - * Returns the name of this search backend to be displayed to administrators - * - * @return string Name - */ + * Returns the name of this search backend to be displayed to administrators + * + * @return string Name + */ public function get_name(); /** @@ -59,113 +62,119 @@ interface search_backend_interface */ public function get_word_length(); - //public function init(); - /** - * Splits keywords entered by a user into an array of words stored in $this->split_words - * Stores the tidied search query in $this->search_query - * - * @param string &$keywords Contains the keyword as entered by the user - * @param string $terms is either 'all' or 'any' - * @return bool false if no valid keywords were found and otherwise true - */ + * Splits keywords entered by a user into an array of words stored in $this->split_words + * Stores the tidied search query in $this->search_query + * + * @param string &$keywords Contains the keyword as entered by the user + * @param string $terms is either 'all' or 'any' + * @return bool false if no valid keywords were found and otherwise true + */ public function split_keywords(&$keywords, $terms); /** - * 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 - */ + * 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); /** - * 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 - */ + * 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); /** - * 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 contains the post id of the post to index - * @param string $message contains the post text of the post - * @param string $subject contains the subject of the post to index - * @param int $poster_id contains the user id of the poster - * @param int $forum_id contains the forum id of parent forum of the post - */ + * Returns if phrase search is supported or not + * + * @return bool + */ + public function supports_phrase_search(): bool; + + /** + * Updates wordlist and wordmatch tables when a message is posted or changed + * Destroys cached search results, that contained one of the new words in a post so the results won't be outdated + * + * @param string $mode contains the post mode: edit, post, reply, quote ... + * @param int $post_id contains the post id of the post to index + * @param string $message contains the post text of the post + * @param string $subject contains the subject of the post to index + * @param int $poster_id contains the user id of the poster + * @param int $forum_id contains the forum id of parent forum of the post + */ public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id); /** - * Destroy cached results, that might be outdated after deleting a post - */ + * Destroy cached results, that might be outdated after deleting a post + */ public function index_remove($post_ids, $author_ids, $forum_ids); /** - * Destroy old cache entries - */ + * Destroy old cache entries + */ public function tidy(); /** - * Create fulltext index - * - * @return string|bool error string is returned incase of errors otherwise false - */ + * Create fulltext index + * + * @return string|bool error string is returned incase of errors otherwise false + */ public function create_index($acp_module, $u_action); /** - * Drop fulltext index - * - * @return string|bool error string is returned incase of errors otherwise false - */ + * Drop fulltext index + * + * @return string|bool error string is returned incase of errors otherwise false + */ public function delete_index($acp_module, $u_action); /** - * Returns true if both FULLTEXT indexes exist - */ + * Returns true if both FULLTEXT indexes exist + */ public function index_created(); /** - * Returns an associative array containing information about the indexes - * - * @return array|false Language string of error false otherwise - */ + * Returns an associative array containing information about the indexes + * + * @return array|false Language string of error false otherwise + */ public function index_stats(); /** - * Display various options that can be configured for the backend from the acp - * - * @return associative array containing template and config variables - */ + * Display various options that can be configured for the backend from the acp + * + * @return associative array containing template and config variables + */ public function acp(); } diff --git a/phpBB/search.php b/phpBB/search.php index 3eac7391ed..f7be082564 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -1287,7 +1287,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) // Check if search backend supports phrase search or not $phrase_search_disabled = ''; - if (strpos(html_entity_decode($keywords), '"') !== false && method_exists($search, 'supports_phrase_search')) + if (strpos(html_entity_decode($keywords), '"') !== false) { $phrase_search_disabled = $search->supports_phrase_search() ? false : true; } From 16220058d370ace0ab361d8f6d64bea1fc28d339 Mon Sep 17 00:00:00 2001 From: rubencm Date: Mon, 22 Mar 2021 21:54:36 +0100 Subject: [PATCH 16/22] [ticket/15540] Decouple create_index and delete_index from acp PHPBB3-15540 --- phpBB/includes/acp/acp_search.php | 56 ++++--- phpBB/phpbb/search/backend/base.php | 157 +++++++++++------- phpBB/phpbb/search/backend/fulltext_mysql.php | 13 +- .../phpbb/search/backend/fulltext_native.php | 4 +- .../search/backend/fulltext_postgres.php | 13 +- .../phpbb/search/backend/fulltext_sphinx.php | 35 ++-- .../backend/search_backend_interface.php | 13 +- 7 files changed, 166 insertions(+), 125 deletions(-) diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 2c7e36d6e3..438d798b76 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -24,8 +24,6 @@ class acp_search var $u_action; var $state; var $search; - var $max_post_id; - var $batch_size = 100; function main($id, $mode) { @@ -220,7 +218,7 @@ class acp_search function index($id, $mode) { - global $db, $user, $template, $phpbb_log, $request; + global $user, $template, $phpbb_log, $request; global $config, $phpbb_admin_path, $phpEx, $phpbb_container; $action = $request->variable('action', ''); @@ -273,19 +271,28 @@ class acp_search $action = &$this->state[1]; - $this->max_post_id = $this->get_max_post_id(); - $this->save_state(); switch ($action) { case 'delete': - // pass a reference to myself so the $search object can make use of save_state() and attributes - if ($error = $this->search->delete_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=delete&hash=" . generate_link_hash('acp_search'), false))) + try + { + if ($status = $this->search->delete_index($this->state[2])) // Status is not null, so deleting is in progress.... + { + // save the current state + $this->save_state(); + + $u_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=delete&hash=" . generate_link_hash('acp_search'), false); + meta_refresh(1, $u_action); + trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $status['row_count'], $status['post_counter']) . $user->lang('SEARCH_INDEX_DELETE_REDIRECT_RATE', $status['rows_per_second'])); + } + } + catch (Exception $e) { $this->state = array(''); $this->save_state(); - trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); + trigger_error($e->getMessage() . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); } $this->search->tidy(); @@ -298,14 +305,28 @@ class acp_search break; case 'create': - // pass a reference to acp_search so the $search object can make use of save_state() and attributes - if ($error = $this->search->create_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=create&hash=" . generate_link_hash('acp_search'), false))) + try { + if ($status = $this->search->create_index($this->state[2])) // Status is not null, so indexing is in progress.... + { + // save the current state + $this->save_state(); + + $u_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=create&hash=" . generate_link_hash('acp_search'), false); + meta_refresh(1, $u_action); + trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $status['row_count'], $status['post_counter']) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $status['rows_per_second'])); + } + } + catch (Exception $e) + { + // Error executing create_index $this->state = array(''); $this->save_state(); - trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); + trigger_error($e->getMessage() . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); } + // Indexing have finished + $this->search->tidy(); $this->state = array(''); @@ -421,19 +442,6 @@ class acp_search "\n"; } - function get_max_post_id() - { - global $db; - - $sql = 'SELECT MAX(post_id) as max_post_id - FROM '. POSTS_TABLE; - $result = $db->sql_query($sql); - $max_post_id = (int) $db->sql_fetchfield('max_post_id'); - $db->sql_freeresult($result); - - return $max_post_id; - } - function save_state($state = false) { global $config; diff --git a/phpBB/phpbb/search/backend/base.php b/phpBB/phpbb/search/backend/base.php index 4553ee0efb..172edeca4d 100644 --- a/phpBB/phpbb/search/backend/base.php +++ b/phpBB/phpbb/search/backend/base.php @@ -23,6 +23,9 @@ abstract class base implements search_backend_interface public const SEARCH_RESULT_IN_CACHE = 1; public const SEARCH_RESULT_INCOMPLETE = 2; + // Batch size for create_index and delete_index + private const BATCH_SIZE = 100; + /** * Retrieves cached search results * @@ -281,61 +284,31 @@ abstract class base implements search_backend_interface /** * {@inheritdoc} */ - public function create_index($acp_module, $u_action) + public function create_index(int &$post_counter = null): ?array { - $sql = 'SELECT forum_id, enable_indexing - FROM ' . FORUMS_TABLE; - $result = $this->db->sql_query($sql, 3600); - - while ($row = $this->db->sql_fetchrow($result)) - { - $forums[$row['forum_id']] = (bool) $row['enable_indexing']; - } - $this->db->sql_freeresult($result); + $max_post_id = $this->get_max_post_id(); + $forums_indexing_enabled = $this->forum_ids_with_indexing_enabled(); $starttime = microtime(true); $row_count = 0; - $post_counter = &$acp_module->state[2]; - while (still_on_time() && $post_counter <= $acp_module->max_post_id) + while (still_on_time() && $post_counter <= $max_post_id) { - $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id - FROM ' . POSTS_TABLE . ' - WHERE post_id >= ' . (int) ($post_counter + 1) . ' - AND post_id <= ' . (int) ($post_counter + $acp_module->batch_size); - $result = $this->db->sql_query($sql); + $rows = $this->get_posts_between($post_counter + 1, $post_counter + self::BATCH_SIZE); - $buffer = $this->db->sql_buffer_nested_transactions(); - - if ($buffer) - { - $rows = $this->db->sql_fetchrowset($result); - $rows[] = false; // indicate end of array for while loop below - - $this->db->sql_freeresult($result); - } - - $i = 0; - while ($row = ($buffer ? $rows[$i++] : $this->db->sql_fetchrow($result))) + foreach ($rows as $row) { // Indexing enabled for this forum - if (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']]) + if (in_array($row['forum_id'], $forums_indexing_enabled, true)) { $this->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); } $row_count++; } - if (!$buffer) - { - $this->db->sql_freeresult($result); - } - $post_counter += $acp_module->batch_size; + $post_counter += self::BATCH_SIZE; } - // save the current state - $acp_module->save_state(); - // pretend the number of posts was as big as the number of ids we indexed so far // just an estimation as it includes deleted posts $num_posts = $this->config['num_posts']; @@ -343,39 +316,41 @@ abstract class base implements search_backend_interface $this->tidy(); $this->config['num_posts'] = $num_posts; - if ($post_counter <= $acp_module->max_post_id) + if ($post_counter <= $max_post_id) { $totaltime = microtime(true) - $starttime; $rows_per_second = $row_count / $totaltime; - meta_refresh(1, $u_action); - trigger_error($this->user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $this->user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); + + return [ + 'row_count' => $row_count, + 'post_counter' => $post_counter, + 'max_post_id' => $max_post_id, + 'rows_per_second' => $rows_per_second, + ]; } + + return null; } /** * {@inheritdoc} */ - public function delete_index($acp_module, $u_action) + public function delete_index(int &$post_counter = null): ?array { + $max_post_id = $this->get_max_post_id(); + $starttime = microtime(true); $row_count = 0; - $post_counter = &$acp_module->state[2]; - while (still_on_time() && $post_counter <= $acp_module->max_post_id) + while (still_on_time() && $post_counter <= $max_post_id) { - $sql = 'SELECT post_id, poster_id, forum_id - FROM ' . POSTS_TABLE . ' - WHERE post_id >= ' . (int) ($post_counter + 1) . ' - AND post_id <= ' . (int) ($post_counter + $acp_module->batch_size); - $result = $this->db->sql_query($sql); - + $rows = $this->get_posts_between($post_counter + 1, $post_counter + self::BATCH_SIZE); $ids = $posters = $forum_ids = array(); - while ($row = $this->db->sql_fetchrow($result)) + foreach ($rows as $row) { $ids[] = $row['post_id']; $posters[] = $row['poster_id']; $forum_ids[] = $row['forum_id']; } - $result->sql_freeresult($result); $row_count += count($ids); if (count($ids)) @@ -383,18 +358,82 @@ abstract class base implements search_backend_interface $this->index_remove($ids, $posters, $forum_ids); } - $post_counter += $acp_module->batch_size; + $post_counter += self::BATCH_SIZE; } - // save the current state - $acp_module->save_state(); - - if ($post_counter <= $acp_module->max_post_id) + if ($post_counter <= $max_post_id) { $totaltime = microtime(true) - $starttime; $rows_per_second = $row_count / $totaltime; - meta_refresh(1, append_sid($u_action)); - trigger_error($this->user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter) . $this->user->lang('SEARCH_INDEX_DELETE_REDIRECT_RATE', $rows_per_second)); + + return [ + 'row_count' => $row_count, + 'post_counter' => $post_counter, + 'max_post_id' => $max_post_id, + 'rows_per_second' => $rows_per_second, + ]; } } + + /** + * Return the ids of the forums that have indexing enabled + * + * @return array + */ + protected function forum_ids_with_indexing_enabled(): array + { + $forums = []; + + $sql = 'SELECT forum_id, enable_indexing + FROM ' . FORUMS_TABLE; + $result = $this->db->sql_query($sql, 3600); + + while ($row = $this->db->sql_fetchrow($result)) + { + if ((bool) $row['enable_indexing']) + { + $forums[] = $row['forum_id']; + } + } + $this->db->sql_freeresult($result); + + return $forums; + } + + /** + * Get posts between 2 ids + * + * @param int $initial_id + * @param int $final_id + * @return \Generator + */ + protected function get_posts_between(int $initial_id, int $final_id): \Generator + { + $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id + FROM ' . POSTS_TABLE . ' + WHERE post_id >= ' . $initial_id . ' + AND post_id <= ' . $final_id; + $result = $this->db->sql_query($sql); + + while($row = $this->db->sql_fetchrow($result)) + { + yield $row; + } + + $this->db->sql_freeresult($result); + } + + /** + * Get post with higher id + */ + protected function get_max_post_id(): int + { + $sql = 'SELECT MAX(post_id) as max_post_id + FROM '. POSTS_TABLE; + $result = $this->db->sql_query($sql); + $max_post_id = (int) $this->db->sql_fetchfield('max_post_id'); + $this->db->sql_freeresult($result); + + return $max_post_id; + } } diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index c42139138d..b35f392578 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -17,6 +17,7 @@ use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\event\dispatcher_interface; use phpbb\user; +use RuntimeException; /** * Fulltext search for MySQL @@ -920,12 +921,12 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function create_index($acp_module, $u_action) + public function create_index(int &$post_counter = null): ?array { // Make sure we can actually use MySQL with fulltext indexes if ($error = $this->init()) { - return $error; + throw new RuntimeException($error); } if (empty($this->stats)) @@ -986,18 +987,18 @@ class fulltext_mysql extends base implements search_backend_interface $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); - return false; + return null; } /** * {@inheritdoc} */ - public function delete_index($acp_module, $u_action) + public function delete_index(int &$post_counter = null): ?array { // Make sure we can actually use MySQL with fulltext indexes if ($error = $this->init()) { - return $error; + throw new RuntimeException($error); } if (empty($this->stats)) @@ -1052,7 +1053,7 @@ class fulltext_mysql extends base implements search_backend_interface $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); - return false; + return null; } /** diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index ec2c9dcf1c..a49d4f59f8 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -1624,7 +1624,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - public function delete_index($acp_module, $u_action) + public function delete_index(int &$post_counter = null): ?array { $sql_queries = []; @@ -1663,6 +1663,8 @@ class fulltext_native extends base implements search_backend_interface { $this->db->sql_query($sql_query); } + + return null; } /** diff --git a/phpBB/phpbb/search/backend/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php index 8692683d96..863c2d43e6 100644 --- a/phpBB/phpbb/search/backend/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -17,6 +17,7 @@ use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\event\dispatcher_interface; use phpbb\user; +use RuntimeException; /** * Fulltext search for PostgreSQL @@ -875,12 +876,12 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function create_index($acp_module, $u_action) + public function create_index(int &$post_counter = null): ?array { // Make sure we can actually use PostgreSQL with fulltext indexes if ($error = $this->init()) { - return $error; + throw new RuntimeException($error); } if (empty($this->stats)) @@ -928,18 +929,18 @@ class fulltext_postgres extends base implements search_backend_interface $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); - return false; + return null; } /** * {@inheritdoc} */ - public function delete_index($acp_module, $u_action) + public function delete_index(int &$post_counter = null): ?array { // Make sure we can actually use PostgreSQL with fulltext indexes if ($error = $this->init()) { - return $error; + throw new RuntimeException($error); } if (empty($this->stats)) @@ -987,7 +988,7 @@ class fulltext_postgres extends base implements search_backend_interface $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); - return false; + return null; } /** diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index 680577d5c1..cd8d2194e1 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -607,21 +607,19 @@ class fulltext_sphinx implements search_backend_interface } /** - * Nothing needs to be destroyed - */ + * Nothing needs to be destroyed + */ public function tidy() { $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) + * {@inheritdoc} + */ + public function create_index(int &$post_counter = null): ?array { - if (!$this->index_created()) + if ($this->index_created()) { $table_data = array( 'COLUMNS' => array( @@ -643,30 +641,23 @@ class fulltext_sphinx implements search_backend_interface $this->db->sql_query($sql); } - return false; + return null; } /** - * Drop sphinx table - * - * @return string|bool error string is returned incase of errors otherwise false + * {@inheritdoc} */ - public function delete_index($acp_module, $u_action) + public function delete_index(int &$post_counter = null): ?array { - if (!$this->index_created()) - { - return false; + if ($this->index_created()) { + $this->db_tools->sql_table_drop(SPHINX_TABLE); } - $this->db_tools->sql_table_drop(SPHINX_TABLE); - - return false; + return null; } /** - * Returns true if the sphinx table was created - * - * @return bool true if sphinx table was created + * {@inheritdoc} */ public function index_created($allow_new_files = true) { diff --git a/phpBB/phpbb/search/backend/search_backend_interface.php b/phpBB/phpbb/search/backend/search_backend_interface.php index 21b8b4dff7..dc874e9460 100644 --- a/phpBB/phpbb/search/backend/search_backend_interface.php +++ b/phpBB/phpbb/search/backend/search_backend_interface.php @@ -15,9 +15,6 @@ namespace phpbb\search\backend; interface search_backend_interface { - // TODO: comprobar los pasos pr referencia - // TODO: eliminar acp_module de create index y delete index - /** * Returns the name of this search backend to be displayed to administrators * @@ -148,16 +145,18 @@ interface search_backend_interface /** * Create fulltext index * - * @return string|bool error string is returned incase of errors otherwise false + * @param int|null $post_counter + * @return array|null array with current status or null if finished */ - public function create_index($acp_module, $u_action); + public function create_index(int &$post_counter = null): ?array; /** * Drop fulltext index * - * @return string|bool error string is returned incase of errors otherwise false + * @param int|null $post_counter + * @return array|null array with current status or null if finished */ - public function delete_index($acp_module, $u_action); + public function delete_index(int &$post_counter = null): ?array; /** * Returns true if both FULLTEXT indexes exist From 5c67eabeedcbeadf923a0cd679af5a95d7e7ff68 Mon Sep 17 00:00:00 2001 From: rubencm Date: Tue, 23 Mar 2021 01:43:01 +0100 Subject: [PATCH 17/22] [ticket/15540] Fix tests PHPBB3-15540 --- phpBB/includes/acp/acp_search.php | 13 ++++++++---- phpBB/includes/mcp/mcp_main.php | 5 ----- phpBB/phpbb/search/backend/base.php | 7 ++++++- phpBB/phpbb/search/backend/fulltext_mysql.php | 2 +- .../phpbb/search/backend/fulltext_sphinx.php | 3 ++- tests/content_visibility/delete_post_test.php | 1 - tests/functional/search/base.php | 20 ++++++++++++++----- tests/mock/user.php | 4 ++-- tests/search/mysql_test.php | 4 +++- tests/search/native_test.php | 4 +++- tests/search/postgres_test.php | 4 +++- 11 files changed, 44 insertions(+), 23 deletions(-) diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 438d798b76..b38e39300c 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -78,7 +78,8 @@ class acp_search foreach ($search_types as $search) { // Only show available search backends - if($search->is_available()) { + if ($search->is_available()) + { $name = $search->get_name(); @@ -88,16 +89,20 @@ class acp_search $identifier = substr($type, strrpos($type, '\\') + 1); $search_options .= ""; - if (method_exists($search, 'acp')) { + if (method_exists($search, 'acp')) + { $vars = $search->acp(); - if (!$submit) { + if (!$submit) + { $template->assign_block_vars('backend', array( 'NAME' => $name, 'SETTINGS' => $vars['tpl'], 'IDENTIFIER' => $identifier, )); - } else if (is_array($vars['config'])) { + } + else if (is_array($vars['config'])) + { $settings = array_merge($settings, $vars['config']); } } diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 5d61ac640d..5e257cfa11 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -1404,11 +1404,6 @@ function mcp_fork_topic($topic_ids) $search_backend_factory = $phpbb_container->get('search.backend_factory'); $search = $search_backend_factory->get_active(); $search_mode = 'post'; - - if ($error) - { - trigger_error($error); - } } else if (!isset($search_type) && !$topic_row['enable_indexing']) { diff --git a/phpBB/phpbb/search/backend/base.php b/phpBB/phpbb/search/backend/base.php index 172edeca4d..f62d798d53 100644 --- a/phpBB/phpbb/search/backend/base.php +++ b/phpBB/phpbb/search/backend/base.php @@ -296,6 +296,11 @@ abstract class base implements search_backend_interface { $rows = $this->get_posts_between($post_counter + 1, $post_counter + self::BATCH_SIZE); + if ($this->db->sql_buffer_nested_transactions()) + { + $rows = iterator_to_array($rows); + } + foreach ($rows as $row) { // Indexing enabled for this forum @@ -415,7 +420,7 @@ abstract class base implements search_backend_interface AND post_id <= ' . $final_id; $result = $this->db->sql_query($sql); - while($row = $this->db->sql_fetchrow($result)) + while ($row = $this->db->sql_fetchrow($result)) { yield $row; } diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index b35f392578..0860d3d7a8 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -123,7 +123,7 @@ class fulltext_mysql extends base implements search_backend_interface public function is_available(): bool { // Check if we are using mysql - if($this->db->get_sql_layer() != 'mysqli') + if ($this->db->get_sql_layer() != 'mysqli') { return false; } diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index cd8d2194e1..a7df8fcb23 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -649,7 +649,8 @@ class fulltext_sphinx implements search_backend_interface */ public function delete_index(int &$post_counter = null): ?array { - if ($this->index_created()) { + if ($this->index_created()) + { $this->db_tools->sql_table_drop(SPHINX_TABLE); } diff --git a/tests/content_visibility/delete_post_test.php b/tests/content_visibility/delete_post_test.php index bba1281551..8f3c6295e6 100644 --- a/tests/content_visibility/delete_post_test.php +++ b/tests/content_visibility/delete_post_test.php @@ -13,7 +13,6 @@ require_once __DIR__ . '/../../phpBB/includes/functions_admin.php'; require_once __DIR__ . '/../../phpBB/includes/functions_posting.php'; -require_once __DIR__ . '/../mock/search.php'; class phpbb_content_visibility_delete_post_test extends phpbb_database_test_case { diff --git a/tests/functional/search/base.php b/tests/functional/search/base.php index b849724bf9..885cd9c684 100644 --- a/tests/functional/search/base.php +++ b/tests/functional/search/base.php @@ -38,7 +38,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case $this->login(); $this->admin_login(); - $this->create_search_index('phpbb\search\backend\fulltext_native'); + $this->create_search_index('phpbb\\search\\backend\\fulltext_native'); $post = $this->create_topic(2, 'Test Topic 1 foosubject', 'This is a test topic posted by the barsearch testing framework.'); @@ -49,18 +49,28 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case if ($values["config[search_type]"] != $this->search_backend) { $values["config[search_type]"] = $this->search_backend; - $form->setValues($values); + + try + { + $form->setValues($values); + } + catch(\InvalidArgumentException $e) + { + // Search backed is not supported because don't appear in the select + $this->delete_topic($post['topic_id']); + $this->markTestSkipped("Search backend is not supported/running"); + } + $crawler = self::submit($form); $form = $crawler->selectButton('Yes')->form(); $values = $form->getValues(); $crawler = self::submit($form); - // check if search backend is not supported + // Unknown error selecting search backend if ($crawler->filter('.errorbox')->count() > 0) { - $this->delete_topic($post['topic_id']); - $this->markTestSkipped("Search backend is not supported/running"); + $this->fail('Error when trying to select available search backend'); } $this->create_search_index(); diff --git a/tests/mock/user.php b/tests/mock/user.php index 5352a22b27..254c02f669 100644 --- a/tests/mock/user.php +++ b/tests/mock/user.php @@ -26,7 +26,7 @@ class phpbb_mock_user public $lang = []; private $options = array(); - public function optionget($item) + public function optionget($item, $data = false) { if (!isset($this->options[$item])) { @@ -36,7 +36,7 @@ class phpbb_mock_user return $this->options[$item]; } - public function optionset($item, $value) + public function optionset($item, $value, $data = false) { $this->options[$item] = $value; } diff --git a/tests/search/mysql_test.php b/tests/search/mysql_test.php index 75f534c328..d8f1ac9e94 100644 --- a/tests/search/mysql_test.php +++ b/tests/search/mysql_test.php @@ -24,13 +24,15 @@ class phpbb_search_mysql_test extends phpbb_search_common_test_case protected function setUp(): void { - global $phpbb_root_path, $phpEx, $config, $user, $cache; + global $phpbb_root_path, $phpEx, $config, $cache; parent::setUp(); // dbal uses cache $cache = new phpbb_mock_cache(); + $user = $this->createMock('\phpbb\user'); + // set config values $config['fulltext_mysql_min_word_len'] = 4; $config['fulltext_mysql_max_word_len'] = 254; diff --git a/tests/search/native_test.php b/tests/search/native_test.php index 652206e1b4..fe2caa6cdd 100644 --- a/tests/search/native_test.php +++ b/tests/search/native_test.php @@ -24,13 +24,15 @@ class phpbb_search_native_test extends phpbb_search_test_case protected function setUp(): void { - global $phpbb_root_path, $phpEx, $config, $user, $cache; + global $phpbb_root_path, $phpEx, $config, $cache; parent::setUp(); // dbal uses cache $cache = new phpbb_mock_cache(); + $user = $this->createMock('\phpbb\user'); + $this->db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_native'); diff --git a/tests/search/postgres_test.php b/tests/search/postgres_test.php index 5f2466a76b..bfb69cf14e 100644 --- a/tests/search/postgres_test.php +++ b/tests/search/postgres_test.php @@ -24,13 +24,15 @@ class phpbb_search_postgres_test extends phpbb_search_common_test_case protected function setUp(): void { - global $phpbb_root_path, $phpEx, $config, $user, $cache; + global $phpbb_root_path, $phpEx, $config, $cache; parent::setUp(); // dbal uses cache $cache = new phpbb_mock_cache(); + $user = $this->createMock('\phpbb\user'); + // set config values $config['fulltext_postgres_min_word_len'] = 4; $config['fulltext_postgres_max_word_len'] = 254; From 656e57fbf642ce366cf48b54a04954a985e2a222 Mon Sep 17 00:00:00 2001 From: rubencm Date: Tue, 23 Mar 2021 04:16:34 +0100 Subject: [PATCH 18/22] [ticket/15540] Properties PHPBB3-15540 --- .../default/container/services_search.yml | 9 ++ phpBB/phpbb/search/backend/base.php | 103 ++++++++++++------ phpBB/phpbb/search/backend/fulltext_mysql.php | 40 +++---- .../phpbb/search/backend/fulltext_native.php | 46 +++----- .../search/backend/fulltext_postgres.php | 43 +++----- .../phpbb/search/backend/fulltext_sphinx.php | 59 ++++++---- tests/search/mysql_test.php | 6 +- tests/search/native_test.php | 6 +- tests/search/postgres_test.php | 6 +- 9 files changed, 173 insertions(+), 145 deletions(-) diff --git a/phpBB/config/default/container/services_search.yml b/phpBB/config/default/container/services_search.yml index 0ec01e187e..ba0f8f2761 100644 --- a/phpBB/config/default/container/services_search.yml +++ b/phpBB/config/default/container/services_search.yml @@ -4,9 +4,11 @@ services: search.fulltext.native: class: phpbb\search\backend\fulltext_native arguments: + - '@cache' - '@config' - '@dbal.conn' - '@dispatcher' + - '@language' - '@user' - '%core.root_path%' - '%core.php_ext%' @@ -16,9 +18,11 @@ services: search.fulltext.mysql: class: phpbb\search\backend\fulltext_mysql arguments: + - '@cache' - '@config' - '@dbal.conn' - '@dispatcher' + - '@language' - '@user' - '%core.root_path%' - '%core.php_ext%' @@ -28,9 +32,11 @@ services: search.fulltext.postgres: class: phpbb\search\backend\fulltext_postgres arguments: + - '@cache' - '@config' - '@dbal.conn' - '@dispatcher' + - '@language' - '@user' - '%core.root_path%' - '%core.php_ext%' @@ -43,7 +49,10 @@ services: - '@auth' - '@config' - '@dbal.conn' + - '@dbal.tools' - '@dispatcher' + - '@language' + - '@log' - '@user' - '%core.root_path%' - '%core.php_ext%' diff --git a/phpBB/phpbb/search/backend/base.php b/phpBB/phpbb/search/backend/base.php index f62d798d53..52a4448a45 100644 --- a/phpBB/phpbb/search/backend/base.php +++ b/phpBB/phpbb/search/backend/base.php @@ -13,6 +13,11 @@ namespace phpbb\search\backend; +use phpbb\cache\service; +use phpbb\config\config; +use phpbb\db\driver\driver_interface; +use phpbb\user; + /** * optional base class for search plugins providing simple caching based on ACM * and functions to retrieve ignore_words and synonyms @@ -26,6 +31,42 @@ abstract class base implements search_backend_interface // Batch size for create_index and delete_index private const BATCH_SIZE = 100; + /** + * @var service + */ + protected $cache; + + /** + * @var config + */ + protected $config; + + /** + * @var driver_interface + */ + protected $db; + + /** + * @var user + */ + protected $user; + + /** + * Constructor. + * + * @param service $cache + * @param config $config + * @param driver_interface $db + * @param user $user + */ + public function __construct(service $cache, config $config, driver_interface $db, user $user) + { + $this->cache = $cache; + $this->config = $config; + $this->db = $db; + $this->user = $user; + } + /** * Retrieves cached search results * @@ -40,9 +81,7 @@ abstract class base implements search_backend_interface */ protected function obtain_ids(string $search_key, &$result_count, &$id_ary, &$start, $per_page, string $sort_dir): int { - global $cache; - - if (!($stored_ids = $cache->get('_search_results_' . $search_key))) + if (!($stored_ids = $this->cache->get('_search_results_' . $search_key))) { // no search results cached for this search_key return self::SEARCH_RESULT_NOT_IN_CACHE; @@ -121,9 +160,9 @@ abstract class base implements search_backend_interface */ protected function save_ids(string $search_key, string $keywords, $author_ary, int $result_count, &$id_ary, int $start, string $sort_dir) { - global $cache, $config, $db, $user; + global $user; - $length = min(count($id_ary), $config['search_block_size']); + $length = min(count($id_ary), $this->config['search_block_size']); // nothing to cache so exit if (!$length) @@ -135,17 +174,17 @@ abstract class base implements search_backend_interface // 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))) + if (!($store = $this->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); + WHERE search_key = \'' . $this->db->sql_escape($search_key) . '\''; + $result = $this->db->sql_query($sql); - if (!$db->sql_fetchrow($result)) + if (!$this->db->sql_fetchrow($result)) { $sql_ary = array( 'search_key' => $search_key, @@ -154,16 +193,16 @@ abstract class base implements search_backend_interface 'search_authors' => ' ' . implode(' ', $author_ary) . ' ' ); - $sql = 'INSERT INTO ' . SEARCH_RESULTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); - $db->sql_query($sql); + $sql = 'INSERT INTO ' . SEARCH_RESULTS_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary); + $this->db->sql_query($sql); } - $db->sql_freeresult($result); + $this->db->sql_freeresult($result); } $sql = 'UPDATE ' . USERS_TABLE . ' SET user_last_search = ' . time() . ' WHERE user_id = ' . $user->data['user_id']; - $db->sql_query($sql); + $this->db->sql_query($sql); $store = array(-1 => $result_count, -2 => $sort_dir); $id_range = range($start, $start + $length - 1); @@ -191,10 +230,10 @@ abstract class base implements search_backend_interface $store += $store_ids; // if the cache is too big - if (count($store) - 2 > 20 * $config['search_block_size']) + if (count($store) - 2 > 20 * $this->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++) + for ($i = 0, $n = $id_range[0] - 2 * $this->config['search_block_size']; $i < $n; $i++) { if (isset($store[$i])) { @@ -204,7 +243,7 @@ abstract class base implements search_backend_interface // 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--) + for ($i = $store[-1] - 1, $n = current($id_range) + 2 * $this->config['search_block_size']; $i > $n; $i--) { if (isset($store[$i])) { @@ -212,12 +251,12 @@ abstract class base implements search_backend_interface } } } - $cache->put('_search_results_' . $search_key, $store, $config['search_store_results']); + $this->cache->put('_search_results_' . $search_key, $store, $this->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); + WHERE search_key = \'' . $this->db->sql_escape($search_key) . '\''; + $this->db->sql_query($sql); } unset($store, $store_ids, $id_range); @@ -231,27 +270,25 @@ abstract class base implements search_backend_interface */ protected function destroy_cache($words, $authors = false): void { - 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_where .= " OR search_keywords " . $this->db->sql_like_expression($this->db->get_any_char() . $word . $this->db->get_any_char()); } $sql = 'SELECT search_key FROM ' . SEARCH_RESULTS_TABLE . " WHERE search_keywords LIKE '%*%' $sql_where"; - $result = $db->sql_query($sql); + $result = $this->db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) + while ($row = $this->db->sql_fetchrow($result)) { - $cache->destroy('_search_results_' . $row['search_key']); + $this->cache->destroy('_search_results_' . $row['search_key']); } - $db->sql_freeresult($result); + $this->db->sql_freeresult($result); } // clear all searches that searched for the specified authors @@ -260,25 +297,25 @@ abstract class base implements search_backend_interface $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_where .= (($sql_where) ? ' OR ' : '') . 'search_authors ' . $this->db->sql_like_expression($this->db->get_any_char() . ' ' . (int) $author . ' ' . $this->db->get_any_char()); } $sql = 'SELECT search_key FROM ' . SEARCH_RESULTS_TABLE . " WHERE $sql_where"; - $result = $db->sql_query($sql); + $result = $this->db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) + while ($row = $this->db->sql_fetchrow($result)) { - $cache->destroy('_search_results_' . $row['search_key']); + $this->cache->destroy('_search_results_' . $row['search_key']); } - $db->sql_freeresult($result); + $this->db->sql_freeresult($result); } $sql = 'DELETE FROM ' . SEARCH_RESULTS_TABLE . ' - WHERE search_time < ' . (time() - (int) $config['search_store_results']); - $db->sql_query($sql); + WHERE search_time < ' . (time() - (int) $this->config['search_store_results']); + $this->db->sql_query($sql); } /** diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index 0860d3d7a8..8471d16ed6 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -13,9 +13,11 @@ namespace phpbb\search\backend; +use phpbb\cache\service; use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\event\dispatcher_interface; +use phpbb\language\language; use phpbb\user; use RuntimeException; @@ -36,18 +38,6 @@ class fulltext_mysql extends base implements search_backend_interface */ protected $split_words = array(); - /** - * Config object - * @var config - */ - protected $config; - - /** - * Database connection - * @var driver_interface - */ - protected $db; - /** * phpBB event dispatcher object * @var dispatcher_interface @@ -55,10 +45,9 @@ class fulltext_mysql extends base implements search_backend_interface protected $phpbb_dispatcher; /** - * User object - * @var user + * @var language */ - protected $user; + protected $language; /** * Associative array stores the min and max word length to be searched @@ -84,19 +73,20 @@ class fulltext_mysql extends base implements search_backend_interface * Constructor * Creates a new \phpbb\search\backend\fulltext_mysql, which is used as a search backend * + * @param service $cache * @param config $config Config object * @param driver_interface $db Database object * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object + * @param language $language * @param user $user User object * @param string $phpbb_root_path Relative path to phpBB root * @param string $phpEx PHP file extension */ - public function __construct(config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, user $user, string $phpbb_root_path, string $phpEx) + public function __construct(service $cache, config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, language $language, user $user, string $phpbb_root_path, string $phpEx) { - $this->config = $config; - $this->db = $db; + parent::__construct($cache, $config, $db, $user); $this->phpbb_dispatcher = $phpbb_dispatcher; - $this->user = $user; + $this->language = $language; $this->word_length = array('min' => $this->config['fulltext_mysql_min_word_len'], 'max' => $this->config['fulltext_mysql_max_word_len']); @@ -138,7 +128,7 @@ class fulltext_mysql extends base implements search_backend_interface { if (!$this->is_available()) { - return $this->user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE']; + return $this->language->lang('FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE'); } $result = $this->db->sql_query('SHOW TABLE STATUS LIKE \'' . POSTS_TABLE . '\''); @@ -159,7 +149,7 @@ class fulltext_mysql extends base implements search_backend_interface if (!$fulltext_supported) { - return $this->user->lang['FULLTEXT_MYSQL_NOT_SUPPORTED']; + return $this->language->lang('FULLTEXT_MYSQL_NOT_SUPPORTED'); } $sql = 'SHOW VARIABLES @@ -236,7 +226,7 @@ class fulltext_mysql extends base implements search_backend_interface // We limit the number of allowed keywords to minimize load on the database 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'], count($this->split_words))); + trigger_error($this->language->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 @@ -1080,7 +1070,7 @@ class fulltext_mysql extends base implements search_backend_interface } return array( - $this->user->lang['FULLTEXT_MYSQL_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0, + $this->language->lang('FULLTEXT_MYSQL_TOTAL_POSTS') => ($this->index_created()) ? $this->stats['total_posts'] : 0, ); } @@ -1160,11 +1150,11 @@ class fulltext_mysql extends base implements search_backend_interface { $tpl = '

-

' . $this->user->lang['FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN'] . '
+

' . $this->language->lang('FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN') . '
' . $this->config['fulltext_mysql_min_word_len'] . '
-

' . $this->user->lang['FULLTEXT_MYSQL_MAX_SEARCH_CHARS_EXPLAIN'] . '
+

' . $this->language->lang('FULLTEXT_MYSQL_MAX_SEARCH_CHARS_EXPLAIN') . '
' . $this->config['fulltext_mysql_max_word_len'] . '
'; diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index a49d4f59f8..56075186ae 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -13,9 +13,11 @@ namespace phpbb\search\backend; +use phpbb\cache\service; use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\event\dispatcher_interface; +use phpbb\language\language; use phpbb\user; /** @@ -86,18 +88,6 @@ class fulltext_native extends base implements search_backend_interface */ protected $php_ext; - /** - * Config object - * @var config - */ - protected $config; - - /** - * Database connection - * @var driver_interface - */ - protected $db; - /** * phpBB event dispatcher object * @var dispatcher_interface @@ -105,27 +95,27 @@ class fulltext_native extends base implements search_backend_interface protected $phpbb_dispatcher; /** - * User object - * @var user + * @var language */ - protected $user; + protected $language; /** * Initialises the fulltext_native search backend with min/max word length * + * @param service $cache * @param config $config Config object * @param driver_interface $db Database object * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object + * @param language $language * @param user $user User object * @param string $phpbb_root_path phpBB root path * @param string $phpEx PHP file extension */ - public function __construct(config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, user $user, string $phpbb_root_path, string $phpEx) + public function __construct(service $cache, config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, language $language, user $user, string $phpbb_root_path, string $phpEx) { - $this->config = $config; - $this->db = $db; + parent::__construct($cache, $config, $db, $user); $this->phpbb_dispatcher = $phpbb_dispatcher; - $this->user = $user; + $this->language = $language; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $phpEx; @@ -304,7 +294,7 @@ class fulltext_native extends base implements search_backend_interface // 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']) { - trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], $num_keywords)); + trigger_error($this->language->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], $num_keywords)); } // $keywords input format: each word separated by a space, words in a bracket are not separated @@ -478,7 +468,7 @@ class fulltext_native extends base implements search_backend_interface // throw an error if we shall not ignore unexistant 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))); + trigger_error(sprintf($this->language->lang('WORDS_IN_NO_POST'), implode($this->language->lang('COMMA_SEPARATOR'), $non_common_words))); } unset($non_common_words); } @@ -1691,8 +1681,8 @@ class fulltext_native extends base implements search_backend_interface } return array( - $this->user->lang['TOTAL_WORDS'] => $this->stats['total_words'], - $this->user->lang['TOTAL_MATCHES'] => $this->stats['total_matches']); + $this->language->lang('TOTAL_WORDS') => $this->stats['total_words'], + $this->language->lang('TOTAL_MATCHES') => $this->stats['total_matches']); } /** @@ -2026,19 +2016,19 @@ class fulltext_native extends base implements search_backend_interface $tpl = '
-

' . $this->user->lang['YES_SEARCH_UPDATE_EXPLAIN'] . '
-
+

' . $this->language->lang('YES_SEARCH_UPDATE_EXPLAIN') . '
+
-

' . $this->user->lang['MIN_SEARCH_CHARS_EXPLAIN'] . '
+

' . $this->language->lang('MIN_SEARCH_CHARS_EXPLAIN') . '
-

' . $this->user->lang['MAX_SEARCH_CHARS_EXPLAIN'] . '
+

' . $this->language->lang('MAX_SEARCH_CHARS_EXPLAIN') . '
-

' . $this->user->lang['COMMON_WORD_THRESHOLD_EXPLAIN'] . '
+

' . $this->language->lang('COMMON_WORD_THRESHOLD_EXPLAIN') . '
%
'; diff --git a/phpBB/phpbb/search/backend/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php index 863c2d43e6..7ffb9da857 100644 --- a/phpBB/phpbb/search/backend/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -13,9 +13,11 @@ namespace phpbb\search\backend; +use phpbb\cache\service; use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\event\dispatcher_interface; +use phpbb\language\language; use phpbb\user; use RuntimeException; @@ -49,18 +51,6 @@ class fulltext_postgres extends base implements search_backend_interface */ protected $phrase_search = false; - /** - * Config object - * @var config - */ - protected $config; - - /** - * Database connection - * @var driver_interface - */ - protected $db; - /** * phpBB event dispatcher object * @var dispatcher_interface @@ -68,11 +58,9 @@ class fulltext_postgres extends base implements search_backend_interface protected $phpbb_dispatcher; /** - * User object - * @var user + * @var language */ - protected $user; - + protected $language; /** * Contains tidied search query. * Operators are prefixed in search query and common words excluded @@ -97,19 +85,20 @@ class fulltext_postgres extends base implements search_backend_interface * Constructor * Creates a new \phpbb\search\backend\fulltext_postgres, which is used as a search backend * + * @param service $cache * @param config $config Config object * @param driver_interface $db Database object * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object + * @param language $language * @param user $user User object * @param string $phpbb_root_path Relative path to phpBB root * @param string $phpEx PHP file extension */ - public function __construct(config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, user $user, string $phpbb_root_path, string $phpEx) + public function __construct(service $cache, config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, language $language, user $user, string $phpbb_root_path, string $phpEx) { - $this->config = $config; - $this->db = $db; + parent::__construct($cache, $config, $db, $user); $this->phpbb_dispatcher = $phpbb_dispatcher; - $this->user = $user; + $this->language = $language; $this->word_length = array('min' => $this->config['fulltext_postgres_min_word_len'], 'max' => $this->config['fulltext_postgres_max_word_len']); @@ -145,7 +134,7 @@ class fulltext_postgres extends base implements search_backend_interface { if (!$this->is_available()) { - return $this->user->lang['FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE']; + return $this->language->lang('FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE'); } return false; @@ -1015,7 +1004,7 @@ class fulltext_postgres extends base implements search_backend_interface } return array( - $this->user->lang['FULLTEXT_POSTGRES_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0, + $this->language->lang('FULLTEXT_POSTGRES_TOTAL_POSTS') => ($this->index_created()) ? $this->stats['total_posts'] : 0, ); } @@ -1096,11 +1085,11 @@ class fulltext_postgres extends base implements search_backend_interface { $tpl = '
-

' . $this->user->lang['FULLTEXT_POSTGRES_VERSION_CHECK_EXPLAIN'] . '
-
' . (($this->db->get_sql_layer() == 'postgres') ? $this->user->lang['YES'] : $this->user->lang['NO']) . '
+

' . $this->language->lang('FULLTEXT_POSTGRES_VERSION_CHECK_EXPLAIN') . '
+
' . (($this->db->get_sql_layer() == 'postgres') ? $this->language->lang('YES') : $this->language->lang('NO')) . '
-

' . $this->user->lang['FULLTEXT_POSTGRES_TS_NAME_EXPLAIN'] . '
+

' . $this->language->lang('FULLTEXT_POSTGRES_TS_NAME_EXPLAIN') . '
-

' . $this->user->lang['FULLTEXT_POSTGRES_MIN_WORD_LEN_EXPLAIN'] . '
+

' . $this->language->lang('FULLTEXT_POSTGRES_MIN_WORD_LEN_EXPLAIN') . '
-

' . $this->user->lang['FULLTEXT_POSTGRES_MAX_WORD_LEN_EXPLAIN'] . '
+

' . $this->language->lang('FULLTEXT_POSTGRES_MAX_WORD_LEN_EXPLAIN') . '
'; diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index a7df8fcb23..cb376c1502 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -14,10 +14,13 @@ namespace phpbb\search\backend; use phpbb\auth\auth; +use phpbb\cache\service; use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\db\tools\tools_interface; use phpbb\event\dispatcher_interface; +use phpbb\language\language; +use phpbb\log\log; use phpbb\user; /** @@ -108,6 +111,16 @@ class fulltext_sphinx implements search_backend_interface */ protected $phpbb_dispatcher; + /** + * @var language + */ + protected $language; + + /** + * @var log + */ + protected $log; + /** * User object * @var user @@ -134,26 +147,28 @@ class fulltext_sphinx implements search_backend_interface * @param auth $auth Auth object * @param config $config Config object * @param driver_interface $db Database object + * @param tools_interface $db_tools * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object + * @param language $language + * @param log $log * @param user $user User object * @param string $phpbb_root_path Relative path to phpBB root * @param string $phpEx PHP file extension - * @throws \Exception */ - public function __construct(auth $auth, config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, user $user, string $phpbb_root_path, string $phpEx) + public function __construct(auth $auth, config $config, driver_interface $db, tools_interface $db_tools, dispatcher_interface $phpbb_dispatcher, language $language, log $log, user $user, string $phpbb_root_path, string $phpEx) { $this->auth = $auth; $this->config = $config; $this->db = $db; $this->phpbb_dispatcher = $phpbb_dispatcher; + $this->language = $language; + $this->log = $log; $this->user = $user; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $phpEx; - // Initialize \phpbb\db\tools\tools object - global $phpbb_container; // TODO inject into object - $this->db_tools = $phpbb_container->get('dbal.tools'); + $this->db_tools = $db_tools; if (!$this->config['fulltext_sphinx_id']) { @@ -196,7 +211,7 @@ class fulltext_sphinx implements search_backend_interface { if (!$this->is_available()) { - return $this->user->lang['FULLTEXT_SPHINX_WRONG_DATABASE']; + return $this->language->lang('FULLTEXT_SPHINX_WRONG_DATABASE'); } // Move delta to main index each hour @@ -268,8 +283,6 @@ class fulltext_sphinx implements search_backend_interface */ 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)) { @@ -450,14 +463,14 @@ class fulltext_sphinx implements search_backend_interface if ($this->sphinx->GetLastError()) { - $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_SPHINX_ERROR', false, array($this->sphinx->GetLastError())); + $this->log->add('critical', $this->user->data['user_id'], $this->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())); + trigger_error($this->language->lang('SPHINX_SEARCH_FAILED', $this->sphinx->GetLastError())); } else { - trigger_error($this->user->lang('SPHINX_SEARCH_FAILED_LOG')); + trigger_error($this->language->lang('SPHINX_SEARCH_FAILED_LOG')); } } @@ -683,9 +696,9 @@ class fulltext_sphinx implements search_backend_interface } 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, + $this->language->lang('FULLTEXT_SPHINX_MAIN_POSTS') => ($this->index_created()) ? $this->stats['main_posts'] : 0, + $this->language->lang('FULLTEXT_SPHINX_DELTA_POSTS') => ($this->index_created()) ? $this->stats['total_posts'] - $this->stats['main_posts'] : 0, + $this->language->lang('FULLTEXT_MYSQL_TOTAL_POSTS') => ($this->index_created()) ? $this->stats['total_posts'] : 0, ); } @@ -781,25 +794,25 @@ class fulltext_sphinx implements search_backend_interface ); $tpl = ' - ' . $this->user->lang['FULLTEXT_SPHINX_CONFIGURE']. ' + ' . $this->language->lang('FULLTEXT_SPHINX_CONFIGURE'). '
-

' . $this->user->lang['FULLTEXT_SPHINX_DATA_PATH_EXPLAIN'] . '
+

' . $this->language->lang('FULLTEXT_SPHINX_DATA_PATH_EXPLAIN') . '
-

' . $this->user->lang['FULLTEXT_SPHINX_HOST_EXPLAIN'] . '
+

' . $this->language->lang('FULLTEXT_SPHINX_HOST_EXPLAIN') . '
-

' . $this->user->lang['FULLTEXT_SPHINX_PORT_EXPLAIN'] . '
+

' . $this->language->lang('FULLTEXT_SPHINX_PORT_EXPLAIN') . '
-

' . $this->user->lang['FULLTEXT_SPHINX_INDEXER_MEM_LIMIT_EXPLAIN'] . '
-
' . $this->user->lang['MIB'] . '
+

' . $this->language->lang('FULLTEXT_SPHINX_INDEXER_MEM_LIMIT_EXPLAIN') . '
+
' . $this->language->lang('MIB') . '
-

' . $this->user->lang['FULLTEXT_SPHINX_CONFIG_FILE_EXPLAIN'] . '
+

' . $this->language->lang('FULLTEXT_SPHINX_CONFIG_FILE_EXPLAIN') . '
' . (($this->config_generate()) ? '' : $this->config_file_data) . '
'; @@ -829,14 +842,14 @@ class fulltext_sphinx implements search_backend_interface } else { - $this->config_file_data = $this->user->lang('FULLTEXT_SPHINX_WRONG_DATABASE'); + $this->config_file_data = $this->language->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'); + $this->config_file_data = $this->language->lang('FULLTEXT_SPHINX_NO_CONFIG_DATA'); return false; } diff --git a/tests/search/mysql_test.php b/tests/search/mysql_test.php index d8f1ac9e94..513135bac1 100644 --- a/tests/search/mysql_test.php +++ b/tests/search/mysql_test.php @@ -29,8 +29,8 @@ class phpbb_search_mysql_test extends phpbb_search_common_test_case parent::setUp(); // dbal uses cache - $cache = new phpbb_mock_cache(); - + $cache = $this->createMock('\phpbb\cache\service'); + $language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); $user = $this->createMock('\phpbb\user'); // set config values @@ -40,6 +40,6 @@ class phpbb_search_mysql_test extends phpbb_search_common_test_case $this->db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_mysql'); - $this->search = new $class($config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); + $this->search = new $class($cache, $config, $this->db, $phpbb_dispatcher, $language, $user, $phpbb_root_path, $phpEx); } } diff --git a/tests/search/native_test.php b/tests/search/native_test.php index fe2caa6cdd..015d8f0b27 100644 --- a/tests/search/native_test.php +++ b/tests/search/native_test.php @@ -29,8 +29,8 @@ class phpbb_search_native_test extends phpbb_search_test_case parent::setUp(); // dbal uses cache - $cache = new phpbb_mock_cache(); - + $cache = $this->createMock('\phpbb\cache\service'); + $language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); $user = $this->createMock('\phpbb\user'); $this->db = $this->new_dbal(); @@ -38,7 +38,7 @@ class phpbb_search_native_test extends phpbb_search_test_case $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_native'); $config['fulltext_native_min_chars'] = 2; $config['fulltext_native_max_chars'] = 14; - $this->search = new $class($config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); + $this->search = new $class($cache, $config, $this->db, $phpbb_dispatcher, $language, $user, $phpbb_root_path, $phpEx); } public function keywords() diff --git a/tests/search/postgres_test.php b/tests/search/postgres_test.php index bfb69cf14e..b4dbb507b3 100644 --- a/tests/search/postgres_test.php +++ b/tests/search/postgres_test.php @@ -29,8 +29,8 @@ class phpbb_search_postgres_test extends phpbb_search_common_test_case parent::setUp(); // dbal uses cache - $cache = new phpbb_mock_cache(); - + $cache = $this->createMock('\phpbb\cache\service'); + $language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); $user = $this->createMock('\phpbb\user'); // set config values @@ -40,6 +40,6 @@ class phpbb_search_postgres_test extends phpbb_search_common_test_case $this->db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_postgres'); - $this->search = new $class($config, $this->db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); + $this->search = new $class($cache, $config, $this->db, $phpbb_dispatcher, $language, $user, $phpbb_root_path, $phpEx); } } From cd8c09d0b3f32ad3d14b22bb101ccfdbe5da3c1d Mon Sep 17 00:00:00 2001 From: rubencm Date: Tue, 23 Mar 2021 04:35:32 +0100 Subject: [PATCH 19/22] [ticket/15540] Fix test PHPBB3-15540 --- .../default/container/services_search.yml | 3 --- phpBB/phpbb/cache/service.php | 18 ++++++++++-------- .../install_data/task/create_search_index.php | 17 ++++++++--------- phpBB/phpbb/search/backend/fulltext_mysql.php | 6 +++--- phpBB/phpbb/search/backend/fulltext_native.php | 6 +++--- .../phpbb/search/backend/fulltext_postgres.php | 6 +++--- phpBB/phpbb/search/backend/fulltext_sphinx.php | 1 - tests/search/mysql_test.php | 2 +- tests/search/native_test.php | 2 +- tests/search/postgres_test.php | 2 +- 10 files changed, 30 insertions(+), 33 deletions(-) diff --git a/phpBB/config/default/container/services_search.yml b/phpBB/config/default/container/services_search.yml index ba0f8f2761..f056f71295 100644 --- a/phpBB/config/default/container/services_search.yml +++ b/phpBB/config/default/container/services_search.yml @@ -4,7 +4,6 @@ services: search.fulltext.native: class: phpbb\search\backend\fulltext_native arguments: - - '@cache' - '@config' - '@dbal.conn' - '@dispatcher' @@ -18,7 +17,6 @@ services: search.fulltext.mysql: class: phpbb\search\backend\fulltext_mysql arguments: - - '@cache' - '@config' - '@dbal.conn' - '@dispatcher' @@ -32,7 +30,6 @@ services: search.fulltext.postgres: class: phpbb\search\backend\fulltext_postgres arguments: - - '@cache' - '@config' - '@dbal.conn' - '@dispatcher' diff --git a/phpBB/phpbb/cache/service.php b/phpBB/phpbb/cache/service.php index bce0c8d6d8..7534c417e8 100644 --- a/phpBB/phpbb/cache/service.php +++ b/phpBB/phpbb/cache/service.php @@ -13,6 +13,8 @@ namespace phpbb\cache; +use phpbb\cache\driver\driver_interface; +use phpbb\config\config; use phpbb\json\sanitizer as json_sanitizer; /** @@ -23,14 +25,14 @@ class service /** * Cache driver. * - * @var \phpbb\cache\driver\driver_interface + * @var driver_interface */ protected $driver; /** * The config. * - * @var \phpbb\config\config + * @var config */ protected $config; @@ -58,13 +60,13 @@ class service /** * Creates a cache service around a cache driver * - * @param \phpbb\cache\driver\driver_interface $driver The cache driver - * @param \phpbb\config\config $config The config + * @param driver_interface $driver The cache driver + * @param config $config The config * @param \phpbb\db\driver\driver_interface $db Database connection * @param string $phpbb_root_path Root path * @param string $php_ext PHP file extension */ - public function __construct(\phpbb\cache\driver\driver_interface $driver, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, $phpbb_root_path, $php_ext) + public function __construct(driver_interface $driver, config $config, \phpbb\db\driver\driver_interface $db, $phpbb_root_path, $php_ext) { $this->set_driver($driver); $this->config = $config; @@ -76,7 +78,7 @@ class service /** * Returns the cache driver used by this cache service. * - * @return \phpbb\cache\driver\driver_interface The cache driver + * @return driver_interface The cache driver */ public function get_driver() { @@ -86,9 +88,9 @@ class service /** * Replaces the cache driver used by this cache service. * - * @param \phpbb\cache\driver\driver_interface $driver The cache driver + * @param driver_interface $driver The cache driver */ - public function set_driver(\phpbb\cache\driver\driver_interface $driver) + public function set_driver(driver_interface $driver) { $this->driver = $driver; } diff --git a/phpBB/phpbb/install/module/install_data/task/create_search_index.php b/phpBB/phpbb/install/module/install_data/task/create_search_index.php index ce74b220d8..bceeb3a8e1 100644 --- a/phpBB/phpbb/install/module/install_data/task/create_search_index.php +++ b/phpBB/phpbb/install/module/install_data/task/create_search_index.php @@ -98,12 +98,12 @@ class create_search_index extends database_task /** * Constructor * - * @param config $config Installer config. - * @param database $db_helper Database helper. - * @param container_factory $container Installer's DI container - * @param iohandler_interface $iohandler IO manager. - * @param string $phpbb_root_path phpBB root path - * @param string $php_ext PHP file extension + * @param config $config Installer config. + * @param database $db_helper Database helper. + * @param container_factory $container Installer's DI container + * @param iohandler_interface $iohandler IO manager. + * @param string $phpbb_root_path phpBB root path + * @param string $php_ext PHP file extension */ public function __construct( config $config, @@ -127,11 +127,11 @@ class create_search_index extends database_task $this->posts_table = $container->get_parameter('tables.posts'); - // Esto se cargara por servicio abajo $this->search_indexer = new fulltext_native( $this->config, $this->db, $this->phpbb_dispatcher, + $container->get('language'), $this->user, $this->phpbb_root_path, $this->php_ext @@ -148,7 +148,6 @@ class create_search_index extends database_task // Make sure fulltext native load update is set $this->config->set('fulltext_native_load_upd', 1); - // TODO: Replace this with create_index() when it don't depend on acp try { $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id FROM ' . $this->posts_table; @@ -181,7 +180,7 @@ class create_search_index extends database_task /** * {@inheritdoc} */ - static public function get_step_count() : int + public static function get_step_count() : int { return 1; } diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index 8471d16ed6..71468debd4 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -13,7 +13,6 @@ namespace phpbb\search\backend; -use phpbb\cache\service; use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\event\dispatcher_interface; @@ -73,7 +72,6 @@ class fulltext_mysql extends base implements search_backend_interface * Constructor * Creates a new \phpbb\search\backend\fulltext_mysql, which is used as a search backend * - * @param service $cache * @param config $config Config object * @param driver_interface $db Database object * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object @@ -82,8 +80,10 @@ class fulltext_mysql extends base implements search_backend_interface * @param string $phpbb_root_path Relative path to phpBB root * @param string $phpEx PHP file extension */ - public function __construct(service $cache, config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, language $language, user $user, string $phpbb_root_path, string $phpEx) + public function __construct(config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, language $language, user $user, string $phpbb_root_path, string $phpEx) { + global $cache; + parent::__construct($cache, $config, $db, $user); $this->phpbb_dispatcher = $phpbb_dispatcher; $this->language = $language; diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index 56075186ae..ccbdc08a2d 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -13,7 +13,6 @@ namespace phpbb\search\backend; -use phpbb\cache\service; use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\event\dispatcher_interface; @@ -102,7 +101,6 @@ class fulltext_native extends base implements search_backend_interface /** * Initialises the fulltext_native search backend with min/max word length * - * @param service $cache * @param config $config Config object * @param driver_interface $db Database object * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object @@ -111,8 +109,10 @@ class fulltext_native extends base implements search_backend_interface * @param string $phpbb_root_path phpBB root path * @param string $phpEx PHP file extension */ - public function __construct(service $cache, config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, language $language, user $user, string $phpbb_root_path, string $phpEx) + public function __construct(config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, language $language, user $user, string $phpbb_root_path, string $phpEx) { + global $cache; + parent::__construct($cache, $config, $db, $user); $this->phpbb_dispatcher = $phpbb_dispatcher; $this->language = $language; diff --git a/phpBB/phpbb/search/backend/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php index 7ffb9da857..90f7771426 100644 --- a/phpBB/phpbb/search/backend/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -13,7 +13,6 @@ namespace phpbb\search\backend; -use phpbb\cache\service; use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\event\dispatcher_interface; @@ -85,7 +84,6 @@ class fulltext_postgres extends base implements search_backend_interface * Constructor * Creates a new \phpbb\search\backend\fulltext_postgres, which is used as a search backend * - * @param service $cache * @param config $config Config object * @param driver_interface $db Database object * @param dispatcher_interface $phpbb_dispatcher Event dispatcher object @@ -94,8 +92,10 @@ class fulltext_postgres extends base implements search_backend_interface * @param string $phpbb_root_path Relative path to phpBB root * @param string $phpEx PHP file extension */ - public function __construct(service $cache, config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, language $language, user $user, string $phpbb_root_path, string $phpEx) + public function __construct(config $config, driver_interface $db, dispatcher_interface $phpbb_dispatcher, language $language, user $user, string $phpbb_root_path, string $phpEx) { + global $cache; + parent::__construct($cache, $config, $db, $user); $this->phpbb_dispatcher = $phpbb_dispatcher; $this->language = $language; diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index cb376c1502..8a493a4dc3 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -14,7 +14,6 @@ namespace phpbb\search\backend; use phpbb\auth\auth; -use phpbb\cache\service; use phpbb\config\config; use phpbb\db\driver\driver_interface; use phpbb\db\tools\tools_interface; diff --git a/tests/search/mysql_test.php b/tests/search/mysql_test.php index 513135bac1..1e822b92af 100644 --- a/tests/search/mysql_test.php +++ b/tests/search/mysql_test.php @@ -40,6 +40,6 @@ class phpbb_search_mysql_test extends phpbb_search_common_test_case $this->db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_mysql'); - $this->search = new $class($cache, $config, $this->db, $phpbb_dispatcher, $language, $user, $phpbb_root_path, $phpEx); + $this->search = new $class($config, $this->db, $phpbb_dispatcher, $language, $user, $phpbb_root_path, $phpEx); } } diff --git a/tests/search/native_test.php b/tests/search/native_test.php index 015d8f0b27..6d8a03f4aa 100644 --- a/tests/search/native_test.php +++ b/tests/search/native_test.php @@ -38,7 +38,7 @@ class phpbb_search_native_test extends phpbb_search_test_case $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_native'); $config['fulltext_native_min_chars'] = 2; $config['fulltext_native_max_chars'] = 14; - $this->search = new $class($cache, $config, $this->db, $phpbb_dispatcher, $language, $user, $phpbb_root_path, $phpEx); + $this->search = new $class($config, $this->db, $phpbb_dispatcher, $language, $user, $phpbb_root_path, $phpEx); } public function keywords() diff --git a/tests/search/postgres_test.php b/tests/search/postgres_test.php index b4dbb507b3..545ffafd50 100644 --- a/tests/search/postgres_test.php +++ b/tests/search/postgres_test.php @@ -40,6 +40,6 @@ class phpbb_search_postgres_test extends phpbb_search_common_test_case $this->db = $this->new_dbal(); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); $class = self::get_search_wrapper('\phpbb\search\backend\fulltext_postgres'); - $this->search = new $class($cache, $config, $this->db, $phpbb_dispatcher, $language, $user, $phpbb_root_path, $phpEx); + $this->search = new $class($config, $this->db, $phpbb_dispatcher, $language, $user, $phpbb_root_path, $phpEx); } } From a8de540e931286752d8ac7558a3055ec09ff6227 Mon Sep 17 00:00:00 2001 From: rubencm Date: Tue, 23 Mar 2021 11:16:53 +0100 Subject: [PATCH 20/22] [ticket/15540] Trigger errors when search module not found PHPBB3-15540 --- phpBB/includes/acp/acp_main.php | 18 ++++++++++++++++-- phpBB/includes/functions_admin.php | 18 ++++++++++++++++-- phpBB/includes/functions_posting.php | 18 ++++++++++++++++-- phpBB/includes/mcp/mcp_main.php | 26 ++++++++++++++++++++------ phpBB/includes/mcp/mcp_post.php | 20 +++++++++++++++++--- phpBB/includes/mcp/mcp_topic.php | 18 ++++++++++++++++-- phpBB/search.php | 18 ++++++++++++++++-- 7 files changed, 117 insertions(+), 19 deletions(-) diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index d65958dfd0..80e102db21 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -648,8 +648,22 @@ class acp_main // Warn if no search index is created if ($config['num_posts']) { - $search_backend_factory = $phpbb_container->get('search.backend_factory'); - $search = $search_backend_factory->get_active(); + try + { + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); + } + catch (RuntimeException $e) + { + if (strpos($e->getMessage(), 'No service found') === 0) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + else + { + throw $e; + } + } if (!$search->index_created()) { diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 73d025ae7f..bddf235647 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -1086,8 +1086,22 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = } // Remove the message from the search index - $search_backend_factory = $phpbb_container->get('search.backend_factory'); - $search = $search_backend_factory->get_active(); + try + { + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); + } + catch (RuntimeException $e) + { + if (strpos($e->getMessage(), 'No service found') === 0) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + else + { + throw $e; + } + } $search->index_remove($post_ids, $poster_ids, $forum_ids); diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 6cdbb2f8a0..59f745835c 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -2291,8 +2291,22 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data // Index message contents if ($update_search_index && $data_ary['enable_indexing']) { - $search_backend_factory = $phpbb_container->get('search.backend_factory'); - $search = $search_backend_factory->get_active(); + try + { + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); + } + catch (RuntimeException $e) + { + if (strpos($e->getMessage(), 'No service found') === 0) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + else + { + throw $e; + } + } $search->index($mode, $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, $data_ary['forum_id']); } diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 5e257cfa11..35f322bba4 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -1398,16 +1398,30 @@ function mcp_fork_topic($topic_ids) foreach ($topic_data as $topic_id => $topic_row) { - if (!isset($search_type) && $topic_row['enable_indexing']) + if (!isset($search) && $topic_row['enable_indexing']) { // Select the search method and do some additional checks to ensure it can actually be utilised - $search_backend_factory = $phpbb_container->get('search.backend_factory'); - $search = $search_backend_factory->get_active(); + try + { + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); + } + catch (RuntimeException $e) + { + if (strpos($e->getMessage(), 'No service found') === 0) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + else + { + throw $e; + } + } $search_mode = 'post'; } - else if (!isset($search_type) && !$topic_row['enable_indexing']) + else if (!isset($search) && !$topic_row['enable_indexing']) { - $search_type = false; + $search = false; } $sql_ary = array( @@ -1589,7 +1603,7 @@ function mcp_fork_topic($topic_ids) // Copy whether the topic is dotted markread('post', $to_forum_id, $new_topic_id, 0, $row['poster_id']); - if (!empty($search_type)) + if (!empty($search)) { $search->index($search_mode, $new_post_id, $sql_ary['post_text'], $sql_ary['post_subject'], $sql_ary['poster_id'], ($topic_row['topic_type'] == POST_GLOBAL) ? 0 : $to_forum_id); $search_mode = 'reply'; // After one we index replies diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index fb120577a3..3f399dd0c6 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -561,7 +561,7 @@ function phpbb_get_num_ips_for_poster(\phpbb\db\driver\driver_interface $db, $po */ function change_poster(&$post_info, $userdata) { - global $db, $config, $user, $phpbb_log, $phpbb_dispatcher; + global $db, $config, $user, $phpbb_log, $phpbb_dispatcher, $phpbb_container; if (empty($userdata) || $userdata['user_id'] == $post_info['user_id']) { @@ -632,8 +632,22 @@ function change_poster(&$post_info, $userdata) } // refresh search cache of this post - $search_backend_factory = $phpbb_container->get('search.backend_factory'); - $search = $search_backend_factory->get_active(); + try + { + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); + } + catch (RuntimeException $e) + { + if (strpos($e->getMessage(), 'No service found') === 0) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + else + { + throw $e; + } + } $search->index_remove([], [$post_info['user_id'], $userdata['user_id']], []); diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 0aa6160831..6d0f40231e 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -625,8 +625,22 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) if ($first_post_data['enable_indexing']) { // Select the search method and do some additional checks to ensure it can actually be utilised - $search_backend_factory = $phpbb_container->get('search.backend_factory'); - $search = $search_backend_factory->get_active(); + try + { + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); + } + catch (RuntimeException $e) + { + if (strpos($e->getMessage(), 'No service found') === 0) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + else + { + throw $e; + } + } $search->index('edit', $first_post_data['post_id'], $first_post_data['post_text'], $subject, $first_post_data['poster_id'], $first_post_data['forum_id']); } diff --git a/phpBB/search.php b/phpBB/search.php index f7be082564..e913e7992a 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -294,8 +294,22 @@ if ($keywords || $author || $author_id || $search_id || $submit) } // Select which method we'll use to obtain the post_id or topic_id information - $search_backend_factory = $phpbb_container->get('search.backend_factory'); - $search = $search_backend_factory->get_active(); + try + { + $search_backend_factory = $phpbb_container->get('search.backend_factory'); + $search = $search_backend_factory->get_active(); + } + catch (RuntimeException $e) + { + if (strpos($e->getMessage(), 'No service found') === 0) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + else + { + throw $e; + } + } // let the search module split up the keywords if ($keywords) From 658a0489d01423e7821639d7d0cc2c6d184ad462 Mon Sep 17 00:00:00 2001 From: rubencm Date: Tue, 23 Mar 2021 11:51:02 +0100 Subject: [PATCH 21/22] [ticket/15540] Add types PHPBB3-15540 --- phpBB/includes/acp/acp_search.php | 2 + phpBB/includes/functions_posting.php | 12 +- phpBB/includes/mcp/mcp_main.php | 4 +- phpBB/includes/mcp/mcp_topic.php | 2 +- .../install_data/task/create_search_index.php | 6 +- phpBB/phpbb/search/backend/base.php | 4 +- phpBB/phpbb/search/backend/fulltext_mysql.php | 20 +-- .../phpbb/search/backend/fulltext_native.php | 36 ++--- .../search/backend/fulltext_postgres.php | 24 ++-- .../phpbb/search/backend/fulltext_sphinx.php | 24 ++-- .../backend/search_backend_interface.php | 135 ++++++++++-------- phpBB/search.php | 4 +- 12 files changed, 140 insertions(+), 133 deletions(-) diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index b38e39300c..751760e2fc 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -283,6 +283,7 @@ class acp_search case 'delete': try { + $this->state[2] = $this->state[2] ?? 0; if ($status = $this->search->delete_index($this->state[2])) // Status is not null, so deleting is in progress.... { // save the current state @@ -312,6 +313,7 @@ class acp_search case 'create': try { + $this->state[2] = $this->state[2] ?? 0; if ($status = $this->search->create_index($this->state[2])) // Status is not null, so indexing is in progress.... { // save the current state diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 59f745835c..817a98f836 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -1634,7 +1634,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data // Collect some basic information about which tables and which rows to update/insert $sql_data = array(); - $poster_id = ($mode == 'edit') ? $data_ary['poster_id'] : (int) $user->data['user_id']; + $poster_id = ($mode == 'edit') ? (int) $data_ary['poster_id'] : (int) $user->data['user_id']; // Retrieve some additional information if not present if ($mode == 'edit' && (!isset($data_ary['post_visibility']) || !isset($data_ary['topic_visibility']) || $data_ary['post_visibility'] === false || $data_ary['topic_visibility'] === false)) @@ -2215,7 +2215,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'"; // Maybe not only the subject, but also changing anonymous usernames. ;) - if ($data_ary['poster_id'] == ANONYMOUS) + if ((int) $data_ary['poster_id'] == ANONYMOUS) { $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'"; } @@ -2232,7 +2232,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data $db->sql_freeresult($result); // this post is the latest post in the forum, better update - if ($row['forum_last_post_id'] == $data_ary['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data_ary['poster_id'] == ANONYMOUS)) + if ($row['forum_last_post_id'] == $data_ary['post_id'] && ($row['forum_last_post_subject'] !== $subject || (int) $data_ary['poster_id'] == ANONYMOUS)) { // the post's subject changed if ($row['forum_last_post_subject'] !== $subject) @@ -2241,7 +2241,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data } // Update the user name if poster is anonymous... just in case a moderator changed it - if ($data_ary['poster_id'] == ANONYMOUS) + if ((int) $data_ary['poster_id'] == ANONYMOUS) { $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'"; } @@ -2308,11 +2308,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data } } - $search->index($mode, $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, $data_ary['forum_id']); + $search->index($mode, (int) $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, (int) $data_ary['forum_id']); } // Topic Notification, do not change if moderator is changing other users posts... - if ($user->data['user_id'] == $poster_id) + if ((int) $user->data['user_id'] == $poster_id) { if (!$data_ary['notify_set'] && $data_ary['notify']) { diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 35f322bba4..42e8f67a05 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -1566,7 +1566,7 @@ function mcp_fork_topic($topic_ids) } } $db->sql_query('INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); - $new_post_id = $db->sql_nextid(); + $new_post_id = (int) $db->sql_nextid(); /** * Perform actions after forked topic is created. @@ -1605,7 +1605,7 @@ function mcp_fork_topic($topic_ids) if (!empty($search)) { - $search->index($search_mode, $new_post_id, $sql_ary['post_text'], $sql_ary['post_subject'], $sql_ary['poster_id'], ($topic_row['topic_type'] == POST_GLOBAL) ? 0 : $to_forum_id); + $search->index($search_mode, $new_post_id, $sql_ary['post_text'], $sql_ary['post_subject'], (int) $sql_ary['poster_id'], ($topic_row['topic_type'] == POST_GLOBAL) ? 0 : $to_forum_id); $search_mode = 'reply'; // After one we index replies } diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 6d0f40231e..f9f62d5fe5 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -642,7 +642,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) } } - $search->index('edit', $first_post_data['post_id'], $first_post_data['post_text'], $subject, $first_post_data['poster_id'], $first_post_data['forum_id']); + $search->index('edit', (int) $first_post_data['post_id'], $first_post_data['post_text'], $subject, (int) $first_post_data['poster_id'], (int) $first_post_data['forum_id']); } // Copy topic subscriptions to new topic diff --git a/phpBB/phpbb/install/module/install_data/task/create_search_index.php b/phpBB/phpbb/install/module/install_data/task/create_search_index.php index bceeb3a8e1..c8f77c105f 100644 --- a/phpBB/phpbb/install/module/install_data/task/create_search_index.php +++ b/phpBB/phpbb/install/module/install_data/task/create_search_index.php @@ -169,11 +169,11 @@ class create_search_index extends database_task { $this->search_indexer->index( 'post', - $value['post_id'], + (int) $value['post_id'], $value['post_text'], $value['post_subject'], - $value['poster_id'], - $value['forum_id'] + (int) $value['poster_id'], + (int) $value['forum_id'] ); } diff --git a/phpBB/phpbb/search/backend/base.php b/phpBB/phpbb/search/backend/base.php index 52a4448a45..1bf16c8ea1 100644 --- a/phpBB/phpbb/search/backend/base.php +++ b/phpBB/phpbb/search/backend/base.php @@ -321,7 +321,7 @@ abstract class base implements search_backend_interface /** * {@inheritdoc} */ - public function create_index(int &$post_counter = null): ?array + public function create_index(int &$post_counter = 0): ?array { $max_post_id = $this->get_max_post_id(); $forums_indexing_enabled = $this->forum_ids_with_indexing_enabled(); @@ -343,7 +343,7 @@ abstract class base implements search_backend_interface // Indexing enabled for this forum if (in_array($row['forum_id'], $forums_indexing_enabled, true)) { - $this->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); + $this->index('post', (int) $row['post_id'], $row['post_text'], $row['post_subject'], (int) $row['poster_id'], (int) $row['forum_id']); } $row_count++; } diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index 71468debd4..22f72e0aaf 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -196,7 +196,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_word_length(): array + public function get_word_length() { return $this->word_length; } @@ -204,7 +204,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function split_keywords(&$keywords, $terms): bool + public function split_keywords(string &$keywords, string $terms): bool { if ($terms == 'all') { @@ -342,7 +342,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - 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) + public function keyword_search(string $type, string $fields, string $terms, array $sort_by_sql, string $sort_key, string $sort_dir, string $sort_days, array $ex_fid_ary, string $post_visibility, int $topic_id, array $author_ary, string $author_name, array &$id_ary, int &$start, int $per_page) { // No keywords? No posts if (!$this->search_query) @@ -590,7 +590,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - 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) + public function author_search(string $type, bool $firstpost_only, array $sort_by_sql, string $sort_key, string $sort_dir, string $sort_days, array $ex_fid_ary, string $post_visibility, int $topic_id, array $author_ary, string $author_name, array &$id_ary, int &$start, int $per_page) { // No author? No posts if (!count($author_ary)) @@ -844,7 +844,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) + public function index(string $mode, int $post_id, string &$message, string &$subject, int $poster_id, int $forum_id) { // Split old and new post/subject to obtain array of words $split_text = $this->split_message($message); @@ -892,7 +892,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function index_remove($post_ids, $author_ids, $forum_ids) + public function index_remove(array $post_ids, array $author_ids, array $forum_ids): void { $this->destroy_cache([], array_unique($author_ids)); } @@ -900,7 +900,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function tidy() + public function tidy(): void { // destroy too old cached search results $this->destroy_cache([]); @@ -911,7 +911,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function create_index(int &$post_counter = null): ?array + public function create_index(int &$post_counter = 0): ?array { // Make sure we can actually use MySQL with fulltext indexes if ($error = $this->init()) @@ -1049,7 +1049,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function index_created() + public function index_created(): bool { if (empty($this->stats)) { @@ -1146,7 +1146,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function acp() + public function acp(): array { $tpl = '
diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index ccbdc08a2d..616b5adcc9 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -134,7 +134,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_name() + public function get_name(): string { return 'phpBB Native Fulltext'; } @@ -158,7 +158,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_search_query() + public function get_search_query(): string { return $this->search_query; } @@ -166,7 +166,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_common_words() + public function get_common_words(): array { return $this->common_words; } @@ -180,21 +180,9 @@ class fulltext_native extends base implements search_backend_interface } /** - * This function fills $this->search_query with the cleaned user search query - * - * If $terms is 'any' then the words will be extracted from the search query - * and combined with | inside brackets. They will afterwards be treated like - * an standard search query. - * - * Then it analyses the query and fills the internal arrays $must_not_contain_ids, - * $must_contain_ids and $must_exclude_one_ids which are later used by keyword_search() - * - * @param string $keywords contains the search query string as entered by the user - * @param string $terms is either 'all' (use search query as entered, default words to 'must be contained in post') - * or 'any' (find all posts containing at least one of the given words) - * @return boolean false if no valid keywords were found and otherwise true - */ - public function split_keywords(&$keywords, $terms) + * {@inheritdoc} + */ + public function split_keywords(string &$keywords, string $terms): bool { $tokens = '+-|()* '; @@ -516,7 +504,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - 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) + public function keyword_search(string $type, string $fields, string $terms, array $sort_by_sql, string $sort_key, string $sort_dir, string $sort_days, array $ex_fid_ary, string $post_visibility, int $topic_id, array $author_ary, string $author_name, array &$id_ary, int &$start, int $per_page) { // No keywords? No posts. if (empty($this->search_query)) @@ -1001,7 +989,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - 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) + public function author_search(string $type, bool $firstpost_only, array $sort_by_sql, string $sort_key, string $sort_dir, string $sort_days, array $ex_fid_ary, string $post_visibility, int $topic_id, array $author_ary, string $author_name, array &$id_ary, int &$start, int $per_page) { // No author? No posts if (!count($author_ary)) @@ -1303,7 +1291,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) + public function index(string $mode, int $post_id, string &$message, string &$subject, int $poster_id, int $forum_id) { if (!$this->config['fulltext_native_load_upd']) { @@ -1492,7 +1480,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - public function index_remove($post_ids, $author_ids, $forum_ids) + public function index_remove(array $post_ids, array $author_ids, array $forum_ids): void { if (count($post_ids)) { @@ -1549,7 +1537,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - public function tidy() + public function tidy(): void { // Is the fulltext indexer disabled? If yes then we need not // carry on ... it's okay ... I know when I'm not wanted boo hoo @@ -2008,7 +1996,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - public function acp() + public function acp(): array { /** * if we need any options, copied from fulltext_native for now, will have to be adjusted or removed diff --git a/phpBB/phpbb/search/backend/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php index 90f7771426..824326a4f3 100644 --- a/phpBB/phpbb/search/backend/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -114,7 +114,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_name() + public function get_name(): string { return 'PostgreSQL Fulltext'; } @@ -143,7 +143,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_search_query() + public function get_search_query(): string { return $this->search_query; } @@ -151,7 +151,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function get_common_words() + public function get_common_words(): array { return $this->common_words; } @@ -167,7 +167,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function split_keywords(&$keywords, $terms) + public function split_keywords(string &$keywords, string $terms): bool { if ($terms == 'all') { @@ -258,7 +258,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - 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) + public function keyword_search(string $type, string $fields, string $terms, array $sort_by_sql, string $sort_key, string $sort_dir, string $sort_days, array $ex_fid_ary, string $post_visibility, int $topic_id, array $author_ary, string $author_name, array &$id_ary, int &$start, int $per_page) { // No keywords? No posts if (!$this->search_query) @@ -522,7 +522,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - 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) + public function author_search(string $type, bool $firstpost_only, array $sort_by_sql, string $sort_key, string $sort_dir, string $sort_days, array $ex_fid_ary, string $post_visibility, int $topic_id, array $author_ary, string $author_name, array &$id_ary, int &$start, int $per_page) { // No author? No posts if (!count($author_ary)) @@ -798,7 +798,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) + public function index(string $mode, int $post_id, string &$message, string &$subject, int $poster_id, int $forum_id) { // Split old and new post/subject to obtain array of words $split_text = $this->split_message($message); @@ -846,7 +846,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function index_remove($post_ids, $author_ids, $forum_ids) + public function index_remove(array $post_ids, array $author_ids, array $forum_ids): void { $this->destroy_cache([], $author_ids); } @@ -854,7 +854,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function tidy() + public function tidy(): void { // destroy too old cached search results $this->destroy_cache(array()); @@ -865,7 +865,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function create_index(int &$post_counter = null): ?array + public function create_index(int &$post_counter = 0): ?array { // Make sure we can actually use PostgreSQL with fulltext indexes if ($error = $this->init()) @@ -983,7 +983,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function index_created() + public function index_created(): bool { if (empty($this->stats)) { @@ -1081,7 +1081,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function acp() + public function acp(): array { $tpl = '
diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index 8a493a4dc3..c59be909ac 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -190,7 +190,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function get_name() + public function get_name(): string { return 'Sphinx Fulltext'; } @@ -222,7 +222,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function get_search_query() + public function get_search_query(): string { return $this->search_query; } @@ -230,7 +230,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function get_common_words() + public function get_common_words(): array { return array(); } @@ -246,7 +246,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function split_keywords(&$keywords, $terms) + public function split_keywords(string &$keywords, string $terms): bool { // Keep quotes and new lines $keywords = str_replace(['"', "\n"], ['"', ' '], trim($keywords)); @@ -280,7 +280,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - 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) + public function keyword_search(string $type, string $fields, string $terms, array $sort_by_sql, string $sort_key, string $sort_dir, string $sort_days, array $ex_fid_ary, string $post_visibility, int $topic_id, array $author_ary, string $author_name, array &$id_ary, int &$start, int $per_page) { // No keywords? No posts. if (!strlen($this->search_query) && !count($author_ary)) @@ -520,7 +520,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - 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) + public function author_search(string $type, bool $firstpost_only, array $sort_by_sql, string $sort_key, string $sort_dir, string $sort_days, array $ex_fid_ary, string $post_visibility, int $topic_id, array $author_ary, string $author_name, array &$id_ary, int &$start, int $per_page) { $this->search_query = ''; @@ -541,7 +541,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) + public function index(string $mode, int $post_id, string &$message, string &$subject, int $poster_id, int $forum_id) { /** * Event to modify method arguments before the Sphinx search index is updated @@ -607,7 +607,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function index_remove($post_ids, $author_ids, $forum_ids) + public function index_remove(array $post_ids, array $author_ids, array $forum_ids): void { $values = array(); foreach ($post_ids as $post_id) @@ -621,7 +621,7 @@ class fulltext_sphinx implements search_backend_interface /** * Nothing needs to be destroyed */ - public function tidy() + public function tidy(): void { $this->config->set('search_last_gc', time(), false); } @@ -629,7 +629,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function create_index(int &$post_counter = null): ?array + public function create_index(int &$post_counter = 0): ?array { if ($this->index_created()) { @@ -672,7 +672,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function index_created($allow_new_files = true) + public function index_created($allow_new_files = true): bool { $created = false; @@ -783,7 +783,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function acp() + public function acp(): array { $config_vars = array( 'fulltext_sphinx_data_path' => 'string', diff --git a/phpBB/phpbb/search/backend/search_backend_interface.php b/phpBB/phpbb/search/backend/search_backend_interface.php index dc874e9460..4a31b74014 100644 --- a/phpBB/phpbb/search/backend/search_backend_interface.php +++ b/phpBB/phpbb/search/backend/search_backend_interface.php @@ -20,14 +20,14 @@ interface search_backend_interface * * @return string Name */ - public function get_name(); + public function get_name(): string; /** * Returns if the search engine is available * * @return bool */ - public function is_available(); + public function is_available(): bool; /** * Method executed when a search backend is set from acp. @@ -43,74 +43,82 @@ interface search_backend_interface * * @return string search query */ - public function get_search_query(); + public function get_search_query(): string; /** * Returns the common_words array * * @return array common words that are ignored by search backend */ - public function get_common_words(); + public function get_common_words(): array; /** * Returns the word_length array * - * @return array min and max word length for searching + * @return array|false min and max word length for searching */ public function get_word_length(); /** * 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 + * This function fills $this->search_query with the cleaned user search query * - * @param string &$keywords Contains the keyword as entered by the user - * @param string $terms is either 'all' or 'any' - * @return bool false if no valid keywords were found and otherwise true + * If $terms is 'any' then the words will be extracted from the search query + * and combined with | inside brackets. They will afterwards be treated like + * an standard search query. + * + * Then it analyses the query and fills the internal arrays $must_not_contain_ids, + * $must_contain_ids and $must_exclude_one_ids which are later used by keyword_search() + * + * @param string $keywords contains the search query string as entered by the user + * @param string $terms is either 'all' (use search query as entered, default words to 'must be contained in post') + * or 'any' (find all posts containing at least one of the given words) + * @return boolean false if no valid keywords were found and otherwise true */ - public function split_keywords(&$keywords, $terms); + public function split_keywords(string &$keywords, string $terms): bool; /** * 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 + * @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); + public function keyword_search(string $type, string $fields, string $terms, array $sort_by_sql, string $sort_key, string $sort_dir, string $sort_days, array $ex_fid_ary, string $post_visibility, int $topic_id, array $author_ary, string $author_name, array &$id_ary, int &$start, int $per_page); /** * 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 + * @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); + public function author_search(string $type, bool $firstpost_only, array $sort_by_sql, string $sort_key, string $sort_dir, string $sort_days, array $ex_fid_ary, string $post_visibility, int $topic_id, array $author_ary, string $author_name, array &$id_ary, int &$start, int $per_page); /** * Returns if phrase search is supported or not @@ -123,45 +131,54 @@ interface search_backend_interface * Updates wordlist and wordmatch tables when a message is posted or changed * Destroys cached search results, that contained one of the new words in a post so the results won't be outdated * - * @param string $mode contains the post mode: edit, post, reply, quote ... - * @param int $post_id contains the post id of the post to index - * @param string $message contains the post text of the post - * @param string $subject contains the subject of the post to index - * @param int $poster_id contains the user id of the poster - * @param int $forum_id contains the forum id of parent forum of the post + * @param string $mode contains the post mode: edit, post, reply, quote ... + * @param int $post_id contains the post id of the post to index + * @param string $message contains the post text of the post + * @param string $subject contains the subject of the post to index + * @param int $poster_id contains the user id of the poster + * @param int $forum_id contains the forum id of parent forum of the post */ - public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id); + public function index(string $mode, int $post_id, string &$message, string &$subject, int $poster_id, int $forum_id); /** * Destroy cached results, that might be outdated after deleting a post + * @param array $post_ids + * @param array $author_ids + * @param array $forum_ids + * + * @return void */ - public function index_remove($post_ids, $author_ids, $forum_ids); + public function index_remove(array $post_ids, array $author_ids, array $forum_ids): void; /** * Destroy old cache entries + * + * @return void */ - public function tidy(); + public function tidy(): void; /** * Create fulltext index * - * @param int|null $post_counter + * @param int $post_counter * @return array|null array with current status or null if finished */ - public function create_index(int &$post_counter = null): ?array; + public function create_index(int &$post_counter = 0): ?array; /** * Drop fulltext index * - * @param int|null $post_counter + * @param int $post_counter * @return array|null array with current status or null if finished */ - public function delete_index(int &$post_counter = null): ?array; + public function delete_index(int &$post_counter = 0): ?array; /** * Returns true if both FULLTEXT indexes exist + * + * @return bool */ - public function index_created(); + public function index_created(): bool; /** * Returns an associative array containing information about the indexes @@ -173,7 +190,7 @@ interface search_backend_interface /** * Display various options that can be configured for the backend from the acp * - * @return associative array containing template and config variables + * @return array array containing template and config variables */ - public function acp(); + public function acp(): array; } diff --git a/phpBB/search.php b/phpBB/search.php index e913e7992a..93ec09e334 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -29,7 +29,7 @@ $mode = $request->variable('mode', ''); $search_id = $request->variable('search_id', ''); $start = max($request->variable('start', 0), 0); $post_id = $request->variable('p', 0); -$topic_id = $request->variable('t', 0); +$topic_id = (int) $request->variable('t', 0); $view = $request->variable('view', ''); $submit = $request->variable('submit', false); @@ -544,7 +544,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) extract($phpbb_dispatcher->trigger_event('core.search_modify_param_after', compact($vars))); // show_results should not change after this - $per_page = ($show_results == 'posts') ? $config['posts_per_page'] : $config['topics_per_page']; + $per_page = ($show_results == 'posts') ? (int) $config['posts_per_page'] : (int) $config['topics_per_page']; $total_match_count = 0; // Set limit for the $total_match_count to reduce server load From 6ae68baa2e5fa052763429d1ddc783989e72c24b Mon Sep 17 00:00:00 2001 From: rubencm Date: Tue, 23 Mar 2021 22:23:10 +0100 Subject: [PATCH 22/22] [ticket/15540] Code changes PHPBB3-15540 --- .../default/container/services_search.yml | 8 ++-- phpBB/includes/acp/acp_search.php | 40 ++++++++++--------- phpBB/includes/functions_convert.php | 28 ------------- phpBB/install/convert/convert.php | 2 - phpBB/install/convert/convertor.php | 2 - .../install_data/task/create_search_index.php | 2 +- phpBB/phpbb/search/backend/base.php | 22 +++++----- phpBB/phpbb/search/backend/fulltext_mysql.php | 5 +-- .../phpbb/search/backend/fulltext_native.php | 2 +- .../search/backend/fulltext_postgres.php | 8 ++-- .../phpbb/search/backend/fulltext_sphinx.php | 2 +- .../backend/search_backend_interface.php | 2 +- phpBB/phpbb/search/search_backend_factory.php | 4 +- phpBB/search.php | 2 +- 14 files changed, 50 insertions(+), 79 deletions(-) diff --git a/phpBB/config/default/container/services_search.yml b/phpBB/config/default/container/services_search.yml index f056f71295..1dba3732be 100644 --- a/phpBB/config/default/container/services_search.yml +++ b/phpBB/config/default/container/services_search.yml @@ -1,8 +1,8 @@ services: # Search backends - search.fulltext.native: - class: phpbb\search\backend\fulltext_native + search.fulltext.mysql: + class: phpbb\search\backend\fulltext_mysql arguments: - '@config' - '@dbal.conn' @@ -14,8 +14,8 @@ services: tags: - { name: search.backend } - search.fulltext.mysql: - class: phpbb\search\backend\fulltext_mysql + search.fulltext.native: + class: phpbb\search\backend\fulltext_native arguments: - '@config' - '@dbal.conn' diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 751760e2fc..0723376f6f 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -25,6 +25,10 @@ class acp_search var $state; var $search; + protected const STATE_SEARCH_TYPE = 0; + protected const STATE_ACTION = 1; + protected const STATE_POST_COUNTER = 2; + function main($id, $mode) { global $user; @@ -80,7 +84,6 @@ class acp_search // Only show available search backends if ($search->is_available()) { - $name = $search->get_name(); $type = get_class($search); @@ -252,25 +255,24 @@ class acp_search break; case 'delete': - $this->state[1] = 'delete'; + $this->state[self::STATE_ACTION] = 'delete'; break; case 'create': - $this->state[1] = 'create'; + $this->state[self::STATE_ACTION] = 'create'; break; default: trigger_error('NO_ACTION', E_USER_ERROR); - break; } - if (empty($this->state[0])) + if (empty($this->state[self::STATE_SEARCH_TYPE])) { - $this->state[0] = $request->variable('search_type', ''); + $this->state[self::STATE_SEARCH_TYPE] = $request->variable('search_type', ''); } $search_backend_factory = $phpbb_container->get('search.backend_factory'); - $this->search = $search_backend_factory->get($this->state[0]); + $this->search = $search_backend_factory->get($this->state[self::STATE_SEARCH_TYPE]); $name = $this->search->get_name(); @@ -283,8 +285,8 @@ class acp_search case 'delete': try { - $this->state[2] = $this->state[2] ?? 0; - if ($status = $this->search->delete_index($this->state[2])) // Status is not null, so deleting is in progress.... + $this->state[self::STATE_POST_COUNTER] = $this->state[self::STATE_POST_COUNTER] ?? 0; + if ($status = $this->search->delete_index($this->state[self::STATE_POST_COUNTER])) // Status is not null, so deleting is in progress.... { // save the current state $this->save_state(); @@ -296,14 +298,14 @@ class acp_search } catch (Exception $e) { - $this->state = array(''); + $this->state = []; $this->save_state(); trigger_error($e->getMessage() . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); } $this->search->tidy(); - $this->state = array(''); + $this->state = []; $this->save_state(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_REMOVED', false, array($name)); @@ -313,8 +315,8 @@ class acp_search case 'create': try { - $this->state[2] = $this->state[2] ?? 0; - if ($status = $this->search->create_index($this->state[2])) // Status is not null, so indexing is in progress.... + $this->state[self::STATE_POST_COUNTER] = $this->state[self::STATE_POST_COUNTER] ?? 0; + if ($status = $this->search->create_index($this->state[self::STATE_POST_COUNTER])) // Status is not null, so indexing is in progress.... { // save the current state $this->save_state(); @@ -327,7 +329,7 @@ class acp_search catch (Exception $e) { // Error executing create_index - $this->state = array(''); + $this->state = []; $this->save_state(); trigger_error($e->getMessage() . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); } @@ -336,7 +338,7 @@ class acp_search $this->search->tidy(); - $this->state = array(''); + $this->state = []; $this->save_state(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_CREATED', false, array($name)); @@ -409,13 +411,13 @@ class acp_search 'UA_PROGRESS_BAR' => addslashes(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=progress_bar")), )); - if (isset($this->state[1])) + if (isset($this->state[self::STATE_ACTION])) { $template->assign_vars(array( 'S_CONTINUE_INDEXING' => $this->state[1], - 'U_CONTINUE_INDEXING' => $this->u_action . '&action=' . $this->state[1] . '&hash=' . generate_link_hash('acp_search'), - 'L_CONTINUE' => ($this->state[1] == 'create') ? $user->lang['CONTINUE_INDEXING'] : $user->lang['CONTINUE_DELETING_INDEX'], - 'L_CONTINUE_EXPLAIN' => ($this->state[1] == 'create') ? $user->lang['CONTINUE_INDEXING_EXPLAIN'] : $user->lang['CONTINUE_DELETING_INDEX_EXPLAIN']) + 'U_CONTINUE_INDEXING' => $this->u_action . '&action=' . $this->state[self::STATE_ACTION] . '&hash=' . generate_link_hash('acp_search'), + 'L_CONTINUE' => ($this->state[self::STATE_ACTION] == 'create') ? $user->lang['CONTINUE_INDEXING'] : $user->lang['CONTINUE_DELETING_INDEX'], + 'L_CONTINUE_EXPLAIN' => ($this->state[self::STATE_ACTION] == 'create') ? $user->lang['CONTINUE_INDEXING_EXPLAIN'] : $user->lang['CONTINUE_DELETING_INDEX_EXPLAIN']) ); } } diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php index 056f968cfc..4bb10fc8d1 100644 --- a/phpBB/includes/functions_convert.php +++ b/phpBB/includes/functions_convert.php @@ -1039,34 +1039,6 @@ function set_user_options() return $option_field; } -/** -* Index messages on the fly as we convert them -* @todo naderman, can you check that this works with the new search plugins as it's use is currently disabled (and thus untested) -function search_indexing($message = '') -{ - global $fulltext_search, $convert_row; - - if (!isset($convert_row['post_id'])) - { - return; - } - - if (!$message) - { - if (!isset($convert_row['message'])) - { - return; - } - - $message = $convert_row['message']; - } - - $title = (isset($convert_row['title'])) ? $convert_row['title'] : ''; - - $fulltext_search->index('post', $convert_row['post_id'], $message, $title, $convert_row['poster_id'], $convert_row['forum_id']); -} -*/ - function make_unique_filename($filename) { if (!strlen($filename)) diff --git a/phpBB/install/convert/convert.php b/phpBB/install/convert/convert.php index 3e9e562f2e..9c460cc954 100644 --- a/phpBB/install/convert/convert.php +++ b/phpBB/install/convert/convert.php @@ -39,8 +39,6 @@ class convert var $src_truncate_statement = 'DELETE FROM '; var $truncate_statement = 'DELETE FROM '; - var $fulltext_search; - // Batch size, can be adjusted by the conversion file // For big boards a value of 6000 seems to be optimal var $batch_size = 2000; diff --git a/phpBB/install/convert/convertor.php b/phpBB/install/convert/convertor.php index ab87243952..b52a0b03bc 100644 --- a/phpBB/install/convert/convertor.php +++ b/phpBB/install/convert/convertor.php @@ -224,8 +224,6 @@ class convertor trigger_error('NO_SUCH_SEARCH_MODULE'); } - $convert->fulltext_search = new $search_type($config, $db, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx); - include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx); $message_parser = new \parse_message(); diff --git a/phpBB/phpbb/install/module/install_data/task/create_search_index.php b/phpBB/phpbb/install/module/install_data/task/create_search_index.php index c8f77c105f..79b53f329a 100644 --- a/phpBB/phpbb/install/module/install_data/task/create_search_index.php +++ b/phpBB/phpbb/install/module/install_data/task/create_search_index.php @@ -180,7 +180,7 @@ class create_search_index extends database_task /** * {@inheritdoc} */ - public static function get_step_count() : int + static public function get_step_count() : int { return 1; } diff --git a/phpBB/phpbb/search/backend/base.php b/phpBB/phpbb/search/backend/base.php index 1bf16c8ea1..0245c72c2a 100644 --- a/phpBB/phpbb/search/backend/base.php +++ b/phpBB/phpbb/search/backend/base.php @@ -71,15 +71,15 @@ abstract class base implements search_backend_interface * 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 &$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 self::SEARCH_RESULT_NOT_IN_CACHE or self::SEARCH_RESULT_IN_CACHE or self::SEARCH_RESULT_INCOMPLETE */ - protected function obtain_ids(string $search_key, &$result_count, &$id_ary, &$start, $per_page, string $sort_dir): int + protected function obtain_ids(string $search_key, int &$result_count, array &$id_ary, int &$start, int $per_page, string $sort_dir): int { if (!($stored_ids = $this->cache->get('_search_results_' . $search_key))) { @@ -89,7 +89,7 @@ abstract class base implements search_backend_interface else { $result_count = $stored_ids[-1]; - $reverse_ids = ($stored_ids[-2] != $sort_dir) ? true : false; + $reverse_ids = $stored_ids[-2] != $sort_dir; $complete = true; // Change start parameter in case out of bounds @@ -106,7 +106,7 @@ abstract class base implements search_backend_interface } // 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 + // from the direction in the cache and reverse the ids later if ($reverse_ids) { $start = $result_count - $start - $per_page; @@ -151,14 +151,14 @@ abstract class base implements search_backend_interface * @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 + * @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 + * @return void */ - protected function save_ids(string $search_key, string $keywords, $author_ary, int $result_count, &$id_ary, int $start, string $sort_dir) + protected function save_ids(string $search_key, string $keywords, array $author_ary, int $result_count, array &$id_ary, int $start, string $sort_dir): void { global $user; @@ -268,7 +268,7 @@ abstract class base implements search_backend_interface * @param array $words * @param array|bool $authors */ - protected function destroy_cache($words, $authors = false): void + protected function destroy_cache(array $words, $authors = false): void { // clear all searches that searched for the specified words if (count($words)) @@ -415,6 +415,8 @@ abstract class base implements search_backend_interface 'rows_per_second' => $rows_per_second, ]; } + + return null; } /** diff --git a/phpBB/phpbb/search/backend/fulltext_mysql.php b/phpBB/phpbb/search/backend/fulltext_mysql.php index 22f72e0aaf..0885e441a7 100644 --- a/phpBB/phpbb/search/backend/fulltext_mysql.php +++ b/phpBB/phpbb/search/backend/fulltext_mysql.php @@ -880,8 +880,7 @@ class fulltext_mysql extends base implements search_backend_interface ); extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_index_before', compact($vars))); - unset($split_text); - unset($split_title); + unset($split_text, $split_title); // destroy cached search results containing any of the words removed or added $this->destroy_cache($words, array($poster_id)); @@ -1146,7 +1145,7 @@ class fulltext_mysql extends base implements search_backend_interface /** * {@inheritdoc} */ - public function acp(): array + public function get_acp_options(): array { $tpl = '
diff --git a/phpBB/phpbb/search/backend/fulltext_native.php b/phpBB/phpbb/search/backend/fulltext_native.php index 616b5adcc9..24a7d7d9bc 100644 --- a/phpBB/phpbb/search/backend/fulltext_native.php +++ b/phpBB/phpbb/search/backend/fulltext_native.php @@ -1996,7 +1996,7 @@ class fulltext_native extends base implements search_backend_interface /** * {@inheritdoc} */ - public function acp(): array + public function get_acp_options(): array { /** * if we need any options, copied from fulltext_native for now, will have to be adjusted or removed diff --git a/phpBB/phpbb/search/backend/fulltext_postgres.php b/phpBB/phpbb/search/backend/fulltext_postgres.php index 824326a4f3..b1855f3119 100644 --- a/phpBB/phpbb/search/backend/fulltext_postgres.php +++ b/phpBB/phpbb/search/backend/fulltext_postgres.php @@ -343,16 +343,16 @@ class fulltext_postgres extends base implements search_backend_interface case 'u': $sql_sort_table = USERS_TABLE . ' u, '; $sql_sort_join = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster '; - break; + break; case 't': $join_topic = true; - break; + break; case 'f': $sql_sort_table = FORUMS_TABLE . ' f, '; $sql_sort_join = ' AND f.forum_id = p.forum_id '; - break; + break; } // Build some display specific sql strings @@ -1081,7 +1081,7 @@ class fulltext_postgres extends base implements search_backend_interface /** * {@inheritdoc} */ - public function acp(): array + public function get_acp_options(): array { $tpl = '
diff --git a/phpBB/phpbb/search/backend/fulltext_sphinx.php b/phpBB/phpbb/search/backend/fulltext_sphinx.php index c59be909ac..cc6c0b8afe 100644 --- a/phpBB/phpbb/search/backend/fulltext_sphinx.php +++ b/phpBB/phpbb/search/backend/fulltext_sphinx.php @@ -783,7 +783,7 @@ class fulltext_sphinx implements search_backend_interface /** * {@inheritdoc} */ - public function acp(): array + public function get_acp_options(): array { $config_vars = array( 'fulltext_sphinx_data_path' => 'string', diff --git a/phpBB/phpbb/search/backend/search_backend_interface.php b/phpBB/phpbb/search/backend/search_backend_interface.php index 4a31b74014..1fdc138028 100644 --- a/phpBB/phpbb/search/backend/search_backend_interface.php +++ b/phpBB/phpbb/search/backend/search_backend_interface.php @@ -192,5 +192,5 @@ interface search_backend_interface * * @return array array containing template and config variables */ - public function acp(): array; + public function get_acp_options(): array; } diff --git a/phpBB/phpbb/search/search_backend_factory.php b/phpBB/phpbb/search/search_backend_factory.php index 5ab6bce8af..eac31885ed 100644 --- a/phpBB/phpbb/search/search_backend_factory.php +++ b/phpBB/phpbb/search/search_backend_factory.php @@ -44,11 +44,11 @@ class search_backend_factory /** * Obtains a specified search backend * - * @param string $class + * @param string $class * * @return search_backend_interface */ - public function get($class): search_backend_interface + public function get(string $class): search_backend_interface { return $this->search_backends->get_by_class($class); } diff --git a/phpBB/search.php b/phpBB/search.php index 93ec09e334..8decc78bb5 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -29,7 +29,7 @@ $mode = $request->variable('mode', ''); $search_id = $request->variable('search_id', ''); $start = max($request->variable('start', 0), 0); $post_id = $request->variable('p', 0); -$topic_id = (int) $request->variable('t', 0); +$topic_id = $request->variable('t', 0); $view = $request->variable('view', ''); $submit = $request->variable('submit', false);