Merge pull request #6172 from rubencm/ticket/16737

[ticket/16737] Rewrite acp_search
This commit is contained in:
Marc Alexander 2021-04-08 21:35:03 +02:00 committed by GitHub
commit 16fb9cc05f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 497 additions and 429 deletions

View file

@ -1,170 +0,0 @@
<!-- INCLUDE overall_header.html -->
<a id="maincontent"></a>
<!-- IF S_SETTINGS -->
<h1>{L_ACP_SEARCH_SETTINGS}</h1>
<p>{L_ACP_SEARCH_SETTINGS_EXPLAIN}</p>
<form id="acp_search" method="post" action="{U_ACTION}">
<fieldset>
<legend>{L_GENERAL_SEARCH_SETTINGS}</legend>
<dl>
<dt><label for="load_search">{L_YES_SEARCH}{L_COLON}</label><br /><span>{L_YES_SEARCH_EXPLAIN}</span></dt>
<dd><label><input type="radio" class="radio" id="load_search" name="config[load_search]" value="1"<!-- IF S_YES_SEARCH --> checked="checked"<!-- ENDIF --> /> {L_YES}</label>
<label><input type="radio" class="radio" name="config[load_search]" value="0"<!-- IF not S_YES_SEARCH --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd>
</dl>
<dl>
<dt><label for="search_interval">{L_SEARCH_INTERVAL}{L_COLON}</label><br /><span>{L_SEARCH_INTERVAL_EXPLAIN}</span></dt>
<dd><input id="search_interval" type="number" min="0" max="9999" name="config[search_interval]" value="{SEARCH_INTERVAL}" /> {L_SECONDS}</dd>
</dl>
<dl>
<dt><label for="search_anonymous_interval">{L_SEARCH_GUEST_INTERVAL}{L_COLON}</label><br /><span>{L_SEARCH_GUEST_INTERVAL_EXPLAIN}</span></dt>
<dd><input id="search_anonymous_interval" type="number" min="0" max="9999" name="config[search_anonymous_interval]" value="{SEARCH_GUEST_INTERVAL}" /> {L_SECONDS}</dd>
</dl>
<dl>
<dt><label for="limit_search_load">{L_LIMIT_SEARCH_LOAD}{L_COLON}</label><br /><span>{L_LIMIT_SEARCH_LOAD_EXPLAIN}</span></dt>
<dd><input id="limit_search_load" type="text" size="4" maxlength="4" name="config[limit_search_load]" value="{LIMIT_SEARCH_LOAD}" /></dd>
</dl>
<dl>
<dt><label for="min_search_author_chars">{L_MIN_SEARCH_AUTHOR_CHARS}{L_COLON}</label><br /><span>{L_MIN_SEARCH_AUTHOR_CHARS_EXPLAIN}</span></dt>
<dd><input id="min_search_author_chars" type="number" min="0" max="9999" name="config[min_search_author_chars]" value="{MIN_SEARCH_AUTHOR_CHARS}" /></dd>
</dl>
<dl>
<dt><label for="max_num_search_keywords">{L_MAX_NUM_SEARCH_KEYWORDS}{L_COLON}</label><br /><span>{L_MAX_NUM_SEARCH_KEYWORDS_EXPLAIN}</span></dt>
<dd><input id="max_num_search_keywords" type="number" min="0" max="9999" name="config[max_num_search_keywords]" value="{MAX_NUM_SEARCH_KEYWORDS}" /></dd>
</dl>
<dl>
<dt>
<label for="default_search_return_chars">{{ lang('DEFAULT_SEARCH_RETURN_CHARS') ~ lang('COLON') }}</label>
<br><span>{{ lang('DEFAULT_SEARCH_RETURN_CHARS_EXPLAIN') }}</span>
</dt>
<dd><input id="default_search_return_chars" name="config[default_search_return_chars]" type="number" value="{{ DEFAULT_SEARCH_RETURN_CHARS }}" min="0" max="9999"></dd>
</dl>
<dl>
<dt><label for="search_store_results">{L_SEARCH_STORE_RESULTS}{L_COLON}</label><br /><span>{L_SEARCH_STORE_RESULTS_EXPLAIN}</span></dt>
<dd><input id="search_store_results" type="number" min="0" max="999999" name="config[search_store_results]" value="{SEARCH_STORE_RESULTS}" /> {L_SECONDS}</dd>
</dl>
</fieldset>
<fieldset>
<legend>{L_SEARCH_TYPE}</legend>
<dl>
<dt><label for="search_type">{L_SEARCH_TYPE}{L_COLON}</label><br /><span>{L_SEARCH_TYPE_EXPLAIN}</span></dt>
<dd><select id="search_type" name="config[search_type]" data-togglable-settings="true">{S_SEARCH_TYPES}</select></dd>
</dl>
</fieldset>
<!-- BEGIN backend -->
<fieldset id="search_{backend.IDENTIFIER}_settings">
<legend>{backend.NAME}</legend>
{backend.SETTINGS}
</fieldset>
<!-- END backend -->
<fieldset>
<legend>{L_ACP_SUBMIT_CHANGES}</legend>
<p class="submit-buttons">
<input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" />&nbsp;
<input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" />
</p>
{S_FORM_TOKEN}
</fieldset>
</form>
<!-- ELSEIF S_INDEX -->
<script>
// <![CDATA[
/**
* Popup search progress bar
*/
function popup_progress_bar(progress_type)
{
close_waitscreen = 0;
// no scrollbars
popup('{UA_PROGRESS_BAR}&amp;type=' + progress_type, 400, 240, '_index');
}
// ]]>
</script>
<h1>{L_ACP_SEARCH_INDEX}</h1>
<!-- IF S_CONTINUE_INDEXING -->
<p>{L_CONTINUE_EXPLAIN}</p>
<form id="acp_search_continue" method="post" action="{U_CONTINUE_INDEXING}">
<fieldset>
<legend>{L_ACP_SUBMIT_CHANGES}</legend>
<p class="submit-buttons">
<input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" />&nbsp;
<input class="button2" type="submit" id="cancel" name="cancel" value="{L_CANCEL}" />
</p>
{S_FORM_TOKEN}
</fieldset>
</form>
<!-- ELSE -->
<p>{L_ACP_SEARCH_INDEX_EXPLAIN}</p>
<!-- BEGIN backend -->
<!-- IF backend.S_STATS -->
<form id="acp_search_index_{backend.NAME}" method="post" action="{U_ACTION}">
<fieldset class="tabulated">
{backend.S_HIDDEN_FIELDS}
<legend>{L_INDEX_STATS}{L_COLON} {backend.L_NAME} <!-- IF backend.S_ACTIVE -->({L_ACTIVE}) <!-- ENDIF --></legend>
<table class="table1">
<caption>{backend.L_NAME} <!-- IF backend.S_ACTIVE -->({L_ACTIVE}) <!-- ENDIF --></caption>
<col class="col1" /><col class="col2" /><col class="col1" /><col class="col2" />
<thead>
<tr>
<th>{L_STATISTIC}</th>
<th>{L_VALUE}</th>
<th>{L_STATISTIC}</th>
<th>{L_VALUE}</th>
</tr>
</thead>
<tbody>
<!-- BEGIN data -->
<tr>
<td>{backend.data.STATISTIC_1}{L_COLON}</td>
<td>{backend.data.VALUE_1}</td>
<td>{backend.data.STATISTIC_2}<!-- IF backend.data.STATISTIC_2 -->{L_COLON}<!-- ENDIF --></td>
<td>{backend.data.VALUE_2}</td>
</tr>
<!-- END data -->
</tbody>
</table>
<!-- ENDIF -->
<p class="quick">
<!-- IF backend.S_INDEXED -->
<input type="hidden" name="action" value="delete" />
<input class="button2" type="submit" value="{L_DELETE_INDEX}" onclick="popup_progress_bar('delete');" />
<!-- ELSE -->
<input type="hidden" name="action" value="create" />
<input class="button2" type="submit" value="{L_CREATE_INDEX}" onclick="popup_progress_bar('create');" />
<!-- ENDIF -->
</p>
{S_FORM_TOKEN}
</fieldset>
</form>
<!-- END backend -->
<!-- ENDIF -->
<!-- ENDIF -->
<!-- INCLUDE overall_footer.html -->

View file

@ -0,0 +1,80 @@
{% include 'overall_header.html' %}
<a id="maincontent"></a>
<script>
// <![CDATA[
/**
* Popup search progress bar
*/
function popup_progress_bar(progress_type)
{
close_waitscreen = 0;
// no scrollbars
popup('{{ UA_PROGRESS_BAR }}&amp;type=' + progress_type, 400, 240, '_index');
}
// ]]>
</script>
<h1>{{ lang('ACP_SEARCH_INDEX') }}</h1>
<p>{{ lang('ACP_SEARCH_INDEX_EXPLAIN') }}</p>
{% for backend in backends %}
{% if backend.S_STATS is not empty %}
<form id="acp_search_index_{{ backend.TYPE }}" method="post" action="{{ U_ACTION }}">
<fieldset class="tabulated">
{{ backend.S_HIDDEN_FIELDS }}
<legend>{{ lang('INDEX_STATS') ~ lang('COLON') }} {{ backend.NAME }} {% if backend.S_ACTIVE %}({{ lang('ACTIVE') }}) {% endif %}</legend>
<table class="table1">
<caption>{{ backend.NAME }} {% if backend.S_ACTIVE %}({{ lang('ACTIVE') }}) {% endif %}</caption>
<col class="col1" /><col class="col2" /><col class="col1" /><col class="col2" />
<thead>
<tr>
<th>{{ lang('STATISTIC') }}</th>
<th>{{ lang('VALUE') }}</th>
<th>{{ lang('STATISTIC') }}</th>
<th>{{ lang('VALUE') }}</th>
</tr>
</thead>
<tbody>
{% for stat in backend.S_STATS | batch(2, '') %}
<tr>
{% for key, value in stat %}
{% if value is not empty %}
<td>{{ key ~ lang('COLON') }}</td>
<td>{{ value }}</td>
{% else %}
<td></td>
<td></td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<p class="quick">
{% if backend.S_INDEXED %}
<input type="hidden" name="action" value="delete" />
<input class="button2" type="submit" value="{{ lang('DELETE_INDEX') }}" onclick="popup_progress_bar('delete');" />
{% else %}
<input type="hidden" name="action" value="create" />
<input class="button2" type="submit" value="{{ lang('CREATE_INDEX') }}" onclick="popup_progress_bar('create');" />
{% endif %}
</p>
{{ S_FORM_TOKEN }}
</fieldset>
</form>
{% endfor %}
{% include 'overall_footer.html' %}

View file

@ -0,0 +1,34 @@
{% include 'overall_header.html' %}
<a id="maincontent"></a>
<script>
// <![CDATA[
/**
* Popup search progress bar
*/
function popup_progress_bar(progress_type)
{
close_waitscreen = 0;
// no scrollbars
popup('{{ UA_PROGRESS_BAR }}&amp;type=' + progress_type, 400, 240, '_index');
}
// ]]>
</script>
<h1>{{ lang('CONTINUE') }}</h1>
<p>{{ lang('CONTINUE_EXPLAIN') }}</p>
<form id="acp_search_continue" method="post" action="{{ U_ACTION }}">
<fieldset>
<legend>{{ lang('ACP_SUBMIT_CHANGES') }}</legend>
<p class="submit-buttons">
<input class="button1" type="submit" id="submit" name="submit" value="{{ lang('SUBMIT') }}" onclick="popup_progress_bar('{{ S_ACTION }}');" />&nbsp;
<input class="button2" type="submit" id="cancel" name="cancel" value="{{ lang('CANCEL') }}" />
</p>
{{ S_FORM_TOKEN }}
</fieldset>
</form>
{% include 'overall_footer.html' %}

View file

@ -0,0 +1,78 @@
{% include 'overall_header.html' %}
<a id="maincontent"></a>
<h1>{{ lang('ACP_SEARCH_SETTINGS') }}</h1>
<p>{{ lang('ACP_SEARCH_SETTINGS_EXPLAIN') }}</p>
<form id="acp_search" method="post" action="{{ U_ACTION }}">
<fieldset>
<legend>{{ lang('GENERAL_SEARCH_SETTINGS') }}</legend>
<dl>
<dt><label for="load_search">{{ lang('YES_SEARCH') ~ lang('COLON') }}</label><br /><span>{{ lang('YES_SEARCH_EXPLAIN') }}</span></dt>
<dd><label><input type="radio" class="radio" id="load_search" name="config[load_search]" value="1"{% if S_YES_SEARCH %} checked="checked"{% endif %} /> {{ lang('YES') }}</label>
<label><input type="radio" class="radio" name="config[load_search]" value="0"{% if not S_YES_SEARCH %} checked="checked"{% endif %} /> {{ lang('NO') }}</label></dd>
</dl>
<dl>
<dt><label for="search_interval">{{ lang('SEARCH_INTERVAL') ~ lang('COLON') }}</label><br /><span>{{ lang('SEARCH_INTERVAL_EXPLAIN') }}</span></dt>
<dd><input id="search_interval" type="number" min="0" max="9999" name="config[search_interval]" value="{{ SEARCH_INTERVAL }}" /> {{ lang('SECONDS') }}</dd>
</dl>
<dl>
<dt><label for="search_anonymous_interval">{{ lang('SEARCH_GUEST_INTERVAL') ~ lang('COLON') }}</label><br /><span>{{ lang('SEARCH_GUEST_INTERVAL_EXPLAIN') }}</span></dt>
<dd><input id="search_anonymous_interval" type="number" min="0" max="9999" name="config[search_anonymous_interval]" value="{{ SEARCH_GUEST_INTERVAL }}" /> {{ lang('SECONDS') }}</dd>
</dl>
<dl>
<dt><label for="limit_search_load">{{ lang('LIMIT_SEARCH_LOAD') ~ lang('COLON') }}</label><br /><span>{{ lang('LIMIT_SEARCH_LOAD_EXPLAIN') }}</span></dt>
<dd><input id="limit_search_load" type="text" size="4" maxlength="4" name="config[limit_search_load]" value="{{ LIMIT_SEARCH_LOAD }}" /></dd>
</dl>
<dl>
<dt><label for="min_search_author_chars">{{ lang('MIN_SEARCH_AUTHOR_CHARS') ~ lang('COLON') }}</label><br /><span>{{ lang('MIN_SEARCH_AUTHOR_CHARS_EXPLAIN') }}</span></dt>
<dd><input id="min_search_author_chars" type="number" min="0" max="9999" name="config[min_search_author_chars]" value="{{ MIN_SEARCH_AUTHOR_CHARS }}" /></dd>
</dl>
<dl>
<dt><label for="max_num_search_keywords">{{ lang('MAX_NUM_SEARCH_KEYWORDS') ~ lang('COLON') }}</label><br /><span>{{ lang('MAX_NUM_SEARCH_KEYWORDS_EXPLAIN') }}</span></dt>
<dd><input id="max_num_search_keywords" type="number" min="0" max="9999" name="config[max_num_search_keywords]" value="{{ MAX_NUM_SEARCH_KEYWORDS }}" /></dd>
</dl>
<dl>
<dt>
<label for="default_search_return_chars">{{ lang('DEFAULT_SEARCH_RETURN_CHARS') ~ lang('COLON') }}</label>
<br><span>{{ lang('DEFAULT_SEARCH_RETURN_CHARS_EXPLAIN') }}</span>
</dt>
<dd><input id="default_search_return_chars" name="config[default_search_return_chars]" type="number" value="{{ DEFAULT_SEARCH_RETURN_CHARS }}" min="0" max="9999"></dd>
</dl>
<dl>
<dt><label for="search_store_results">{{ lang('SEARCH_STORE_RESULTS') ~ lang('COLON') }}</label><br /><span>{{ lang('SEARCH_STORE_RESULTS_EXPLAIN') }}</span></dt>
<dd><input id="search_store_results" type="number" min="0" max="999999" name="config[search_store_results]" value="{{ SEARCH_STORE_RESULTS }}" /> {{ lang('SECONDS') }}</dd>
</dl>
</fieldset>
<fieldset>
<legend>{{ lang('SEARCH_TYPE') }}</legend>
<dl>
<dt><label for="search_type">{{ lang('SEARCH_TYPE') ~ lang('COLON') }}</label><br /><span>{{ lang('SEARCH_TYPE_EXPLAIN') }}</span></dt>
<dd><select id="search_type" name="config[search_type]" data-togglable-settings="true">{{ S_SEARCH_TYPES }}</select></dd>
</dl>
</fieldset>
{% for backend in loops.backend %}
<fieldset id="search_{{ backend.IDENTIFIER }}_settings">
<legend>{{ backend.NAME }}</legend>
{{ backend.SETTINGS }}
</fieldset>
{% endfor %}
<fieldset>
<legend>{{ lang('ACP_SUBMIT_CHANGES') }}</legend>
<p class="submit-buttons">
<input class="button1" type="submit" id="submit" name="submit" value="{{ lang('SUBMIT') }}" />&nbsp;
<input class="button2" type="reset" id="reset" name="reset" value="{{ lang('RESET') }}" />
</p>
{{ S_FORM_TOKEN }}
</fieldset>
</form>
{% include 'overall_footer.html' %}

View file

@ -14,6 +14,16 @@
/**
* @ignore
*/
use phpbb\config\config;
use phpbb\di\service_collection;
use phpbb\language\language;
use phpbb\log\log;
use phpbb\request\request;
use phpbb\search\search_backend_factory;
use phpbb\template\template;
use phpbb\user;
if (!defined('IN_PHPBB'))
{
exit;
@ -21,22 +31,69 @@ if (!defined('IN_PHPBB'))
class acp_search
{
var $u_action;
var $state;
var $search;
public $u_action;
public $tpl_name;
public $page_title;
protected const STATE_SEARCH_TYPE = 0;
protected const STATE_ACTION = 1;
protected const STATE_POST_COUNTER = 2;
function main($id, $mode)
/** @var config */
protected $config;
/** @var language */
protected $language;
/** @var log */
protected $log;
/** @var request */
protected $request;
/** @var service_collection */
protected $search_backend_collection;
/** @var search_backend_factory */
protected $search_backend_factory;
/** @var template */
protected $template;
/** @var user */
protected $user;
/** @var string */
protected $phpbb_admin_path;
/** @var string */
protected $php_ex;
public function __construct($p_master)
{
global $user;
global $config, $phpbb_container, $language, $phpbb_log, $request, $template, $user, $phpbb_admin_path, $phpEx;
$user->add_lang('acp/search');
$this->config = $config;
$this->language = $language;
$this->log = $phpbb_log;
$this->request = $request;
$this->search_backend_collection = $phpbb_container->get('search.backend_collection');
$this->search_backend_factory = $phpbb_container->get('search.backend_factory');
$this->template = $template;
$this->user = $user;
$this->phpbb_admin_path = $phpbb_admin_path;
$this->php_ex = $phpEx;
}
// For some this may be of help...
@ini_set('memory_limit', '128M');
/**
* @param string $id
* @param string $mode
* @throws Exception
* @return void
*/
public function main(string $id, string $mode): void
{
$this->language->add_lang('acp/search');
switch ($mode)
{
@ -50,21 +107,21 @@ class acp_search
}
}
function settings($id, $mode)
/**
* Settings page
*
* @param string $id
* @param string $mode
*/
public function settings(string $id, string $mode): void
{
global $user, $template, $phpbb_log, $request;
global $config, $phpbb_admin_path, $phpEx;
global $phpbb_container;
$submit = $this->request->is_set_post('submit');
$submit = $request->is_set_post('submit');
if ($submit && !check_link_hash($request->variable('hash', ''), 'acp_search'))
if ($submit && !check_link_hash($this->request->variable('hash', ''), 'acp_search'))
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
trigger_error($this->language->lang('FORM_INVALID') . adm_back_link($this->u_action), E_USER_WARNING);
}
$search_types = $phpbb_container->get('search.backend_collection');
$settings = [
'search_interval' => 'float',
'search_anonymous_interval' => 'float',
@ -76,18 +133,17 @@ class acp_search
'search_store_results' => 'integer',
];
$search = null;
$search_options = '';
foreach ($search_types as $search)
foreach ($this->search_backend_collection as $search)
{
// Only show available search backends
if ($search->is_available())
{
$name = $search->get_name();
$type = get_class($search);
$type = $search->get_type();
$selected = ($config['search_type'] == $type) ? ' selected="selected"' : '';
$selected = ($this->config['search_type'] === $type) ? ' selected="selected"' : '';
$identifier = substr($type, strrpos($type, '\\') + 1);
$search_options .= "<option value=\"$type\"$selected data-toggle-setting=\"#search_{$identifier}_settings\">$name</option>";
@ -95,11 +151,11 @@ class acp_search
if (!$submit)
{
$template->assign_block_vars('backend', array(
$this->template->assign_block_vars('backend', [
'NAME' => $name,
'SETTINGS' => $vars['tpl'],
'IDENTIFIER' => $identifier,
));
]);
}
else if (is_array($vars['config']))
{
@ -107,10 +163,9 @@ class acp_search
}
}
}
unset($search);
$cfg_array = (isset($_REQUEST['config'])) ? $request->variable('config', array('' => ''), true) : array();
$updated = $request->variable('updated', false);
$cfg_array = (isset($_REQUEST['config'])) ? $this->request->variable('config', ['' => ''], true) : [];
$updated = $this->request->variable('updated', false);
foreach ($settings as $config_name => $var_type)
{
@ -136,9 +191,9 @@ class acp_search
}
// only change config if anything was actually changed
if ($submit && ($config[$config_name] != $config_value))
if ($submit && ($this->config[$config_name] !== $config_value))
{
$config->set($config_name, $config_value);
$this->config->set($config_name, $config_value);
$updated = true;
}
}
@ -148,25 +203,24 @@ class acp_search
$extra_message = '';
if ($updated)
{
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH');
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_SEARCH');
}
if (isset($cfg_array['search_type']) && ($cfg_array['search_type'] != $config['search_type']))
if (isset($cfg_array['search_type']) && ($cfg_array['search_type'] !== $this->config['search_type']))
{
$search_backend_factory = $phpbb_container->get('search.backend_factory');
$search = $search_backend_factory->get($cfg_array['search_type']);
$search = $this->search_backend_factory->get($cfg_array['search_type']);
if (confirm_box(true))
{
// Initialize search backend, if $error is false means that everything is ok
if (!($error = $search->init()))
{
$config->set('search_type', $cfg_array['search_type']);
$this->config->set('search_type', $cfg_array['search_type']);
if (!$updated)
{
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH');
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_SEARCH');
}
$extra_message = '<br />' . $user->lang['SWITCHED_SEARCH_BACKEND'] . '<br /><a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=search&amp;mode=index') . '">&raquo; ' . $user->lang['GO_TO_SEARCH_INDEX'] . '</a>';
$extra_message = '<br>' . $this->language->lang('SWITCHED_SEARCH_BACKEND') . '<br><a href="' . append_sid($this->phpbb_admin_path . "index." . $this->php_ex, 'i=search&amp;mode=index') . '">&raquo; ' . $this->language->lang('GO_TO_SEARCH_INDEX') . '</a>';
}
else
{
@ -175,270 +229,243 @@ class acp_search
}
else
{
confirm_box(false, $user->lang['CONFIRM_SEARCH_BACKEND'], build_hidden_fields(array(
confirm_box(false, $this->language->lang('CONFIRM_SEARCH_BACKEND'), build_hidden_fields([
'i' => $id,
'mode' => $mode,
'submit' => true,
'updated' => $updated,
'config' => array('search_type' => $cfg_array['search_type']),
)));
'config' => ['search_type' => $cfg_array['search_type']],
]));
}
}
if ($updated)
{
if (method_exists($search, 'config_updated'))
{
if ($search->config_updated())
{
trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);
}
}
}
trigger_error($user->lang['CONFIG_UPDATED'] . $extra_message . adm_back_link($this->u_action));
trigger_error($this->language->lang('CONFIG_UPDATED') . $extra_message . adm_back_link($this->u_action));
}
unset($cfg_array);
$this->tpl_name = 'acp_search';
$this->tpl_name = 'acp_search_settings';
$this->page_title = 'ACP_SEARCH_SETTINGS';
$template->assign_vars([
'DEFAULT_SEARCH_RETURN_CHARS' => (int) $config['default_search_return_chars'],
'LIMIT_SEARCH_LOAD' => (float) $config['limit_search_load'],
'MIN_SEARCH_AUTHOR_CHARS' => (int) $config['min_search_author_chars'],
'SEARCH_INTERVAL' => (float) $config['search_interval'],
'SEARCH_GUEST_INTERVAL' => (float) $config['search_anonymous_interval'],
'SEARCH_STORE_RESULTS' => (int) $config['search_store_results'],
'MAX_NUM_SEARCH_KEYWORDS' => (int) $config['max_num_search_keywords'],
$this->template->assign_vars([
'DEFAULT_SEARCH_RETURN_CHARS' => (int) $this->config['default_search_return_chars'],
'LIMIT_SEARCH_LOAD' => (float) $this->config['limit_search_load'],
'MIN_SEARCH_AUTHOR_CHARS' => (int) $this->config['min_search_author_chars'],
'SEARCH_INTERVAL' => (float) $this->config['search_interval'],
'SEARCH_GUEST_INTERVAL' => (float) $this->config['search_anonymous_interval'],
'SEARCH_STORE_RESULTS' => (int) $this->config['search_store_results'],
'MAX_NUM_SEARCH_KEYWORDS' => (int) $this->config['max_num_search_keywords'],
'S_SEARCH_TYPES' => $search_options,
'S_YES_SEARCH' => (bool) $config['load_search'],
'S_SETTINGS' => true,
'S_YES_SEARCH' => (bool) $this->config['load_search'],
'U_ACTION' => $this->u_action . '&amp;hash=' . generate_link_hash('acp_search'),
]);
}
function index($id, $mode)
/**
* Execute action depending on the action and state
*
* @param string $id
* @param string $mode
* @throws Exception
*/
public function index(string $id, string $mode): void
{
global $user, $template, $phpbb_log, $request;
global $config, $phpbb_admin_path, $phpEx, $phpbb_container;
$action = $this->request->variable('action', '');
$state = !empty($this->config['search_indexing_state']) ? explode(',', $this->config['search_indexing_state']) : [];
$action = $request->variable('action', '');
$this->state = explode(',', $config['search_indexing_state']);
if ($request->is_set_post('cancel'))
{
$action = '';
$this->state = array();
$this->save_state();
}
$submit = $request->is_set_post('submit');
if (!check_link_hash($request->variable('hash', ''), 'acp_search') && in_array($action, array('create', 'delete')))
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if ($action)
if ($action && !$this->request->is_set_post('cancel'))
{
switch ($action)
{
case 'progress_bar':
$type = $request->variable('type', '');
$this->display_progress_bar($type);
break;
case 'delete':
$this->state[self::STATE_ACTION] = 'delete';
$this->display_progress_bar();
break;
case 'create':
$this->state[self::STATE_ACTION] = 'create';
case 'delete':
$this->index_action($id, $mode, $action, $state);
break;
default:
trigger_error('NO_ACTION', E_USER_ERROR);
}
if (empty($this->state[self::STATE_SEARCH_TYPE]))
{
$this->state[self::STATE_SEARCH_TYPE] = $request->variable('search_type', '');
}
$search_backend_factory = $phpbb_container->get('search.backend_factory');
$this->search = $search_backend_factory->get($this->state[self::STATE_SEARCH_TYPE]);
$name = $this->search->get_name();
$action = &$this->state[1];
$this->save_state();
switch ($action)
{
case 'delete':
try
{
$this->state[self::STATE_POST_COUNTER] = $this->state[self::STATE_POST_COUNTER] ?? 0;
if ($status = $this->search->delete_index($this->state[self::STATE_POST_COUNTER])) // Status is not null, so deleting is in progress....
{
// save the current state
$this->save_state();
$u_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=delete&hash=" . generate_link_hash('acp_search'), false);
meta_refresh(1, $u_action);
trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $status['row_count'], $status['post_counter']) . $user->lang('SEARCH_INDEX_DELETE_REDIRECT_RATE', $status['rows_per_second']));
}
}
catch (Exception $e)
{
$this->state = [];
$this->save_state();
trigger_error($e->getMessage() . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING);
}
$this->search->tidy();
$this->state = [];
$this->save_state();
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_REMOVED', false, array($name));
trigger_error($user->lang['SEARCH_INDEX_REMOVED'] . adm_back_link($this->u_action) . $this->close_popup_js());
break;
case 'create':
try
{
$this->state[self::STATE_POST_COUNTER] = $this->state[self::STATE_POST_COUNTER] ?? 0;
if ($status = $this->search->create_index($this->state[self::STATE_POST_COUNTER])) // Status is not null, so indexing is in progress....
{
// save the current state
$this->save_state();
$u_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=create&hash=" . generate_link_hash('acp_search'), false);
meta_refresh(1, $u_action);
trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $status['row_count'], $status['post_counter']) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $status['rows_per_second']));
}
}
catch (Exception $e)
{
// Error executing create_index
$this->state = [];
$this->save_state();
trigger_error($e->getMessage() . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING);
}
// Indexing have finished
$this->search->tidy();
$this->state = [];
$this->save_state();
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_CREATED', false, array($name));
trigger_error($user->lang['SEARCH_INDEX_CREATED'] . adm_back_link($this->u_action) . $this->close_popup_js());
break;
}
}
$search_types = $phpbb_container->get('search.backend_collection');
$search = null;
foreach ($search_types as $search)
else
{
$type = get_class($search);
$name = $search->get_name();
$data = array();
if (method_exists($search, 'index_stats'))
// If clicked to cancel the indexing progress (acp_search_index_inprogress form)
if ($this->request->is_set_post('cancel'))
{
$data = $search->index_stats();
$state = [];
$this->save_state($state);
}
$statistics = array();
foreach ($data as $statistic => $value)
if (!empty($state))
{
$n = count($statistics);
if ($n && count($statistics[$n - 1]) < 3)
{
$statistics[$n - 1] += array('statistic_2' => $statistic, 'value_2' => $value);
}
else
{
$statistics[] = array('statistic_1' => $statistic, 'value_1' => $value);
}
$this->index_inprogress($id, $mode, $state[self::STATE_ACTION]);
}
$template->assign_block_vars('backend', array(
'L_NAME' => $name,
'NAME' => $type,
'S_ACTIVE' => ($type == $config['search_type']) ? true : false,
'S_HIDDEN_FIELDS' => build_hidden_fields(array('search_type' => $type)),
'S_INDEXED' => (bool) $search->index_created(),
'S_STATS' => (bool) count($statistics))
);
foreach ($statistics as $statistic)
else
{
$template->assign_block_vars('backend.data', array(
'STATISTIC_1' => $statistic['statistic_1'],
'VALUE_1' => $statistic['value_1'],
'STATISTIC_2' => (isset($statistic['statistic_2'])) ? $statistic['statistic_2'] : '',
'VALUE_2' => (isset($statistic['value_2'])) ? $statistic['value_2'] : '')
);
$this->index_overview($id, $mode);
}
}
unset($search);
unset($statistics);
unset($data);
$this->tpl_name = 'acp_search';
$this->page_title = 'ACP_SEARCH_INDEX';
$template->assign_vars(array(
'S_INDEX' => true,
'U_ACTION' => $this->u_action . '&amp;hash=' . generate_link_hash('acp_search'),
'U_PROGRESS_BAR' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&amp;mode=$mode&amp;action=progress_bar"),
'UA_PROGRESS_BAR' => addslashes(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&amp;mode=$mode&amp;action=progress_bar")),
));
if (isset($this->state[self::STATE_ACTION]))
{
$template->assign_vars(array(
'S_CONTINUE_INDEXING' => $this->state[1],
'U_CONTINUE_INDEXING' => $this->u_action . '&amp;action=' . $this->state[self::STATE_ACTION] . '&amp;hash=' . generate_link_hash('acp_search'),
'L_CONTINUE' => ($this->state[self::STATE_ACTION] == 'create') ? $user->lang['CONTINUE_INDEXING'] : $user->lang['CONTINUE_DELETING_INDEX'],
'L_CONTINUE_EXPLAIN' => ($this->state[self::STATE_ACTION] == 'create') ? $user->lang['CONTINUE_INDEXING_EXPLAIN'] : $user->lang['CONTINUE_DELETING_INDEX_EXPLAIN'])
);
}
}
function display_progress_bar($type)
/**
* @param string $id
* @param string $mode
*
* @throws Exception
*/
private function index_overview(string $id, string $mode): void
{
global $template, $user;
$this->tpl_name = 'acp_search_index';
$this->page_title = 'ACP_SEARCH_INDEX';
$l_type = ($type == 'create') ? 'INDEXING_IN_PROGRESS' : 'DELETING_INDEX_IN_PROGRESS';
foreach ($this->search_backend_collection as $search)
{
$this->template->assign_block_vars('backends', [
'NAME' => $search->get_name(),
'TYPE' => $search->get_type(),
adm_page_header($user->lang[$l_type]);
'S_ACTIVE' => $search->get_type() === $this->config['search_type'],
'S_HIDDEN_FIELDS' => build_hidden_fields(['search_type' => $search->get_type()]),
'S_INDEXED' => $search->index_created(),
'S_STATS' => $search->index_stats(),
]);
}
$template->set_filenames(array(
'body' => 'progress_bar.html')
);
$this->template->assign_vars([
'U_ACTION' => $this->u_action . '&amp;hash=' . generate_link_hash('acp_search'),
'UA_PROGRESS_BAR' => addslashes($this->u_action . '&amp;action=progress_bar'),
]);
}
$template->assign_vars(array(
'L_PROGRESS' => $user->lang[$l_type],
'L_PROGRESS_EXPLAIN' => $user->lang[$l_type . '_EXPLAIN'])
);
/**
* Form to continue or cancel indexing process
*
* @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
{
$this->tpl_name = 'acp_search_index_inprogress';
$this->page_title = 'ACP_SEARCH_INDEX';
$this->template->assign_vars([
'U_ACTION' => $this->u_action . '&amp;action=' . $action . '&amp;hash=' . generate_link_hash('acp_search'),
'UA_PROGRESS_BAR' => addslashes($this->u_action . '&amp;action=progress_bar'),
'L_CONTINUE' => ($action === 'create') ? $this->language->lang('CONTINUE_INDEXING') : $this->language->lang('CONTINUE_DELETING_INDEX'),
'L_CONTINUE_EXPLAIN' => ($action === 'create') ? $this->language->lang('CONTINUE_INDEXING_EXPLAIN') : $this->language->lang('CONTINUE_DELETING_INDEX_EXPLAIN'),
'S_ACTION' => $action,
]);
}
/**
* Progress that do the indexing/index removal, updating the page continuously until is finished
*
* @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
{
// For some this may be of help...
@ini_set('memory_limit', '128M');
if (!check_link_hash($this->request->variable('hash', ''), 'acp_search'))
{
trigger_error($this->language->lang('FORM_INVALID') . adm_back_link($this->u_action), E_USER_WARNING);
}
// Entering here for the first time
if (empty($state))
{
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
];
}
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
$search = $this->search_backend_factory->get($type);
try
{
$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
$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);
$message_redirect = $this->language->lang(($action == 'create') ? 'SEARCH_INDEX_CREATE_REDIRECT' : 'SEARCH_INDEX_DELETE_REDIRECT', (int) $status['row_count'], $status['post_counter']);
$message_rate = $this->language->lang(($action == 'create') ? 'SEARCH_INDEX_CREATE_REDIRECT_RATE' : 'SEARCH_INDEX_DELETE_REDIRECT_RATE', $status['rows_per_second']);
trigger_error($message_redirect . $message_rate);
}
}
catch (Exception $e)
{
$this->save_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
$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()]);
$message = $this->language->lang(($action == 'create') ? 'SEARCH_INDEX_CREATED' : 'SEARCH_INDEX_REMOVED');
trigger_error($message . adm_back_link($this->u_action) . $this->close_popup_js());
}
/**
* Popup window
*/
private function display_progress_bar(): void
{
$type = $this->request->variable('type', '');
$l_type = ($type === 'create') ? 'INDEXING_IN_PROGRESS' : 'DELETING_INDEX_IN_PROGRESS';
adm_page_header($this->language->lang($l_type));
$this->template->set_filenames([
'body' => 'progress_bar.html'
]);
$this->template->assign_vars([
'L_PROGRESS' => $this->language->lang($l_type),
'L_PROGRESS_EXPLAIN' => $this->language->lang($l_type . '_EXPLAIN'),
]);
adm_page_footer();
}
function close_popup_js()
/**
* Javascript code for closing the waiting screen (is attached to the trigger_errors)
*
* @return string
*/
private function close_popup_js(): string
{
return "<script type=\"text/javascript\">\n" .
"// <![CDATA[\n" .
@ -447,17 +474,13 @@ class acp_search
"</script>\n";
}
function save_state($state = false)
/**
* @param array $state
*/
private function save_state(array $state = []): void
{
global $config;
ksort($state);
if ($state)
{
$this->state = $state;
}
ksort($this->state);
$config->set('search_indexing_state', implode(',', $this->state), true);
$this->config->set('search_indexing_state', implode(',', $state), true);
}
}

View file

@ -480,4 +480,12 @@ abstract class base implements search_backend_interface
return $max_post_id;
}
/**
* {@inheritdoc}
*/
public function get_type(): string
{
return static::class;
}
}

View file

@ -1022,4 +1022,12 @@ class fulltext_sphinx implements search_backend_interface
return true;
}
/**
* {@inheritdoc}
*/
public function get_type(): string
{
return static::class;
}
}

View file

@ -193,4 +193,11 @@ interface search_backend_interface
* @return array array containing template and config variables
*/
public function get_acp_options(): array;
/**
* Gets backend class
*
* @return string
*/
public function get_type(): string;
}

View file

@ -26,7 +26,7 @@ class local implements provider_interface
/**
* {@inheritdoc}
*/
public function get_adapter_class()
public function get_adapter_class(): string
{
return \phpbb\storage\adapter\local::class;
}

View file

@ -25,9 +25,9 @@ interface provider_interface
/**
* Gets adapter class
*
* @return \phpbb\storage\adapter\adapter_interface
* @return string
*/
public function get_adapter_class();
public function get_adapter_class(): string;
/**
* Gets adapter options