mirror of
https://github.com/phpbb/phpbb.git
synced 2025-06-07 20:08:53 +00:00
Merge pull request #5439 from rubencm/ticket/12683
[ticket/12683] Add a CLI command to generate the search index
This commit is contained in:
commit
995717f4a0
46 changed files with 1527 additions and 221 deletions
|
@ -23,6 +23,7 @@ imports:
|
|||
- { resource: services_notification.yml }
|
||||
- { resource: services_password.yml }
|
||||
- { resource: services_php.yml }
|
||||
- { resource: services_posting.yml }
|
||||
- { resource: services_profilefield.yml }
|
||||
- { resource: services_report.yml }
|
||||
- { resource: services_routing.yml }
|
||||
|
|
|
@ -246,6 +246,40 @@ services:
|
|||
tags:
|
||||
- { name: console.command }
|
||||
|
||||
console.command.searchindex.list_all:
|
||||
class: phpbb\console\command\searchindex\list_all
|
||||
arguments:
|
||||
- '@config'
|
||||
- '@language'
|
||||
- '@search.backend_collection'
|
||||
- '@user'
|
||||
tags:
|
||||
- { name: console.command }
|
||||
|
||||
console.command.searchindex.create:
|
||||
class: phpbb\console\command\searchindex\create
|
||||
arguments:
|
||||
- '@language'
|
||||
- '@log'
|
||||
- '@post.helper'
|
||||
- '@search.backend_factory'
|
||||
- '@search.state_helper'
|
||||
- '@user'
|
||||
tags:
|
||||
- { name: console.command }
|
||||
|
||||
console.command.searchindex.delete:
|
||||
class: phpbb\console\command\searchindex\delete
|
||||
arguments:
|
||||
- '@language'
|
||||
- '@log'
|
||||
- '@post.helper'
|
||||
- '@search.backend_factory'
|
||||
- '@search.state_helper'
|
||||
- '@user'
|
||||
tags:
|
||||
- { name: console.command }
|
||||
|
||||
console.command.thumbnail.delete:
|
||||
class: phpbb\console\command\thumbnail\delete
|
||||
arguments:
|
||||
|
|
5
phpBB/config/default/container/services_posting.yml
Normal file
5
phpBB/config/default/container/services_posting.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
services:
|
||||
post.helper:
|
||||
class: phpbb\posting\post_helper
|
||||
arguments:
|
||||
- '@dbal.conn'
|
|
@ -1,5 +1,11 @@
|
|||
services:
|
||||
|
||||
search.state_helper:
|
||||
class: phpbb\search\state_helper
|
||||
arguments:
|
||||
- '@config'
|
||||
- '@search.backend_factory'
|
||||
|
||||
# Search backends
|
||||
search.fulltext.mysql:
|
||||
class: phpbb\search\backend\fulltext_mysql
|
||||
|
@ -9,6 +15,7 @@ services:
|
|||
- '@dispatcher'
|
||||
- '@language'
|
||||
- '@user'
|
||||
- '%tables.search_results%'
|
||||
- '%core.root_path%'
|
||||
- '%core.php_ext%'
|
||||
tags:
|
||||
|
@ -22,6 +29,9 @@ services:
|
|||
- '@dispatcher'
|
||||
- '@language'
|
||||
- '@user'
|
||||
- '%tables.search_results%'
|
||||
- '%tables.search_wordlist%'
|
||||
- '%tables.search_wordmatch%'
|
||||
- '%core.root_path%'
|
||||
- '%core.php_ext%'
|
||||
tags:
|
||||
|
@ -35,6 +45,7 @@ services:
|
|||
- '@dispatcher'
|
||||
- '@language'
|
||||
- '@user'
|
||||
- '%tables.search_results%'
|
||||
- '%core.root_path%'
|
||||
- '%core.php_ext%'
|
||||
tags:
|
||||
|
|
|
@ -652,16 +652,9 @@ class acp_main
|
|||
$search_backend_factory = $phpbb_container->get('search.backend_factory');
|
||||
$search = $search_backend_factory->get_active();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
catch (\phpbb\search\exception\no_search_backend_found_exception $e)
|
||||
{
|
||||
if (strpos($e->getMessage(), 'No service found') === 0)
|
||||
{
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
|
||||
if (!$search->index_created())
|
||||
|
|
|
@ -21,6 +21,7 @@ use phpbb\language\language;
|
|||
use phpbb\log\log;
|
||||
use phpbb\request\request;
|
||||
use phpbb\search\search_backend_factory;
|
||||
use phpbb\search\state_helper;
|
||||
use phpbb\template\template;
|
||||
use phpbb\user;
|
||||
|
||||
|
@ -35,10 +36,6 @@ class acp_search
|
|||
public $tpl_name;
|
||||
public $page_title;
|
||||
|
||||
protected const STATE_SEARCH_TYPE = 0;
|
||||
protected const STATE_ACTION = 1;
|
||||
protected const STATE_POST_COUNTER = 2;
|
||||
|
||||
/** @var config */
|
||||
protected $config;
|
||||
|
||||
|
@ -57,6 +54,9 @@ class acp_search
|
|||
/** @var search_backend_factory */
|
||||
protected $search_backend_factory;
|
||||
|
||||
/** @var state_helper */
|
||||
protected $search_state_helper;
|
||||
|
||||
/** @var template */
|
||||
protected $template;
|
||||
|
||||
|
@ -79,6 +79,7 @@ class acp_search
|
|||
$this->request = $request;
|
||||
$this->search_backend_collection = $phpbb_container->get('search.backend_collection');
|
||||
$this->search_backend_factory = $phpbb_container->get('search.backend_factory');
|
||||
$this->search_state_helper = $phpbb_container->get('search.state_helper');
|
||||
$this->template = $template;
|
||||
$this->user = $user;
|
||||
$this->phpbb_admin_path = $phpbb_admin_path;
|
||||
|
@ -272,7 +273,6 @@ class acp_search
|
|||
public function index(string $id, string $mode): void
|
||||
{
|
||||
$action = $this->request->variable('action', '');
|
||||
$state = !empty($this->config['search_indexing_state']) ? explode(',', $this->config['search_indexing_state']) : [];
|
||||
|
||||
if ($action && !$this->request->is_set_post('cancel'))
|
||||
{
|
||||
|
@ -284,7 +284,7 @@ class acp_search
|
|||
|
||||
case 'create':
|
||||
case 'delete':
|
||||
$this->index_action($id, $mode, $action, $state);
|
||||
$this->index_action($id, $mode, $action);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -296,13 +296,12 @@ class acp_search
|
|||
// If clicked to cancel the indexing progress (acp_search_index_inprogress form)
|
||||
if ($this->request->is_set_post('cancel'))
|
||||
{
|
||||
$state = [];
|
||||
$this->save_state($state);
|
||||
$this->search_state_helper->clear_state();
|
||||
}
|
||||
|
||||
if (!empty($state))
|
||||
if ($this->search_state_helper->is_action_in_progress())
|
||||
{
|
||||
$this->index_inprogress($id, $mode, $state[self::STATE_ACTION]);
|
||||
$this->index_inprogress($id, $mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -325,8 +324,8 @@ class acp_search
|
|||
foreach ($this->search_backend_collection as $search)
|
||||
{
|
||||
$this->template->assign_block_vars('backends', [
|
||||
'NAME' => $search->get_name(),
|
||||
'TYPE' => $search->get_type(),
|
||||
'NAME' => $search->get_name(),
|
||||
'TYPE' => $search->get_type(),
|
||||
|
||||
'S_ACTIVE' => $search->get_type() === $this->config['search_type'],
|
||||
'S_HIDDEN_FIELDS' => build_hidden_fields(['search_type' => $search->get_type()]),
|
||||
|
@ -336,8 +335,8 @@ class acp_search
|
|||
}
|
||||
|
||||
$this->template->assign_vars([
|
||||
'U_ACTION' => $this->u_action . '&hash=' . generate_link_hash('acp_search'),
|
||||
'UA_PROGRESS_BAR' => addslashes($this->u_action . '&action=progress_bar'),
|
||||
'U_ACTION' => $this->u_action . '&hash=' . generate_link_hash('acp_search'),
|
||||
'UA_PROGRESS_BAR' => addslashes($this->u_action . '&action=progress_bar'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -346,13 +345,14 @@ class acp_search
|
|||
*
|
||||
* @param string $id
|
||||
* @param string $mode
|
||||
* @param string $action Action in progress: 'create' or 'delete'
|
||||
*/
|
||||
private function index_inprogress(string $id, string $mode, string $action): void
|
||||
private function index_inprogress(string $id, string $mode): void
|
||||
{
|
||||
$this->tpl_name = 'acp_search_index_inprogress';
|
||||
$this->page_title = 'ACP_SEARCH_INDEX';
|
||||
|
||||
$action = $this->search_state_helper->action();
|
||||
|
||||
$this->template->assign_vars([
|
||||
'U_ACTION' => $this->u_action . '&action=' . $action . '&hash=' . generate_link_hash('acp_search'),
|
||||
'UA_PROGRESS_BAR' => addslashes($this->u_action . '&action=progress_bar'),
|
||||
|
@ -368,9 +368,8 @@ class acp_search
|
|||
* @param string $id
|
||||
* @param string $mode
|
||||
* @param string $action
|
||||
* @param array $state
|
||||
*/
|
||||
private function index_action(string $id, string $mode, string $action, array $state): void
|
||||
private function index_action(string $id, string $mode, string $action): void
|
||||
{
|
||||
// For some this may be of help...
|
||||
@ini_set('memory_limit', '128M');
|
||||
|
@ -381,29 +380,23 @@ class acp_search
|
|||
}
|
||||
|
||||
// Entering here for the first time
|
||||
if (empty($state))
|
||||
if (!$this->search_state_helper->is_action_in_progress())
|
||||
{
|
||||
if ($this->request->is_set_post('search_type', ''))
|
||||
{
|
||||
$state = [
|
||||
self::STATE_SEARCH_TYPE => $this->request->variable('search_type', ''),
|
||||
self::STATE_ACTION => $action,
|
||||
self::STATE_POST_COUNTER => 0
|
||||
];
|
||||
$this->search_state_helper->init($this->request->variable('search_type', ''), $action);
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error($this->language->lang('FORM_INVALID') . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$this->save_state($state); // Create new state in the database
|
||||
}
|
||||
|
||||
$type = $state[self::STATE_SEARCH_TYPE];
|
||||
$action = $state[self::STATE_ACTION];
|
||||
$post_counter = &$state[self::STATE_POST_COUNTER];
|
||||
|
||||
// Execute create/delete
|
||||
$type = $this->search_state_helper->type();
|
||||
$action = $this->search_state_helper->action();
|
||||
$post_counter = $this->search_state_helper->counter();
|
||||
|
||||
$search = $this->search_backend_factory->get($type);
|
||||
|
||||
try
|
||||
|
@ -411,7 +404,7 @@ class acp_search
|
|||
$status = ($action == 'create') ? $search->create_index($post_counter) : $search->delete_index($post_counter);
|
||||
if ($status) // Status is not null, so action is in progress....
|
||||
{
|
||||
$this->save_state($state); // update $post_counter in $state in the database
|
||||
$this->search_state_helper->update_counter($status['post_counter']);
|
||||
|
||||
$u_action = append_sid($this->phpbb_admin_path . "index." . $this->php_ex, "i=$id&mode=$mode&action=$action&hash=" . generate_link_hash('acp_search'), false);
|
||||
meta_refresh(1, $u_action);
|
||||
|
@ -423,13 +416,13 @@ class acp_search
|
|||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$this->save_state([]); // Unexpected error, cancel action
|
||||
$this->search_state_helper->clear_state(); // Unexpected error, cancel action
|
||||
trigger_error($e->getMessage() . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$search->tidy();
|
||||
|
||||
$this->save_state([]); // finished operation, cancel action
|
||||
$this->search_state_helper->clear_state(); // finished operation, cancel action
|
||||
|
||||
$log_operation = ($action == 'create') ? 'LOG_SEARCH_INDEX_CREATED' : 'LOG_SEARCH_INDEX_REMOVED';
|
||||
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $log_operation, false, [$search->get_name()]);
|
||||
|
@ -473,14 +466,4 @@ class acp_search
|
|||
"// ]]>\n" .
|
||||
"</script>\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $state
|
||||
*/
|
||||
private function save_state(array $state = []): void
|
||||
{
|
||||
ksort($state);
|
||||
|
||||
$this->config->set('search_indexing_state', implode(',', $state), true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1092,16 +1092,9 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =
|
|||
$search_backend_factory = $phpbb_container->get('search.backend_factory');
|
||||
$search = $search_backend_factory->get_active();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
catch (\phpbb\search\exception\no_search_backend_found_exception $e)
|
||||
{
|
||||
if (strpos($e->getMessage(), 'No service found') === 0)
|
||||
{
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
|
||||
$search->index_remove($post_ids, $poster_ids, $forum_ids);
|
||||
|
|
|
@ -2356,16 +2356,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data
|
|||
$search_backend_factory = $phpbb_container->get('search.backend_factory');
|
||||
$search = $search_backend_factory->get_active();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
catch (\phpbb\search\exception\no_search_backend_found_exception $e)
|
||||
{
|
||||
if (strpos($e->getMessage(), 'No service found') === 0)
|
||||
{
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
|
||||
$search->index($mode, (int) $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, (int) $data_ary['forum_id']);
|
||||
|
|
|
@ -1397,16 +1397,9 @@ function mcp_fork_topic($topic_ids)
|
|||
$search_backend_factory = $phpbb_container->get('search.backend_factory');
|
||||
$search = $search_backend_factory->get_active();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
catch (\phpbb\search\exception\no_search_backend_found_exception $e)
|
||||
{
|
||||
if (strpos($e->getMessage(), 'No service found') === 0)
|
||||
{
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
$search_mode = 'post';
|
||||
}
|
||||
|
|
|
@ -637,16 +637,9 @@ function change_poster(&$post_info, $userdata)
|
|||
$search_backend_factory = $phpbb_container->get('search.backend_factory');
|
||||
$search = $search_backend_factory->get_active();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
catch (\phpbb\search\exception\no_search_backend_found_exception $e)
|
||||
{
|
||||
if (strpos($e->getMessage(), 'No service found') === 0)
|
||||
{
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
|
||||
$search->index_remove([], [$post_info['user_id'], $userdata['user_id']], []);
|
||||
|
|
|
@ -680,16 +680,9 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
|
|||
$search_backend_factory = $phpbb_container->get('search.backend_factory');
|
||||
$search = $search_backend_factory->get_active();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
catch (\phpbb\search\exception\no_search_backend_found_exception $e)
|
||||
{
|
||||
if (strpos($e->getMessage(), 'No service found') === 0)
|
||||
{
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
|
||||
$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']);
|
||||
|
|
|
@ -91,6 +91,8 @@ $lang = array_merge($lang, array(
|
|||
'GENERAL_SEARCH_SETTINGS' => 'General search settings',
|
||||
'GO_TO_SEARCH_INDEX' => 'Go to search index page',
|
||||
|
||||
'INVALID_ACTION' => 'Invalid action',
|
||||
|
||||
'INDEX_STATS' => 'Index statistics',
|
||||
'INDEXING_IN_PROGRESS' => 'Indexing in progress',
|
||||
'INDEXING_IN_PROGRESS_EXPLAIN' => 'The search backend is currently indexing all posts on the board. This can take from a few minutes to a few hours depending on your board’s size.',
|
||||
|
|
|
@ -83,6 +83,10 @@ $lang = array_merge($lang, array(
|
|||
'CLI_DESCRIPTION_SET_ATOMIC_CONFIG' => 'Sets a configuration option’s value only if the old matches the current value',
|
||||
'CLI_DESCRIPTION_SET_CONFIG' => 'Sets a configuration option’s value',
|
||||
|
||||
'CLI_DESCRIPTION_SEARCHINDEX_DELETE' => 'Delete search index.',
|
||||
'CLI_DESCRIPTION_SEARCHINDEX_CREATE' => 'Create search index.',
|
||||
'CLI_DESCRIPTION_SEARCHINDEX_LIST' => 'List all search backends.',
|
||||
|
||||
'CLI_DESCRIPTION_THUMBNAIL_DELETE' => 'Delete all existing thumbnails.',
|
||||
'CLI_DESCRIPTION_THUMBNAIL_GENERATE' => 'Generate all missing thumbnails.',
|
||||
'CLI_DESCRIPTION_THUMBNAIL_RECREATE' => 'Recreate all thumbnails.',
|
||||
|
@ -142,6 +146,16 @@ $lang = array_merge($lang, array(
|
|||
'CLI_REPARSER_REPARSE_REPARSING_START' => 'Reparsing %s...',
|
||||
'CLI_REPARSER_REPARSE_SUCCESS' => 'Reparsing ended with success',
|
||||
|
||||
'CLI_SEARCHINDEX_SEARCH_BACKEND_NAME' => 'Backend class',
|
||||
'CLI_SEARCHINDEX_BACKEND_NOT_FOUND' => 'Search module not found',
|
||||
'CLI_SEARCHINDEX_CREATE_SUCCESS' => 'Search index created successfully',
|
||||
'CLI_SEARCHINDEX_CREATE_FAILURE' => 'Error creating search index',
|
||||
'CLI_SEARCHINDEX_DELETE_SUCCESS' => 'Search index deleted successfully',
|
||||
'CLI_SEARCHINDEX_DELETE_FAILURE' => 'Error deleting search index',
|
||||
'CLI_SEARCHINDEX_ACTION_IN_PROGRESS' => 'There is an action currently in progress. CLI doesn’t support incomplete index/delete actions, please solve it from the ACP.',
|
||||
'CLI_SEARCHINDEX_ACTIVE_NOT_INDEXED' => 'Active search backend isn’t indexed',
|
||||
'CLI_SEARCHINDEX_BACKEND_NOT_AVAILABLE' => 'Search backend isn’t available.',
|
||||
|
||||
// In all the case %1$s is the logical name of the file and %2$s the real name on the filesystem
|
||||
// eg: big_image.png (2_a51529ae7932008cf8454a95af84cacd) generated.
|
||||
'CLI_THUMBNAIL_DELETED' => '%1$s (%2$s) deleted.',
|
||||
|
|
|
@ -215,6 +215,9 @@ $lang = array_merge($lang, array(
|
|||
2 => 'Downloaded %d times',
|
||||
),
|
||||
|
||||
'DI_SERVICE_NOT_FOUND' => 'Service for class "%1$s" not found in collection.',
|
||||
'DI_MULTIPLE_SERVICE_DEFINITIONS' => 'More than one service definitions found for class "%1$s" in collection.',
|
||||
|
||||
'EDIT_POST' => 'Edit post',
|
||||
'ELLIPSIS' => '…',
|
||||
'EMAIL' => 'Email', // Short form for EMAIL_ADDRESS
|
||||
|
@ -715,6 +718,7 @@ $lang = array_merge($lang, array(
|
|||
'SEARCH_UNANSWERED' => 'Unanswered topics',
|
||||
'SEARCH_UNREAD' => 'Unread posts',
|
||||
'SEARCH_USER_POSTS' => 'Search user’s posts',
|
||||
'SEARCH_BACKEND_NOT_FOUND' => 'No search backend could be found.',
|
||||
'SECONDS' => 'Seconds',
|
||||
'SEE_ALL' => 'See All',
|
||||
'SELECT' => 'Select',
|
||||
|
|
|
@ -49,10 +49,8 @@ class list_all extends \phpbb\console\command\command
|
|||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('reparser:list')
|
||||
->setDescription($this->user->lang('CLI_DESCRIPTION_REPARSER_LIST'))
|
||||
;
|
||||
$this->setName('reparser:list')
|
||||
->setDescription($this->user->lang('CLI_DESCRIPTION_REPARSER_LIST'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
165
phpBB/phpbb/console/command/searchindex/create.php
Normal file
165
phpBB/phpbb/console/command/searchindex/create.php
Normal file
|
@ -0,0 +1,165 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\console\command\searchindex;
|
||||
|
||||
use phpbb\console\command\command;
|
||||
use phpbb\language\language;
|
||||
use phpbb\log\log;
|
||||
use phpbb\posting\post_helper;
|
||||
use phpbb\search\exception\no_search_backend_found_exception;
|
||||
use phpbb\search\search_backend_factory;
|
||||
use phpbb\search\state_helper;
|
||||
use phpbb\user;
|
||||
use Symfony\Component\Console\Command\Command as symfony_command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
class create extends command
|
||||
{
|
||||
/** @var language */
|
||||
protected $language;
|
||||
|
||||
/** @var log */
|
||||
protected $log;
|
||||
|
||||
/** @var post_helper */
|
||||
protected $post_helper;
|
||||
|
||||
/** @var search_backend_factory */
|
||||
protected $search_backend_factory;
|
||||
|
||||
/** @var state_helper */
|
||||
protected $state_helper;
|
||||
|
||||
/**
|
||||
* Construct method
|
||||
*
|
||||
* @param language $language
|
||||
* @param log $log
|
||||
* @param post_helper $post_helper
|
||||
* @param search_backend_factory $search_backend_factory
|
||||
* @param state_helper $state_helper
|
||||
* @param user $user
|
||||
*/
|
||||
public function __construct(language $language, log $log, post_helper $post_helper, search_backend_factory $search_backend_factory, state_helper $state_helper, user $user)
|
||||
{
|
||||
$this->language = $language;
|
||||
$this->log = $log;
|
||||
$this->post_helper = $post_helper;
|
||||
$this->search_backend_factory = $search_backend_factory;
|
||||
$this->state_helper = $state_helper;
|
||||
|
||||
$this->language->add_lang(array('acp/common', 'acp/search'));
|
||||
|
||||
parent::__construct($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command name and description
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('searchindex:create')
|
||||
->setDescription($this->language->lang('CLI_DESCRIPTION_SEARCHINDEX_CREATE'))
|
||||
->addArgument(
|
||||
'search-backend',
|
||||
InputArgument::REQUIRED,
|
||||
$this->language->lang('CLI_SEARCHINDEX_SEARCH_BACKEND_NAME')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the command searchindex:create
|
||||
*
|
||||
* Create search index
|
||||
*
|
||||
* @param InputInterface $input The input stream used to get the options
|
||||
* @param OutputInterface $output The output stream, used to print messages
|
||||
*
|
||||
* @return int 0 if all is well, 1 if any errors occurred
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$io->section($this->language->lang('CLI_DESCRIPTION_SEARCHINDEX_CREATE'));
|
||||
|
||||
$search_backend = $input->getArgument('search-backend');
|
||||
|
||||
try
|
||||
{
|
||||
$search = $this->search_backend_factory->get($search_backend);
|
||||
$name = $search->get_name();
|
||||
}
|
||||
catch (no_search_backend_found_exception $e)
|
||||
{
|
||||
$io->error($this->language->lang('CLI_SEARCHINDEX_BACKEND_NOT_FOUND', $search_backend));
|
||||
return symfony_command::FAILURE;
|
||||
}
|
||||
|
||||
if ($this->state_helper->is_action_in_progress())
|
||||
{
|
||||
$io->error($this->language->lang('CLI_SEARCHINDEX_ACTION_IN_PROGRESS', $search_backend));
|
||||
return symfony_command::FAILURE;
|
||||
}
|
||||
|
||||
if (!$search->is_available())
|
||||
{
|
||||
$io->error($this->language->lang('CLI_SEARCHINDEX_BACKEND_NOT_AVAILABLE', $search_backend));
|
||||
return symfony_command::FAILURE;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$progress = $this->create_progress_bar($this->post_helper->get_max_post_id(), $io, $output, true);
|
||||
$progress->setMessage('');
|
||||
$progress->start();
|
||||
|
||||
$this->state_helper->init($search->get_type(), 'create');
|
||||
|
||||
$counter = 0;
|
||||
while (($status = $search->create_index($counter)) !== null)
|
||||
{
|
||||
$this->state_helper->update_counter($status['post_counter']);
|
||||
|
||||
$progress->setProgress($status['post_counter']);
|
||||
$progress->setMessage(round($status['rows_per_second'], 2) . ' rows/s');
|
||||
}
|
||||
|
||||
$progress->finish();
|
||||
|
||||
$io->newLine(2);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$this->state_helper->clear_state(); // Unexpected error, cancel action
|
||||
$io->error($e->getMessage()); // Show also exception message like in acp
|
||||
$io->error($this->language->lang('CLI_SEARCHINDEX_CREATE_FAILURE', $name));
|
||||
return symfony_command::FAILURE;
|
||||
}
|
||||
|
||||
$search->tidy();
|
||||
|
||||
$this->state_helper->clear_state();
|
||||
|
||||
$this->log->add('admin', ANONYMOUS, '', 'LOG_SEARCH_INDEX_CREATED', false, array($name));
|
||||
$io->success($this->language->lang('CLI_SEARCHINDEX_CREATE_SUCCESS', $name));
|
||||
|
||||
return symfony_command::SUCCESS;
|
||||
}
|
||||
}
|
165
phpBB/phpbb/console/command/searchindex/delete.php
Normal file
165
phpBB/phpbb/console/command/searchindex/delete.php
Normal file
|
@ -0,0 +1,165 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\console\command\searchindex;
|
||||
|
||||
use phpbb\console\command\command;
|
||||
use phpbb\language\language;
|
||||
use phpbb\log\log;
|
||||
use phpbb\posting\post_helper;
|
||||
use phpbb\search\exception\no_search_backend_found_exception;
|
||||
use phpbb\search\search_backend_factory;
|
||||
use phpbb\search\state_helper;
|
||||
use phpbb\user;
|
||||
use Symfony\Component\Console\Command\Command as symfony_command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
class delete extends command
|
||||
{
|
||||
/** @var language */
|
||||
protected $language;
|
||||
|
||||
/** @var log */
|
||||
protected $log;
|
||||
|
||||
/** @var post_helper */
|
||||
protected $post_helper;
|
||||
|
||||
/** @var search_backend_factory */
|
||||
protected $search_backend_factory;
|
||||
|
||||
/** @var state_helper */
|
||||
protected $state_helper;
|
||||
|
||||
/**
|
||||
* Construct method
|
||||
*
|
||||
* @param language $language
|
||||
* @param log $log
|
||||
* @param post_helper $post_helper
|
||||
* @param search_backend_factory $search_backend_factory
|
||||
* @param state_helper $state_helper
|
||||
* @param user $user
|
||||
*/
|
||||
public function __construct(language $language, log $log, post_helper $post_helper, search_backend_factory $search_backend_factory, state_helper $state_helper, user $user)
|
||||
{
|
||||
$this->language = $language;
|
||||
$this->log = $log;
|
||||
$this->post_helper = $post_helper;
|
||||
$this->search_backend_factory = $search_backend_factory;
|
||||
$this->state_helper = $state_helper;
|
||||
|
||||
$this->language->add_lang(array('acp/common', 'acp/search'));
|
||||
|
||||
parent::__construct($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command name and description
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('searchindex:delete')
|
||||
->setDescription($this->language->lang('CLI_DESCRIPTION_SEARCHINDEX_DELETE'))
|
||||
->addArgument(
|
||||
'search-backend',
|
||||
InputArgument::REQUIRED,
|
||||
$this->language->lang('CLI_SEARCHINDEX_SEARCH_BACKEND_NAME')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the command searchindex:delete
|
||||
*
|
||||
* Delete search index
|
||||
*
|
||||
* @param InputInterface $input The input stream used to get the options
|
||||
* @param OutputInterface $output The output stream, used to print messages
|
||||
*
|
||||
* @return int 0 if all is well, 1 if any errors occurred
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$io->section($this->language->lang('CLI_DESCRIPTION_SEARCHINDEX_DELETE'));
|
||||
|
||||
$search_backend = $input->getArgument('search-backend');
|
||||
|
||||
try
|
||||
{
|
||||
$search = $this->search_backend_factory->get($search_backend);
|
||||
$name = $search->get_name();
|
||||
}
|
||||
catch (no_search_backend_found_exception $e)
|
||||
{
|
||||
$io->error($this->language->lang('CLI_SEARCHINDEX_BACKEND_NOT_FOUND', $search_backend));
|
||||
return symfony_command::FAILURE;
|
||||
}
|
||||
|
||||
if ($this->state_helper->is_action_in_progress())
|
||||
{
|
||||
$io->error($this->language->lang('CLI_SEARCHINDEX_ACTION_IN_PROGRESS', $search_backend));
|
||||
return symfony_command::FAILURE;
|
||||
}
|
||||
|
||||
if (!$search->is_available())
|
||||
{
|
||||
$io->error($this->language->lang('CLI_SEARCHINDEX_BACKEND_NOT_AVAILABLE', $search_backend));
|
||||
return symfony_command::FAILURE;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$progress = $this->create_progress_bar($this->post_helper->get_max_post_id(), $io, $output, true);
|
||||
$progress->setMessage('');
|
||||
$progress->start();
|
||||
|
||||
$this->state_helper->init($search->get_type(), 'delete');
|
||||
|
||||
$counter = 0;
|
||||
while (($status = $search->delete_index($counter)) !== null)
|
||||
{
|
||||
$this->state_helper->update_counter($status['post_counter']);
|
||||
|
||||
$progress->setProgress($status['post_counter']);
|
||||
$progress->setMessage(round($status['rows_per_second'], 2) . ' rows/s');
|
||||
}
|
||||
|
||||
$progress->finish();
|
||||
|
||||
$io->newLine(2);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$this->state_helper->clear_state(); // Unexpected error, cancel action
|
||||
$io->error($e->getMessage()); // Show also exception message like in acp
|
||||
$io->error($this->language->lang('CLI_SEARCHINDEX_DELETE_FAILURE', $name));
|
||||
return symfony_command::FAILURE;
|
||||
}
|
||||
|
||||
$search->tidy();
|
||||
|
||||
$this->state_helper->clear_state();
|
||||
|
||||
$this->log->add('admin', ANONYMOUS, '', 'LOG_SEARCH_INDEX_REMOVED', false, array($name));
|
||||
$io->success($this->language->lang('CLI_SEARCHINDEX_DELETE_SUCCESS', $name));
|
||||
|
||||
return symfony_command::SUCCESS;
|
||||
}
|
||||
}
|
96
phpBB/phpbb/console/command/searchindex/list_all.php
Normal file
96
phpBB/phpbb/console/command/searchindex/list_all.php
Normal file
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\console\command\searchindex;
|
||||
|
||||
use phpbb\config\config;
|
||||
use phpbb\console\command\command;
|
||||
use phpbb\di\service_collection;
|
||||
use phpbb\language\language;
|
||||
use phpbb\user;
|
||||
use Symfony\Component\Console\Command\Command as symfony_command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
class list_all extends command
|
||||
{
|
||||
/** @var config */
|
||||
protected $config;
|
||||
|
||||
/** @var language */
|
||||
protected $language;
|
||||
|
||||
/** @var service_collection */
|
||||
protected $search_backend_collection;
|
||||
|
||||
/**
|
||||
* Construct method
|
||||
*
|
||||
* @param config $config
|
||||
* @param language $language
|
||||
* @param service_collection $search_backend_collection
|
||||
* @param user $user
|
||||
*/
|
||||
public function __construct(config $config, language $language, service_collection $search_backend_collection, user $user)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->language = $language;
|
||||
$this->search_backend_collection = $search_backend_collection;
|
||||
|
||||
parent::__construct($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command name and description
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('searchindex:list')
|
||||
->setDescription($this->language->lang('CLI_DESCRIPTION_SEARCHINDEX_LIST'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the command searchindex:list
|
||||
*
|
||||
* List all search backends.
|
||||
*
|
||||
* @param InputInterface $input The input stream used to get the options
|
||||
* @param OutputInterface $output The output stream, used to print messages
|
||||
*
|
||||
* @return int 0 if all is well, 1 if any errors occurred
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$search_backends = [];
|
||||
foreach ($this->search_backend_collection as $search_backend)
|
||||
{
|
||||
$name = $search_backend->get_type();
|
||||
$active = ($name === $this->config['search_type']) ? '(<comment>' . $this->language->lang('ACTIVE') . '</comment>) ' : '';
|
||||
$search_backends[] = '<info>' . $name . '</info> ' . $active . $search_backend->get_name();
|
||||
|
||||
if ($name === $this->config['search_type'] && !$search_backend->index_created())
|
||||
{
|
||||
$io->error($this->language->lang('CLI_SEARCHINDEX_ACTIVE_NOT_INDEXED'));
|
||||
}
|
||||
}
|
||||
|
||||
$io->listing($search_backends);
|
||||
|
||||
return symfony_command::SUCCESS;
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ namespace phpbb\cron\task\core;
|
|||
|
||||
use phpbb\config\config;
|
||||
use phpbb\cron\task\base;
|
||||
use phpbb\di\exception\di_exception;
|
||||
use phpbb\search\backend\search_backend_interface;
|
||||
use phpbb\search\search_backend_factory;
|
||||
|
||||
|
@ -88,7 +89,7 @@ class tidy_search extends base
|
|||
$this->active_search = $this->search_backend_factory->get_active();
|
||||
}
|
||||
}
|
||||
catch (\RuntimeException $e)
|
||||
catch (di_exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
20
phpBB/phpbb/di/exception/di_exception.php
Normal file
20
phpBB/phpbb/di/exception/di_exception.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\di\exception;
|
||||
|
||||
use phpbb\exception\runtime_exception;
|
||||
|
||||
class di_exception extends runtime_exception
|
||||
{
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\di\exception;
|
||||
|
||||
class multiple_service_definitions_exception extends di_exception
|
||||
{
|
||||
}
|
18
phpBB/phpbb/di/exception/service_not_found_exception.php
Normal file
18
phpBB/phpbb/di/exception/service_not_found_exception.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\di\exception;
|
||||
|
||||
class service_not_found_exception extends di_exception
|
||||
{
|
||||
}
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
namespace phpbb\di;
|
||||
|
||||
use phpbb\di\exception\multiple_service_definitions_exception;
|
||||
use phpbb\di\exception\service_not_found_exception;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
|
@ -105,7 +107,7 @@ class service_collection extends \ArrayObject
|
|||
{
|
||||
if ($service_id !== null)
|
||||
{
|
||||
throw new \RuntimeException('More than one service definitions found for class "'.$class.'" in collection.');
|
||||
throw new multiple_service_definitions_exception('DI_MULTIPLE_SERVICE_DEFINITIONS', [$class]);
|
||||
}
|
||||
|
||||
$service_id = $id;
|
||||
|
@ -114,7 +116,7 @@ class service_collection extends \ArrayObject
|
|||
|
||||
if ($service_id === null)
|
||||
{
|
||||
throw new \RuntimeException('No service found for class "'.$class.'" in collection.');
|
||||
throw new service_not_found_exception('DI_SERVICE_NOT_FOUND', [$class]);
|
||||
}
|
||||
|
||||
return $this->offsetGet($service_id);
|
||||
|
|
|
@ -133,6 +133,9 @@ class create_search_index extends database_task
|
|||
$this->phpbb_dispatcher,
|
||||
$container->get('language'),
|
||||
$this->user,
|
||||
SEARCH_RESULTS_TABLE,
|
||||
SEARCH_WORDLIST_TABLE,
|
||||
SEARCH_WORDMATCH_TABLE,
|
||||
$this->phpbb_root_path,
|
||||
$this->php_ext
|
||||
);
|
||||
|
|
43
phpBB/phpbb/posting/post_helper.php
Normal file
43
phpBB/phpbb/posting/post_helper.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\posting;
|
||||
|
||||
use phpbb\db\driver\driver_interface;
|
||||
|
||||
class post_helper
|
||||
{
|
||||
/**
|
||||
* @var driver_interface
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
public function __construct(driver_interface $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last post id
|
||||
*/
|
||||
public 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;
|
||||
}
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search\backend;
|
||||
|
||||
|
@ -19,9 +19,9 @@ 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
|
||||
*/
|
||||
* optional base class for search plugins providing simple caching based on ACM
|
||||
* and functions to retrieve ignore_words and synonyms
|
||||
*/
|
||||
abstract class base implements search_backend_interface
|
||||
{
|
||||
public const SEARCH_RESULT_NOT_IN_CACHE = 0;
|
||||
|
@ -51,20 +51,27 @@ abstract class base implements search_backend_interface
|
|||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $search_results_table;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param service $cache
|
||||
* @param config $config
|
||||
* @param driver_interface $db
|
||||
* @param user $user
|
||||
* @param service $cache
|
||||
* @param config $config
|
||||
* @param driver_interface $db
|
||||
* @param user $user
|
||||
* @param string $search_results_table
|
||||
*/
|
||||
public function __construct(service $cache, config $config, driver_interface $db, user $user)
|
||||
public function __construct(service $cache, config $config, driver_interface $db, user $user, string $search_results_table)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
$this->config = $config;
|
||||
$this->db = $db;
|
||||
$this->user = $user;
|
||||
$this->search_results_table = $search_results_table;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,7 +187,7 @@ abstract class base implements search_backend_interface
|
|||
if (!empty($keywords) || count($author_ary))
|
||||
{
|
||||
$sql = 'SELECT search_time
|
||||
FROM ' . SEARCH_RESULTS_TABLE . '
|
||||
FROM ' . $this->search_results_table . '
|
||||
WHERE search_key = \'' . $this->db->sql_escape($search_key) . '\'';
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
|
@ -193,7 +200,7 @@ abstract class base implements search_backend_interface
|
|||
'search_authors' => ' ' . implode(' ', $author_ary) . ' '
|
||||
);
|
||||
|
||||
$sql = 'INSERT INTO ' . SEARCH_RESULTS_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
|
||||
$sql = 'INSERT INTO ' . $this->search_results_table . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
@ -253,7 +260,7 @@ abstract class base implements search_backend_interface
|
|||
}
|
||||
$this->cache->put('_search_results_' . $search_key, $store, $this->config['search_store_results']);
|
||||
|
||||
$sql = 'UPDATE ' . SEARCH_RESULTS_TABLE . '
|
||||
$sql = 'UPDATE ' . $this->search_results_table . '
|
||||
SET search_time = ' . time() . '
|
||||
WHERE search_key = \'' . $this->db->sql_escape($search_key) . '\'';
|
||||
$this->db->sql_query($sql);
|
||||
|
@ -280,7 +287,7 @@ abstract class base implements search_backend_interface
|
|||
}
|
||||
|
||||
$sql = 'SELECT search_key
|
||||
FROM ' . SEARCH_RESULTS_TABLE . "
|
||||
FROM ' . $this->search_results_table . "
|
||||
WHERE search_keywords LIKE '%*%' $sql_where";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
|
@ -301,7 +308,7 @@ abstract class base implements search_backend_interface
|
|||
}
|
||||
|
||||
$sql = 'SELECT search_key
|
||||
FROM ' . SEARCH_RESULTS_TABLE . "
|
||||
FROM ' . $this->search_results_table . "
|
||||
WHERE $sql_where";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
|
@ -313,7 +320,7 @@ abstract class base implements search_backend_interface
|
|||
}
|
||||
|
||||
$sql = 'DELETE
|
||||
FROM ' . SEARCH_RESULTS_TABLE . '
|
||||
FROM ' . $this->search_results_table . '
|
||||
WHERE search_time < ' . (time() - (int) $this->config['search_store_results']);
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
|
@ -329,7 +336,7 @@ abstract class base implements search_backend_interface
|
|||
$starttime = microtime(true);
|
||||
$row_count = 0;
|
||||
|
||||
while (still_on_time() && $post_counter <= $max_post_id)
|
||||
while (still_on_time() && $post_counter < $max_post_id)
|
||||
{
|
||||
$rows = $this->get_posts_batch_after($post_counter);
|
||||
|
||||
|
@ -346,7 +353,13 @@ abstract class base implements search_backend_interface
|
|||
$this->index('post', (int) $row['post_id'], $row['post_text'], $row['post_subject'], (int) $row['poster_id'], (int) $row['forum_id']);
|
||||
}
|
||||
$row_count++;
|
||||
$post_counter = $row['post_id'];
|
||||
$post_counter = (int) $row['post_id'];
|
||||
}
|
||||
|
||||
// With cli process only one batch each time to be able to track progress
|
||||
if (PHP_SAPI === 'cli')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,7 +370,7 @@ abstract class base implements search_backend_interface
|
|||
$this->tidy();
|
||||
$this->config['num_posts'] = $num_posts;
|
||||
|
||||
if ($post_counter < $max_post_id)
|
||||
if ($post_counter < $max_post_id) // If there are still post to index
|
||||
{
|
||||
$totaltime = microtime(true) - $starttime;
|
||||
$rows_per_second = $row_count / $totaltime;
|
||||
|
@ -382,7 +395,8 @@ abstract class base implements search_backend_interface
|
|||
|
||||
$starttime = microtime(true);
|
||||
$row_count = 0;
|
||||
while (still_on_time() && $post_counter <= $max_post_id)
|
||||
|
||||
while (still_on_time() && $post_counter < $max_post_id)
|
||||
{
|
||||
$rows = $this->get_posts_batch_after($post_counter);
|
||||
$ids = $posters = $forum_ids = array();
|
||||
|
@ -399,9 +413,15 @@ abstract class base implements search_backend_interface
|
|||
$this->index_remove($ids, $posters, $forum_ids);
|
||||
$post_counter = $ids[count($ids) - 1];
|
||||
}
|
||||
|
||||
// With cli process only one batch each time to be able to track progress
|
||||
if (PHP_SAPI === 'cli')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($post_counter < $max_post_id)
|
||||
if ($post_counter < $max_post_id) // If there are still post delete from index
|
||||
{
|
||||
$totaltime = microtime(true) - $starttime;
|
||||
$rows_per_second = $row_count / $totaltime;
|
||||
|
|
|
@ -17,8 +17,8 @@ use phpbb\config\config;
|
|||
use phpbb\db\driver\driver_interface;
|
||||
use phpbb\event\dispatcher_interface;
|
||||
use phpbb\language\language;
|
||||
use phpbb\search\exception\search_exception;
|
||||
use phpbb\user;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Fulltext search for MySQL
|
||||
|
@ -72,19 +72,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 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
|
||||
* @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 $search_results_table
|
||||
* @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, 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 $search_results_table, string $phpbb_root_path, string $phpEx)
|
||||
{
|
||||
global $cache;
|
||||
|
||||
parent::__construct($cache, $config, $db, $user);
|
||||
parent::__construct($cache, $config, $db, $user, $search_results_table);
|
||||
$this->phpbb_dispatcher = $phpbb_dispatcher;
|
||||
$this->language = $language;
|
||||
|
||||
|
@ -916,7 +917,7 @@ class fulltext_mysql extends base implements search_backend_interface
|
|||
// Make sure we can actually use MySQL with fulltext indexes
|
||||
if ($error = $this->init())
|
||||
{
|
||||
throw new RuntimeException($error);
|
||||
throw new search_exception($error);
|
||||
}
|
||||
|
||||
if (empty($this->stats))
|
||||
|
@ -975,7 +976,7 @@ class fulltext_mysql extends base implements search_backend_interface
|
|||
$this->db->sql_query($sql_query);
|
||||
}
|
||||
|
||||
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
|
||||
$this->db->sql_query('TRUNCATE TABLE ' . $this->search_results_table);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -988,7 +989,7 @@ class fulltext_mysql extends base implements search_backend_interface
|
|||
// Make sure we can actually use MySQL with fulltext indexes
|
||||
if ($error = $this->init())
|
||||
{
|
||||
throw new RuntimeException($error);
|
||||
throw new search_exception($error);
|
||||
}
|
||||
|
||||
if (empty($this->stats))
|
||||
|
@ -1041,7 +1042,7 @@ class fulltext_mysql extends base implements search_backend_interface
|
|||
$this->db->sql_query($sql_query);
|
||||
}
|
||||
|
||||
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
|
||||
$this->db->sql_query('TRUNCATE TABLE ' . $this->search_results_table);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -93,30 +93,42 @@ class fulltext_native extends base implements search_backend_interface
|
|||
*/
|
||||
protected $phpbb_dispatcher;
|
||||
|
||||
/**
|
||||
* @var language
|
||||
*/
|
||||
/** @var language */
|
||||
protected $language;
|
||||
|
||||
/** @var string */
|
||||
protected $search_wordlist_table;
|
||||
|
||||
/** @var string */
|
||||
protected $search_wordmatch_table;
|
||||
|
||||
/**
|
||||
* 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 language $language
|
||||
* @param user $user User object
|
||||
* @param string $phpbb_root_path phpBB root path
|
||||
* @param string $phpEx PHP file extension
|
||||
* @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 $search_results_table
|
||||
* @param string $search_wordlist_table
|
||||
* @param string $search_wordmatch_table
|
||||
* @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, 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 $search_results_table, string $search_wordlist_table,
|
||||
string $search_wordmatch_table, string $phpbb_root_path, string $phpEx)
|
||||
{
|
||||
global $cache;
|
||||
|
||||
parent::__construct($cache, $config, $db, $user);
|
||||
parent::__construct($cache, $config, $db, $user, $search_results_table);
|
||||
$this->phpbb_dispatcher = $phpbb_dispatcher;
|
||||
$this->language = $language;
|
||||
|
||||
$this->search_wordlist_table = $search_wordlist_table;
|
||||
$this->search_wordmatch_table = $search_wordmatch_table;
|
||||
|
||||
$this->phpbb_root_path = $phpbb_root_path;
|
||||
$this->php_ext = $phpEx;
|
||||
|
||||
|
@ -335,7 +347,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
if (count($exact_words))
|
||||
{
|
||||
$sql = 'SELECT word_id, word_text, word_common
|
||||
FROM ' . SEARCH_WORDLIST_TABLE . '
|
||||
FROM ' . $this->search_wordlist_table . '
|
||||
WHERE ' . $this->db->sql_in_set('word_text', $exact_words) . '
|
||||
ORDER BY word_count ASC';
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
@ -607,8 +619,8 @@ class fulltext_native extends base implements search_backend_interface
|
|||
$sql_array = array(
|
||||
'SELECT' => ($type == 'posts') ? 'DISTINCT p.post_id' : 'DISTINCT p.topic_id',
|
||||
'FROM' => array(
|
||||
SEARCH_WORDMATCH_TABLE => array(),
|
||||
SEARCH_WORDLIST_TABLE => array(),
|
||||
$this->search_wordmatch_table => array(),
|
||||
$this->search_wordlist_table => array(),
|
||||
),
|
||||
'LEFT_JOIN' => array(array(
|
||||
'FROM' => array(POSTS_TABLE => 'p'),
|
||||
|
@ -660,7 +672,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
if (is_string($id))
|
||||
{
|
||||
$sql_array['LEFT_JOIN'][] = array(
|
||||
'FROM' => array(SEARCH_WORDLIST_TABLE => 'w' . $w_num),
|
||||
'FROM' => array($this->search_wordlist_table => 'w' . $w_num),
|
||||
'ON' => "w$w_num.word_text LIKE $id"
|
||||
);
|
||||
$word_ids[] = "w$w_num.word_id";
|
||||
|
@ -680,7 +692,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
}
|
||||
else if (is_string($subquery))
|
||||
{
|
||||
$sql_array['FROM'][SEARCH_WORDLIST_TABLE][] = 'w' . $w_num;
|
||||
$sql_array['FROM'][$this->search_wordlist_table][] = 'w' . $w_num;
|
||||
|
||||
$sql_where[] = "w$w_num.word_text LIKE $subquery";
|
||||
$sql_where[] = "m$m_num.word_id = w$w_num.word_id";
|
||||
|
@ -693,7 +705,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
$sql_where[] = "m$m_num.word_id = $subquery";
|
||||
}
|
||||
|
||||
$sql_array['FROM'][SEARCH_WORDMATCH_TABLE][] = 'm' . $m_num;
|
||||
$sql_array['FROM'][$this->search_wordmatch_table][] = 'm' . $m_num;
|
||||
|
||||
if ($title_match)
|
||||
{
|
||||
|
@ -712,7 +724,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
if (is_string($subquery))
|
||||
{
|
||||
$sql_array['LEFT_JOIN'][] = array(
|
||||
'FROM' => array(SEARCH_WORDLIST_TABLE => 'w' . $w_num),
|
||||
'FROM' => array($this->search_wordlist_table => 'w' . $w_num),
|
||||
'ON' => "w$w_num.word_text LIKE $subquery"
|
||||
);
|
||||
|
||||
|
@ -726,7 +738,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
if (count($this->must_not_contain_ids))
|
||||
{
|
||||
$sql_array['LEFT_JOIN'][] = array(
|
||||
'FROM' => array(SEARCH_WORDMATCH_TABLE => 'm' . $m_num),
|
||||
'FROM' => array($this->search_wordmatch_table => 'm' . $m_num),
|
||||
'ON' => $this->db->sql_in_set("m$m_num.word_id", $this->must_not_contain_ids) . (($title_match) ? " AND m$m_num.$title_match" : '') . " AND m$m_num.post_id = m0.post_id"
|
||||
);
|
||||
|
||||
|
@ -742,7 +754,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
if (is_string($id))
|
||||
{
|
||||
$sql_array['LEFT_JOIN'][] = array(
|
||||
'FROM' => array(SEARCH_WORDLIST_TABLE => 'w' . $w_num),
|
||||
'FROM' => array($this->search_wordlist_table => 'w' . $w_num),
|
||||
'ON' => "w$w_num.word_text LIKE $id"
|
||||
);
|
||||
$id = "w$w_num.word_id";
|
||||
|
@ -752,7 +764,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
}
|
||||
|
||||
$sql_array['LEFT_JOIN'][] = array(
|
||||
'FROM' => array(SEARCH_WORDMATCH_TABLE => 'm' . $m_num),
|
||||
'FROM' => array($this->search_wordmatch_table => 'm' . $m_num),
|
||||
'ON' => "m$m_num.word_id = $id AND m$m_num.post_id = m0.post_id" . (($title_match) ? " AND m$m_num.$title_match" : '')
|
||||
);
|
||||
$is_null_joins[] = "m$m_num.word_id IS NULL";
|
||||
|
@ -1310,7 +1322,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
$words['del']['title'] = array();
|
||||
|
||||
$sql = 'SELECT w.word_id, w.word_text, m.title_match
|
||||
FROM ' . SEARCH_WORDLIST_TABLE . ' w, ' . SEARCH_WORDMATCH_TABLE . " m
|
||||
FROM ' . $this->search_wordlist_table . ' w, ' . $this->search_wordmatch_table . " m
|
||||
WHERE m.post_id = $post_id
|
||||
AND w.word_id = m.word_id";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
@ -1379,7 +1391,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
if (count($unique_add_words))
|
||||
{
|
||||
$sql = 'SELECT word_id, word_text
|
||||
FROM ' . SEARCH_WORDLIST_TABLE . '
|
||||
FROM ' . $this->search_wordlist_table . '
|
||||
WHERE ' . $this->db->sql_in_set('word_text', $unique_add_words);
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
|
@ -1401,7 +1413,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
$sql_ary[] = array('word_text' => (string) $word, 'word_count' => 0);
|
||||
}
|
||||
$this->db->sql_return_on_error(true);
|
||||
$this->db->sql_multi_insert(SEARCH_WORDLIST_TABLE, $sql_ary);
|
||||
$this->db->sql_multi_insert($this->search_wordlist_table, $sql_ary);
|
||||
$this->db->sql_return_on_error(false);
|
||||
}
|
||||
unset($new_words, $sql_ary);
|
||||
|
@ -1424,13 +1436,13 @@ class fulltext_native extends base implements search_backend_interface
|
|||
$sql_in[] = $cur_words[$word_in][$word];
|
||||
}
|
||||
|
||||
$sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
|
||||
$sql = 'DELETE FROM ' . $this->search_wordmatch_table . '
|
||||
WHERE ' . $this->db->sql_in_set('word_id', $sql_in) . '
|
||||
AND post_id = ' . intval($post_id) . "
|
||||
AND title_match = $title_match";
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
|
||||
$sql = 'UPDATE ' . $this->search_wordlist_table . '
|
||||
SET word_count = word_count - 1
|
||||
WHERE ' . $this->db->sql_in_set('word_id', $sql_in) . '
|
||||
AND word_count > 0';
|
||||
|
@ -1447,13 +1459,13 @@ class fulltext_native extends base implements search_backend_interface
|
|||
|
||||
if (count($word_ary))
|
||||
{
|
||||
$sql = 'INSERT INTO ' . SEARCH_WORDMATCH_TABLE . ' (post_id, word_id, title_match)
|
||||
$sql = 'INSERT INTO ' . $this->search_wordmatch_table . ' (post_id, word_id, title_match)
|
||||
SELECT ' . (int) $post_id . ', word_id, ' . (int) $title_match . '
|
||||
FROM ' . SEARCH_WORDLIST_TABLE . '
|
||||
FROM ' . $this->search_wordlist_table . '
|
||||
WHERE ' . $this->db->sql_in_set('word_text', $word_ary);
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
|
||||
$sql = 'UPDATE ' . $this->search_wordlist_table . '
|
||||
SET word_count = word_count + 1
|
||||
WHERE ' . $this->db->sql_in_set('word_text', $word_ary);
|
||||
$this->db->sql_query($sql);
|
||||
|
@ -1479,7 +1491,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
if (count($post_ids))
|
||||
{
|
||||
$sql = 'SELECT w.word_id, w.word_text, m.title_match
|
||||
FROM ' . SEARCH_WORDMATCH_TABLE . ' m, ' . SEARCH_WORDLIST_TABLE . ' w
|
||||
FROM ' . $this->search_wordmatch_table . ' m, ' . $this->search_wordlist_table . ' w
|
||||
WHERE ' . $this->db->sql_in_set('m.post_id', $post_ids) . '
|
||||
AND w.word_id = m.word_id';
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
@ -1501,7 +1513,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
|
||||
if (count($title_word_ids))
|
||||
{
|
||||
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
|
||||
$sql = 'UPDATE ' . $this->search_wordlist_table . '
|
||||
SET word_count = word_count - 1
|
||||
WHERE ' . $this->db->sql_in_set('word_id', $title_word_ids) . '
|
||||
AND word_count > 0';
|
||||
|
@ -1510,7 +1522,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
|
||||
if (count($message_word_ids))
|
||||
{
|
||||
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
|
||||
$sql = 'UPDATE ' . $this->search_wordlist_table . '
|
||||
SET word_count = word_count - 1
|
||||
WHERE ' . $this->db->sql_in_set('word_id', $message_word_ids) . '
|
||||
AND word_count > 0';
|
||||
|
@ -1520,7 +1532,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
unset($title_word_ids);
|
||||
unset($message_word_ids);
|
||||
|
||||
$sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
|
||||
$sql = 'DELETE FROM ' . $this->search_wordmatch_table . '
|
||||
WHERE ' . $this->db->sql_in_set('post_id', $post_ids);
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
|
@ -1549,7 +1561,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
$common_threshold = ((double) $this->config['fulltext_native_common_thres']) / 100.0;
|
||||
// First, get the IDs of common words
|
||||
$sql = 'SELECT word_id, word_text
|
||||
FROM ' . SEARCH_WORDLIST_TABLE . '
|
||||
FROM ' . $this->search_wordlist_table . '
|
||||
WHERE word_count > ' . floor($this->config['num_posts'] * $common_threshold) . '
|
||||
OR word_common = 1';
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
@ -1565,7 +1577,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
if (count($sql_in))
|
||||
{
|
||||
// Flag the words
|
||||
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
|
||||
$sql = 'UPDATE ' . $this->search_wordlist_table . '
|
||||
SET word_common = 1
|
||||
WHERE ' . $this->db->sql_in_set('word_id', $sql_in);
|
||||
$this->db->sql_query($sql);
|
||||
|
@ -1575,7 +1587,7 @@ class fulltext_native extends base implements search_backend_interface
|
|||
$this->config->set('search_last_gc', time(), false);
|
||||
|
||||
// Delete the matches
|
||||
$sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
|
||||
$sql = 'DELETE FROM ' . $this->search_wordmatch_table . '
|
||||
WHERE ' . $this->db->sql_in_set('word_id', $sql_in);
|
||||
$this->db->sql_query($sql);
|
||||
}
|
||||
|
@ -1603,15 +1615,15 @@ class fulltext_native extends base implements search_backend_interface
|
|||
switch ($this->db->get_sql_layer())
|
||||
{
|
||||
case 'sqlite3':
|
||||
$sql_queries[] = 'DELETE FROM ' . SEARCH_WORDLIST_TABLE;
|
||||
$sql_queries[] = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE;
|
||||
$sql_queries[] = 'DELETE FROM ' . SEARCH_RESULTS_TABLE;
|
||||
$sql_queries[] = 'DELETE FROM ' . $this->search_wordlist_table;
|
||||
$sql_queries[] = 'DELETE FROM ' . $this->search_wordmatch_table;
|
||||
$sql_queries[] = 'DELETE FROM ' . $this->search_results_table;
|
||||
break;
|
||||
|
||||
default:
|
||||
$sql_queries[] = 'TRUNCATE TABLE ' . SEARCH_WORDLIST_TABLE;
|
||||
$sql_queries[] = 'TRUNCATE TABLE ' . SEARCH_WORDMATCH_TABLE;
|
||||
$sql_queries[] = 'TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE;
|
||||
$sql_queries[] = 'TRUNCATE TABLE ' . $this->search_wordlist_table;
|
||||
$sql_queries[] = 'TRUNCATE TABLE ' . $this->search_wordmatch_table;
|
||||
$sql_queries[] = 'TRUNCATE TABLE ' . $this->search_results_table;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1672,8 +1684,8 @@ class fulltext_native extends base implements search_backend_interface
|
|||
*/
|
||||
protected function get_stats()
|
||||
{
|
||||
$this->stats['total_words'] = $this->db->get_estimated_row_count(SEARCH_WORDLIST_TABLE);
|
||||
$this->stats['total_matches'] = $this->db->get_estimated_row_count(SEARCH_WORDMATCH_TABLE);
|
||||
$this->stats['total_words'] = $this->db->get_estimated_row_count($this->search_wordlist_table);
|
||||
$this->stats['total_matches'] = $this->db->get_estimated_row_count($this->search_wordmatch_table);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,8 +17,8 @@ use phpbb\config\config;
|
|||
use phpbb\db\driver\driver_interface;
|
||||
use phpbb\event\dispatcher_interface;
|
||||
use phpbb\language\language;
|
||||
use phpbb\search\exception\search_exception;
|
||||
use phpbb\user;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Fulltext search for PostgreSQL
|
||||
|
@ -84,19 +84,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 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
|
||||
* @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 $search_results_table
|
||||
* @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, 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 $search_results_table, string $phpbb_root_path, string $phpEx)
|
||||
{
|
||||
global $cache;
|
||||
|
||||
parent::__construct($cache, $config, $db, $user);
|
||||
parent::__construct($cache, $config, $db, $user, $search_results_table);
|
||||
$this->phpbb_dispatcher = $phpbb_dispatcher;
|
||||
$this->language = $language;
|
||||
|
||||
|
@ -871,7 +872,7 @@ class fulltext_postgres extends base implements search_backend_interface
|
|||
// Make sure we can actually use PostgreSQL with fulltext indexes
|
||||
if ($error = $this->init())
|
||||
{
|
||||
throw new RuntimeException($error);
|
||||
throw new search_exception($error);
|
||||
}
|
||||
|
||||
if (empty($this->stats))
|
||||
|
@ -917,7 +918,7 @@ class fulltext_postgres extends base implements search_backend_interface
|
|||
$this->db->sql_query($sql_query);
|
||||
}
|
||||
|
||||
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
|
||||
$this->db->sql_query('TRUNCATE TABLE ' . $this->search_results_table);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -930,7 +931,7 @@ class fulltext_postgres extends base implements search_backend_interface
|
|||
// Make sure we can actually use PostgreSQL with fulltext indexes
|
||||
if ($error = $this->init())
|
||||
{
|
||||
throw new RuntimeException($error);
|
||||
throw new search_exception($error);
|
||||
}
|
||||
|
||||
if (empty($this->stats))
|
||||
|
@ -976,7 +977,7 @@ class fulltext_postgres extends base implements search_backend_interface
|
|||
$this->db->sql_query($sql_query);
|
||||
}
|
||||
|
||||
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
|
||||
$this->db->sql_query('TRUNCATE TABLE ' . $this->search_results_table);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search\exception;
|
||||
|
||||
class action_in_progress_exception extends search_exception
|
||||
{
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search\exception;
|
||||
|
||||
class no_action_in_progress_exception extends search_exception
|
||||
{
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search\exception;
|
||||
|
||||
class no_search_backend_found_exception extends search_exception
|
||||
{
|
||||
}
|
20
phpBB/phpbb/search/exception/search_exception.php
Normal file
20
phpBB/phpbb/search/exception/search_exception.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search\exception;
|
||||
|
||||
use phpbb\exception\runtime_exception;
|
||||
|
||||
class search_exception extends runtime_exception
|
||||
{
|
||||
}
|
|
@ -14,8 +14,10 @@
|
|||
namespace phpbb\search;
|
||||
|
||||
use phpbb\config\config;
|
||||
use phpbb\di\exception\service_not_found_exception;
|
||||
use phpbb\di\service_collection;
|
||||
use phpbb\search\backend\search_backend_interface;
|
||||
use phpbb\search\exception\no_search_backend_found_exception;
|
||||
|
||||
class search_backend_factory
|
||||
{
|
||||
|
@ -46,16 +48,29 @@ class search_backend_factory
|
|||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @throws no_search_backend_found_exception
|
||||
*
|
||||
* @return search_backend_interface
|
||||
*/
|
||||
public function get(string $class): search_backend_interface
|
||||
{
|
||||
return $this->search_backends->get_by_class($class);
|
||||
try
|
||||
{
|
||||
$search = $this->search_backends->get_by_class($class);
|
||||
}
|
||||
catch (service_not_found_exception $e)
|
||||
{
|
||||
throw new no_search_backend_found_exception('SEARCH_BACKEND_NOT_FOUND', [], $e);
|
||||
}
|
||||
|
||||
return $search;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains active search backend
|
||||
*
|
||||
* @throws no_search_backend_found_exception
|
||||
*
|
||||
* @return search_backend_interface
|
||||
*/
|
||||
public function get_active(): search_backend_interface
|
||||
|
|
181
phpBB/phpbb/search/state_helper.php
Normal file
181
phpBB/phpbb/search/state_helper.php
Normal file
|
@ -0,0 +1,181 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\search;
|
||||
|
||||
use phpbb\config\config;
|
||||
use phpbb\search\exception\action_in_progress_exception;
|
||||
use phpbb\search\exception\no_action_in_progress_exception;
|
||||
use phpbb\search\exception\no_search_backend_found_exception;
|
||||
use phpbb\search\exception\search_exception;
|
||||
|
||||
class state_helper
|
||||
{
|
||||
protected const STATE_SEARCH_TYPE = 0;
|
||||
protected const STATE_ACTION = 1;
|
||||
protected const STATE_POST_COUNTER = 2;
|
||||
|
||||
/** @var config */
|
||||
protected $config;
|
||||
|
||||
/** @var search_backend_factory */
|
||||
protected $search_backend_factory;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param config $config
|
||||
* @param search_backend_factory $search_backend_factory
|
||||
*/
|
||||
public function __construct(config $config, search_backend_factory $search_backend_factory)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->search_backend_factory = $search_backend_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there is an action in progress
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_action_in_progress(): bool
|
||||
{
|
||||
return !empty($this->config['search_indexing_state']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string The class name of the search backend
|
||||
*
|
||||
* @throws no_action_in_progress_exception If there is no action in progress
|
||||
*/
|
||||
public function type(): string
|
||||
{
|
||||
$state = $this->load_state();
|
||||
|
||||
return $state[self::STATE_SEARCH_TYPE];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string The action that is being executed, can be 'create' or 'delete'
|
||||
*
|
||||
* @throws no_action_in_progress_exception If there is no action in progress
|
||||
*/
|
||||
public function action(): string
|
||||
{
|
||||
$state = $this->load_state();
|
||||
|
||||
return $state[self::STATE_ACTION];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The post counter
|
||||
*
|
||||
* @throws no_action_in_progress_exception If there is no action in progress
|
||||
*/
|
||||
public function counter(): int
|
||||
{
|
||||
$state = $this->load_state();
|
||||
|
||||
return $state[self::STATE_POST_COUNTER];
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a indexing or delete process.
|
||||
*
|
||||
* @param string $search_type
|
||||
* @param string $action
|
||||
*
|
||||
* @throws action_in_progress_exception If there is an action in progress
|
||||
* @throws no_search_backend_found_exception If search backend don't exist
|
||||
* @throws search_exception If action isn't valid
|
||||
*/
|
||||
public function init(string $search_type, string $action): void
|
||||
{
|
||||
// It's not possible to start a new process when there is one already running
|
||||
if ($this->is_action_in_progress())
|
||||
{
|
||||
throw new action_in_progress_exception();
|
||||
}
|
||||
|
||||
// Make sure the search type exists (if not, throw an exception)
|
||||
$this->search_backend_factory->get($search_type);
|
||||
|
||||
// Make sure the action is correct (just in case)
|
||||
if (!in_array($action, ['create', 'delete']))
|
||||
{
|
||||
throw new search_exception('INVALID_ACTION');
|
||||
}
|
||||
|
||||
$state = [
|
||||
self::STATE_SEARCH_TYPE => $search_type,
|
||||
self::STATE_ACTION => $action,
|
||||
self::STATE_POST_COUNTER => 0
|
||||
];
|
||||
|
||||
$this->save_state($state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the post counter
|
||||
*
|
||||
* @param int $counter
|
||||
*
|
||||
* @throws no_action_in_progress_exception If there is no action in progress
|
||||
*/
|
||||
public function update_counter(int $counter): void
|
||||
{
|
||||
$state = $this->load_state();
|
||||
|
||||
$state[self::STATE_POST_COUNTER] = $counter;
|
||||
|
||||
$this->save_state($state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the state
|
||||
*/
|
||||
public function clear_state(): void
|
||||
{
|
||||
$this->save_state();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the state from the database
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws no_action_in_progress_exception If there is no action in progress
|
||||
*/
|
||||
private function load_state(): array
|
||||
{
|
||||
// Is not possible to execute an action over state if it's empty
|
||||
if (!$this->is_action_in_progress())
|
||||
{
|
||||
throw new no_action_in_progress_exception();
|
||||
}
|
||||
|
||||
return explode(',', $this->config['search_indexing_state']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the specified state in the database
|
||||
*
|
||||
* @param array $state
|
||||
*/
|
||||
private function save_state(array $state = []): void
|
||||
{
|
||||
ksort($state);
|
||||
|
||||
$this->config->set('search_indexing_state', implode(',', $state));
|
||||
}
|
||||
}
|
|
@ -299,16 +299,9 @@ if ($keywords || $author || $author_id || $search_id || $submit)
|
|||
$search_backend_factory = $phpbb_container->get('search.backend_factory');
|
||||
$search = $search_backend_factory->get_active();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
catch (\phpbb\search\exception\no_search_backend_found_exception $e)
|
||||
{
|
||||
if (strpos($e->getMessage(), 'No service found') === 0)
|
||||
{
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
trigger_error('NO_SUCH_SEARCH_MODULE');
|
||||
}
|
||||
|
||||
// let the search module split up the keywords
|
||||
|
|
92
tests/console/searchindex/create_test.php
Normal file
92
tests/console/searchindex/create_test.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
use phpbb\console\command\searchindex\create;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
require_once __DIR__ . '/phpbb_console_searchindex_base.php';
|
||||
require_once __DIR__ . '/../../mock/search_backend_mock.php';
|
||||
|
||||
class phpbb_console_searchindex_create_test extends phpbb_console_searchindex_base
|
||||
{
|
||||
public function get_command_tester()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->add(new create(
|
||||
$this->language,
|
||||
$this->log,
|
||||
$this->post_helper,
|
||||
$this->search_backend_factory,
|
||||
$this->state_helper,
|
||||
$this->user
|
||||
));
|
||||
|
||||
$command = $application->find('searchindex:create');
|
||||
|
||||
return new CommandTester($command);
|
||||
}
|
||||
|
||||
public function test_create()
|
||||
{
|
||||
$command_tester = $this->get_command_tester();
|
||||
|
||||
$command_tester->execute([
|
||||
'search-backend' => 'search_backend_mock',
|
||||
]);
|
||||
|
||||
$this->assertEquals(Command::SUCCESS, $command_tester->getStatusCode());
|
||||
$this->assertStringContainsString('CLI_SEARCHINDEX_CREATE_SUCCESS', $command_tester->getDisplay());
|
||||
}
|
||||
|
||||
public function test_create_when_search_backend_dont_exist()
|
||||
{
|
||||
$command_tester = $this->get_command_tester();
|
||||
|
||||
$command_tester->execute([
|
||||
'search-backend' => 'missing',
|
||||
]);
|
||||
|
||||
$this->assertEquals(Command::FAILURE, $command_tester->getStatusCode());
|
||||
$this->assertStringContainsString('CLI_SEARCHINDEX_BACKEND_NOT_FOUND', $command_tester->getDisplay());
|
||||
}
|
||||
|
||||
public function test_create_when_action_in_progress()
|
||||
{
|
||||
$this->config['search_indexing_state'] = ['not', 'empty'];
|
||||
|
||||
$command_tester = $this->get_command_tester();
|
||||
|
||||
$command_tester->execute([
|
||||
'search-backend' => 'search_backend_mock',
|
||||
]);
|
||||
|
||||
$this->assertEquals(Command::FAILURE, $command_tester->getStatusCode());
|
||||
$this->assertStringContainsString('CLI_SEARCHINDEX_ACTION_IN_PROGRESS', $command_tester->getDisplay());
|
||||
|
||||
$this->config['search_indexing_state'] = [];
|
||||
}
|
||||
|
||||
public function test_create_when_search_backend_not_available()
|
||||
{
|
||||
$command_tester = $this->get_command_tester();
|
||||
|
||||
$command_tester->execute([
|
||||
'search-backend' => 'search_backend_mock_not_available',
|
||||
]);
|
||||
|
||||
$this->assertEquals(Command::FAILURE, $command_tester->getStatusCode());
|
||||
$this->assertStringContainsString('CLI_SEARCHINDEX_BACKEND_NOT_AVAILABLE', $command_tester->getDisplay());
|
||||
}
|
||||
}
|
92
tests/console/searchindex/delete_test.php
Normal file
92
tests/console/searchindex/delete_test.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
use phpbb\console\command\searchindex\delete;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
require_once __DIR__ . '/phpbb_console_searchindex_base.php';
|
||||
require_once __DIR__ . '/../../mock/search_backend_mock.php';
|
||||
|
||||
class phpbb_console_searchindex_delete_test extends phpbb_console_searchindex_base
|
||||
{
|
||||
public function get_command_tester()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->add(new delete(
|
||||
$this->language,
|
||||
$this->log,
|
||||
$this->post_helper,
|
||||
$this->search_backend_factory,
|
||||
$this->state_helper,
|
||||
$this->user
|
||||
));
|
||||
|
||||
$command = $application->find('searchindex:delete');
|
||||
|
||||
return new CommandTester($command);
|
||||
}
|
||||
|
||||
public function test_delete()
|
||||
{
|
||||
$command_tester = $this->get_command_tester();
|
||||
|
||||
$command_tester->execute([
|
||||
'search-backend' => 'search_backend_mock',
|
||||
]);
|
||||
|
||||
$this->assertEquals(Command::SUCCESS, $command_tester->getStatusCode());
|
||||
$this->assertStringContainsString('CLI_SEARCHINDEX_DELETE_SUCCESS', $command_tester->getDisplay());
|
||||
}
|
||||
|
||||
public function test_delete_when_search_backend_dont_exist()
|
||||
{
|
||||
$command_tester = $this->get_command_tester();
|
||||
|
||||
$command_tester->execute([
|
||||
'search-backend' => 'missing',
|
||||
]);
|
||||
|
||||
$this->assertEquals(Command::FAILURE, $command_tester->getStatusCode());
|
||||
$this->assertStringContainsString('CLI_SEARCHINDEX_BACKEND_NOT_FOUND', $command_tester->getDisplay());
|
||||
}
|
||||
|
||||
public function test_delete_when_action_in_progress()
|
||||
{
|
||||
$this->config['search_indexing_state'] = ['not', 'empty'];
|
||||
|
||||
$command_tester = $this->get_command_tester();
|
||||
|
||||
$command_tester->execute([
|
||||
'search-backend' => 'search_backend_mock',
|
||||
]);
|
||||
|
||||
$this->assertEquals(Command::FAILURE, $command_tester->getStatusCode());
|
||||
$this->assertStringContainsString('CLI_SEARCHINDEX_ACTION_IN_PROGRESS', $command_tester->getDisplay());
|
||||
|
||||
$this->config['search_indexing_state'] = [];
|
||||
}
|
||||
|
||||
public function test_delete_when_search_backend_not_available()
|
||||
{
|
||||
$command_tester = $this->get_command_tester();
|
||||
|
||||
$command_tester->execute([
|
||||
'search-backend' => 'search_backend_mock_not_available',
|
||||
]);
|
||||
|
||||
$this->assertEquals(Command::FAILURE, $command_tester->getStatusCode());
|
||||
$this->assertStringContainsString('CLI_SEARCHINDEX_BACKEND_NOT_AVAILABLE', $command_tester->getDisplay());
|
||||
}
|
||||
}
|
49
tests/console/searchindex/list_all_test.php
Normal file
49
tests/console/searchindex/list_all_test.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
use phpbb\console\command\searchindex\list_all;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
require_once __DIR__ . '/phpbb_console_searchindex_base.php';
|
||||
require_once __DIR__ . '/../../mock/search_backend_mock.php';
|
||||
|
||||
class phpbb_console_searchindex_list_all_test extends phpbb_console_searchindex_base
|
||||
{
|
||||
public function get_command_tester()
|
||||
{
|
||||
$application = new Application();
|
||||
$application->add(new list_all(
|
||||
$this->config,
|
||||
$this->language,
|
||||
$this->search_backend_collection,
|
||||
$this->user
|
||||
));
|
||||
|
||||
$command = $application->find('searchindex:list');
|
||||
|
||||
return new CommandTester($command);
|
||||
}
|
||||
|
||||
public function test_list()
|
||||
{
|
||||
$command_tester = $this->get_command_tester();
|
||||
|
||||
$command_tester->execute([]);
|
||||
|
||||
$this->assertEquals(Command::SUCCESS, $command_tester->getStatusCode());
|
||||
$this->assertStringContainsString('Mock search backend', $command_tester->getDisplay());
|
||||
$this->assertStringContainsString('ACTIVE', $command_tester->getDisplay());
|
||||
}
|
||||
}
|
93
tests/console/searchindex/phpbb_console_searchindex_base.php
Normal file
93
tests/console/searchindex/phpbb_console_searchindex_base.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
use phpbb\config\config;
|
||||
use phpbb\di\service_collection;
|
||||
use phpbb\language\language;
|
||||
use phpbb\log\log;
|
||||
use phpbb\posting\post_helper;
|
||||
use phpbb\search\search_backend_factory;
|
||||
use phpbb\search\state_helper;
|
||||
use phpbb\user;
|
||||
|
||||
require_once __DIR__ . '/../../mock/search_backend_mock.php';
|
||||
require_once __DIR__ . '/../../mock/search_backend_mock_not_available.php';
|
||||
|
||||
class phpbb_console_searchindex_base extends phpbb_test_case
|
||||
{
|
||||
/** @var config */
|
||||
protected $config;
|
||||
|
||||
/** @var language */
|
||||
protected $language;
|
||||
|
||||
/** @var log */
|
||||
protected $log;
|
||||
|
||||
/** @var post_helper */
|
||||
protected $post_helper;
|
||||
|
||||
/** @var user */
|
||||
protected $user;
|
||||
|
||||
/** @var search_backend_factory */
|
||||
protected $search_backend_factory;
|
||||
|
||||
/** @var state_helper */
|
||||
protected $state_helper;
|
||||
|
||||
/** @var service_collection */
|
||||
protected $search_backend_collection;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
global $phpbb_root_path, $phpEx;
|
||||
|
||||
$this->config = new \phpbb\config\config([
|
||||
'search_indexing_state' => [],
|
||||
'search_type' => 'search_backend_mock'
|
||||
]);
|
||||
|
||||
$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
|
||||
$this->language = new \phpbb\language\language($lang_loader);
|
||||
|
||||
$this->log = $this->createMock('\phpbb\log\log');
|
||||
|
||||
$this->post_helper = $this->createMock('\phpbb\posting\post_helper');
|
||||
$this->post_helper
|
||||
->method('get_max_post_id')
|
||||
->willReturn(1000);
|
||||
|
||||
$this->user = $this->createMock('\phpbb\user');
|
||||
|
||||
$phpbb_container = new phpbb_mock_container_builder();
|
||||
$this->search_backend_collection = new \phpbb\di\service_collection($phpbb_container);
|
||||
|
||||
$search_backend_mock = new search_backend_mock();
|
||||
$this->search_backend_collection->add('search_backend_mock');
|
||||
$this->search_backend_collection->add_service_class('search_backend_mock', 'search_backend_mock');
|
||||
$phpbb_container->set('search_backend_mock', $search_backend_mock);
|
||||
|
||||
$search_backend_mock_not_available = new search_backend_mock_not_available();
|
||||
$this->search_backend_collection->add('search_backend_mock_not_available');
|
||||
$this->search_backend_collection->add_service_class('search_backend_mock_not_available', 'search_backend_mock_not_available');
|
||||
$phpbb_container->set('search_backend_mock_not_available', $search_backend_mock_not_available);
|
||||
|
||||
$this->search_backend_factory = new search_backend_factory($this->config, $this->search_backend_collection);
|
||||
|
||||
$this->state_helper = new state_helper($this->config, $this->search_backend_factory);
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@ class phpbb_service_collection_test extends \phpbb_test_case
|
|||
public function test_get_by_class_many_services_exception()
|
||||
{
|
||||
$this->expectException('RuntimeException');
|
||||
$this->expectExceptionMessage('More than one service definitions found for class "bar_class" in collection.');
|
||||
$this->expectExceptionMessage('DI_MULTIPLE_SERVICE_DEFINITIONS');
|
||||
|
||||
$this->service_collection->get_by_class('bar_class');
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class phpbb_service_collection_test extends \phpbb_test_case
|
|||
public function test_get_by_class_no_service_exception()
|
||||
{
|
||||
$this->expectException('RuntimeException');
|
||||
$this->expectExceptionMessage('No service found for class "baz_class" in collection.');
|
||||
$this->expectExceptionMessage('DI_SERVICE_NOT_FOUND');
|
||||
|
||||
$this->service_collection->get_by_class('baz_class');
|
||||
}
|
||||
|
|
117
tests/mock/search_backend_mock.php
Normal file
117
tests/mock/search_backend_mock.php
Normal file
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
use phpbb\search\backend\search_backend_interface;
|
||||
|
||||
class search_backend_mock implements search_backend_interface
|
||||
{
|
||||
public $index_created = false;
|
||||
|
||||
public function get_name(): string
|
||||
{
|
||||
return 'Mock search backend';
|
||||
}
|
||||
|
||||
public function is_available(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function get_search_query(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function get_common_words(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function get_word_length()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function split_keywords(string &$keywords, string $terms): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function supports_phrase_search(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function index(string $mode, int $post_id, string &$message, string &$subject, int $poster_id, int $forum_id)
|
||||
{
|
||||
// Nothing
|
||||
}
|
||||
|
||||
public function index_remove(array $post_ids, array $author_ids, array $forum_ids): void
|
||||
{
|
||||
// Nothing
|
||||
}
|
||||
|
||||
public function tidy(): void
|
||||
{
|
||||
// Nothing
|
||||
}
|
||||
|
||||
public function create_index(int &$post_counter = 0): ?array
|
||||
{
|
||||
$this->index_created = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function delete_index(int &$post_counter = 0): ?array
|
||||
{
|
||||
$this->index_created = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function index_created(): bool
|
||||
{
|
||||
return $this->index_created;
|
||||
}
|
||||
|
||||
public function index_stats()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function get_acp_options(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function get_type(): string
|
||||
{
|
||||
return static::class;
|
||||
}
|
||||
}
|
||||
|
25
tests/mock/search_backend_mock_not_available.php
Normal file
25
tests/mock/search_backend_mock_not_available.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class search_backend_mock_not_available extends search_backend_mock
|
||||
{
|
||||
public function get_name(): string
|
||||
{
|
||||
return 'Mock unavailable search backend';
|
||||
}
|
||||
|
||||
public function is_available(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -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, $language, $user, $phpbb_root_path, $phpEx);
|
||||
$this->search = new $class($config, $this->db, $phpbb_dispatcher, $language, $user, SEARCH_RESULTS_TABLE, $phpbb_root_path, $phpEx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, $language, $user, $phpbb_root_path, $phpEx);
|
||||
$this->search = new $class($config, $this->db, $phpbb_dispatcher, $language, $user, SEARCH_RESULTS_TABLE, SEARCH_WORDLIST_TABLE, SEARCH_WORDMATCH_TABLE, $phpbb_root_path, $phpEx);
|
||||
}
|
||||
|
||||
public function keywords()
|
||||
|
|
|
@ -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, $language, $user, $phpbb_root_path, $phpEx);
|
||||
$this->search = new $class($config, $this->db, $phpbb_dispatcher, $language, $user, SEARCH_RESULTS_TABLE, $phpbb_root_path, $phpEx);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue