Merge remote-tracking branch 'upstream/develop' into feature/dic

* upstream/develop: (259 commits)
  [prep-release-3.0.11] Bumping version number for 3.0.11 final.
  [feature/php-events] Fix doc of core.viewonline_overwrite_location
  [feature/php-events] Fix doc of core.user_set_default_group
  [feature/php-events] Fix doc of core.generate_smilies_after
  [feature/php-events] Fix doc of core.delete_user_after
  [feature/php-events] Fix doc of core.delete_user_before
  [feature/php-events] Fix doc of core.update_username
  [feature/php-events] Fix doc of core.memberlist_prepare_profile_data
  [feature/php-events] Fix doc and position of viewonline_overwrite_location
  [feature/php-events] Fix doc of core.viewtopic_get_post_data
  [feature/php-events] Fix doc of core.viewtopic_cache_guest_data
  [ticket/11061] Add the --dev flag to the composer instructions in README
  [ticket/11060] Make sure pyrus can install everything on travis
  [ticket/11059] Use https for the README logo
  [feature/php-events] Fix acp_manage_forums_update_data_before and is_new_forum
  [feature/php-events] Fix core.acp_manage_forums_update_data_after vars
  [ticket/11032] fix language of error displayed
  [ticket/11052] update search backend constructor everywhere
  [ticket/11052] pass parametes to search construct while posting
  [ticket/11054] Fixed $config var description
  ...

Conflicts:
	phpBB/includes/cron/task/core/tidy_cache.php
	phpBB/includes/cron/task/core/tidy_search.php
This commit is contained in:
Igor Wiedler 2012-08-25 17:00:40 +02:00
commit ae85d43757
82 changed files with 4640 additions and 605 deletions

View file

@ -12,6 +12,7 @@ before_script:
- sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'DROP DATABASE IF EXISTS phpbb_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'create database phpbb_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS phpbb_tests;'; fi"
- pyrus set auto_discover 1
- pyrus install --force phpunit/DbUnit
- phpenv rehash
- cd phpBB

View file

@ -1,4 +1,4 @@
[![phpBB](http://www.phpbb.com/theme/images/logos/blue/160x52.png)](http://www.phpbb.com)
[![phpBB](https://www.phpbb.com/theme/images/logos/blue/160x52.png)](http://www.phpbb.com)
## ABOUT
@ -13,7 +13,7 @@ Find support and lots more on [phpBB.com](http://www.phpbb.com)! Discuss the dev
To be able to run an installation from the repo (and not from a pre-built package) you need to run the following commands to install phpBB's dependencies.
cd phpBB
php ../composer.phar install
php ../composer.phar install --dev
## CONTRIBUTE

View file

@ -2,9 +2,9 @@
<project name="phpBB" description="The phpBB forum software" default="all" basedir="../">
<!-- a few settings for the build -->
<property name="newversion" value="3.0.11-RC2" />
<property name="newversion" value="3.0.11" />
<property name="prevversion" value="3.0.10" />
<property name="olderversions" value="3.0.2, 3.0.3, 3.0.4, 3.0.5, 3.0.6, 3.0.7, 3.0.7-PL1, 3.0.8, 3.0.9, 3.0.11-RC1" />
<property name="olderversions" value="3.0.2, 3.0.3, 3.0.4, 3.0.5, 3.0.6, 3.0.7, 3.0.7-PL1, 3.0.8, 3.0.9, 3.0.11-RC1, 3.0.11-RC2" />
<!-- no configuration should be needed beyond this point -->
<property name="oldversions" value="${olderversions}, ${prevversion}" />

View file

@ -417,8 +417,19 @@ phpbb.ajaxify = function(options) {
* @param bool keep_selection Shall we keep the value selected, or shall the user be forced to repick one.
*/
phpbb.timezone_switch_date = function(keep_selection) {
$('#timezone > optgroup').css('display', 'none');
$("#timezone > optgroup[label='" + $('#tz_date').val() + "']").css('display', 'block');
if ($('#timezone_copy').length == 0) {
// We make a backup of the original dropdown, so we can remove optgroups
// instead of setting display to none, because IE and chrome will not
// hide options inside of optgroups and selects via css
$('#timezone').clone().attr('id', 'timezone_copy').css('display', 'none').attr('name', 'tz_copy').insertAfter('#timezone');
} else {
// Copy the content of our backup, so we can remove all unneeded options
$('#timezone').replaceWith($('#timezone_copy').clone().attr('id', 'timezone').css('display', 'block').attr('name', 'tz'));
}
if ($('#tz_date').val() != '') {
$('#timezone > optgroup').remove(":not([label='" + $('#tz_date').val() + "'])");
}
if ($('#tz_date').val() == $('#tz_select_date_suggest').attr('data-suggested-tz')) {
$('#tz_select_date_suggest').css('display', 'none');
@ -488,18 +499,20 @@ phpbb.timezone_preselect_select = function(force_selector) {
if ($('#tz_date').val() != option.value && !force_selector) {
// We do not select the option for the user, but notify him,
// that we would suggest a different setting.
$('#tz_select_date_suggest').css('display', 'inline');
$('#tz_select_date_suggest').attr('title', $('#tz_select_date_suggest').attr('data-l-suggestion').replace("%s", option.innerHTML));
$('#tz_select_date_suggest').attr('value', $('#tz_select_date_suggest').attr('data-l-suggestion').replace("%s", option.innerHTML.substring(0, 9)));
$('#tz_select_date_suggest').attr('data-suggested-tz', option.innerHTML);
phpbb.timezone_switch_date(true);
$('#tz_select_date_suggest').css('display', 'inline');
} else {
option.selected = true;
phpbb.timezone_switch_date(!force_selector);
$('#tz_select_date_suggest').attr('data-suggested-tz', option.innerHTML);
$('#tz_select_date_suggest').css('display', 'none');
}
break;
$('#tz_select_date_suggest').attr('title', $('#tz_select_date_suggest').attr('data-l-suggestion').replace("%s", option.innerHTML));
$('#tz_select_date_suggest').attr('value', $('#tz_select_date_suggest').attr('data-l-suggestion').replace("%s", option.innerHTML.substring(0, 9)));
$('#tz_select_date_suggest').attr('data-suggested-tz', option.innerHTML);
// Found the suggestion, there cannot be more, so return from here.
return;
}
}
}

View file

@ -135,7 +135,7 @@ $phpbb_style = $phpbb_container->get('style');
// Add own hook handler
require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
$phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
$phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('phpbb_template', 'display')));
foreach ($cache->obtain_hooks() as $hook)
{
@ -146,3 +146,18 @@ if (!$config['use_system_cron'])
{
$cron = $phpbb_container->get('cron.manager');
}
/**
* Main event which is triggered on every page
*
* You can use this event to load function files and initiate objects
*
* NOTE: At this point the global session ($user) and permissions ($auth)
* do NOT exist yet. If you need to use the user object
* (f.e. to include language files) or need to check permissions,
* please use the core.user_setup event instead!
*
* @event core.common
* @since 3.1-A1
*/
$phpbb_dispatcher->dispatch('core.common');

View file

@ -50,7 +50,10 @@ services:
arguments:
- %core.root_path%
- %core.php_ext%
- @auth
- @config
- @dbal.conn
- @user
tags:
- { name: cron.task }

View file

@ -40,7 +40,7 @@ if (!class_exists($search_type))
}
$error = false;
$search = new $search_type($error);
$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
if ($error)
{

View file

@ -75,6 +75,7 @@ Jabber Class (c) 2006 Flyspray.org, http://www.flyspray.org/
Chora (c) 2000-2006, The Horde Project. http://horde.org/chora/
Horde Project (c) 2000-2006, The Horde Project. http://horde.org/
jQuery (c) 2011, John Resig. http://jquery.com/
Sphinx Technologies Inc (c) 2001-2012 Andrew Aksyonoff, http://sphinxsearch.com/
PHP License, version 3.0:
Pear (c) 2001-2004 PHP Group, http://pear.php.net

View file

@ -0,0 +1,96 @@
source source_phpbb_{SPHINX_ID}_main
{
type = mysql #mysql or pgsql
sql_host = localhost #SQL server host sphinx connects to
sql_user = username
sql_pass = password
sql_db = db_name
sql_port = 3306 #optional, default is 3306 for mysql and 5432 for pgsql
sql_query_pre = SET NAMES 'utf8'
sql_query_pre = UPDATE phpbb_sphinx SET max_doc_id = MAX(post_id) WHERE counter_id = 1
sql_query_range = SELECT MIN(post_id), MAX(post_id) FROM phpbb_posts
sql_range_step = 5000
sql_query = SELECT \
p.post_id AS id, \
p.forum_id, \
p.topic_id, \
p.poster_id, \
CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post, \
p.post_time, \
p.post_subject, \
p.post_subject as title, \
p.post_text as data, \
t.topic_last_post_time, \
0 as deleted \
FROM phpbb_posts p, phpbb_topics t \
WHERE \
p.topic_id = t.topic_id \
AND p.post_id >= $start AND p.post_id <= $end
sql_query_post =
sql_query_post_index = UPDATE phpbb_sphinx SET max_doc_id = $maxid WHERE counter_id = 1
sql_query_info = SELECT * FROM phpbb_posts WHERE post_id = $id
sql_attr_uint = forum_id
sql_attr_uint = topic_id
sql_attr_uint = poster_id
sql_attr_bool = topic_first_post
sql_attr_bool = deleted
sql_attr_timestamp = post_time
sql_attr_timestamp = topic_last_post_time
sql_attr_str2ordinal = post_subject
}
source source_phpbb_{SPHINX_ID}_delta : source_phpbb_{SPHINX_ID}_main
{
sql_query_range =
sql_range_step =
sql_query = SELECT \
p.post_id AS id, \
p.forum_id, \
p.topic_id, \
p.poster_id, \
CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post, \
p.post_time, \
p.post_subject, \
p.post_subject as title, \
p.post_text as data, \
t.topic_last_post_time, \
0 as deleted \
FROM phpbb_posts p, phpbb_topics t \
WHERE \
p.topic_id = t.topic_id \
AND p.post_id >= ( SELECT max_doc_id FROM phpbb_sphinx WHERE counter_id=1 )
sql_query_pre =
}
index index_phpbb_{SPHINX_ID}_main
{
path = {DATA_PATH}/index_phpbb_{SPHINX_ID}_main
source = source_phpbb_{SPHINX_ID}_main
docinfo = extern
morphology = none
stopwords =
min_word_len = 2
charset_type = utf-8
charset_table = U+FF10..U+FF19->0..9, 0..9, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z, A..Z->a..z, a..z, U+0149, U+017F, U+0138, U+00DF, U+00FF, U+00C0..U+00D6->U+00E0..U+00F6, U+00E0..U+00F6, U+00D8..U+00DE->U+00F8..U+00FE, U+00F8..U+00FE, U+0100->U+0101, U+0101, U+0102->U+0103, U+0103, U+0104->U+0105, U+0105, U+0106->U+0107, U+0107, U+0108->U+0109, U+0109, U+010A->U+010B, U+010B, U+010C->U+010D, U+010D, U+010E->U+010F, U+010F, U+0110->U+0111, U+0111, U+0112->U+0113, U+0113, U+0114->U+0115, U+0115, U+0116->U+0117, U+0117, U+0118->U+0119, U+0119, U+011A->U+011B, U+011B, U+011C->U+011D, U+011D, U+011E->U+011F, U+011F, U+0130->U+0131, U+0131, U+0132->U+0133, U+0133, U+0134->U+0135, U+0135, U+0136->U+0137, U+0137, U+0139->U+013A, U+013A, U+013B->U+013C, U+013C, U+013D->U+013E, U+013E, U+013F->U+0140, U+0140, U+0141->U+0142, U+0142, U+0143->U+0144, U+0144, U+0145->U+0146, U+0146, U+0147->U+0148, U+0148, U+014A->U+014B, U+014B, U+014C->U+014D, U+014D, U+014E->U+014F, U+014F, U+0150->U+0151, U+0151, U+0152->U+0153, U+0153, U+0154->U+0155, U+0155, U+0156->U+0157, U+0157, U+0158->U+0159, U+0159, U+015A->U+015B, U+015B, U+015C->U+015D, U+015D, U+015E->U+015F, U+015F, U+0160->U+0161, U+0161, U+0162->U+0163, U+0163, U+0164->U+0165, U+0165, U+0166->U+0167, U+0167, U+0168->U+0169, U+0169, U+016A->U+016B, U+016B, U+016C->U+016D, U+016D, U+016E->U+016F, U+016F, U+0170->U+0171, U+0171, U+0172->U+0173, U+0173, U+0174->U+0175, U+0175, U+0176->U+0177, U+0177, U+0178->U+00FF, U+00FF, U+0179->U+017A, U+017A, U+017B->U+017C, U+017C, U+017D->U+017E, U+017E, U+0410..U+042F->U+0430..U+044F, U+0430..U+044F, U+4E00..U+9FFF
min_prefix_len = 0
min_infix_len = 0
}
index index_phpbb_{SPHINX_ID}_delta : index_phpbb_{SPHINX_ID}_main
{
path = {DATA_PATH}/index_phpbb_{SPHINX_ID}_delta
source = source_phpbb_{SPHINX_ID}_delta
}
indexer
{
mem_limit = 512M
}
searchd
{
compat_sphinxql_magics = 0
listen = localhost:9312
log = {DATA_PATH}/log/searchd.log
query_log = {DATA_PATH}/log/sphinx-query.log
read_timeout = 5
max_children = 30
pid_file = {DATA_PATH}/searchd.pid
max_matches = 20000
binlog_path = {DATA_PATH}
}

View file

@ -25,7 +25,7 @@ class acp_forums
function main($id, $mode)
{
global $db, $user, $auth, $template, $cache, $request;
global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher;
global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;
$user->add_lang('acp/forums');
@ -150,6 +150,17 @@ class acp_forums
'forum_password_unset' => request_var('forum_password_unset', false),
);
/**
* Request forum data and operate on it (parse texts, etc.)
*
* @event core.acp_manage_forums_request_data
* @var string action Type of the action: add|edit
* @var array forum_data Array with new forum data
* @since 3.1-A1
*/
$vars = array('action', 'forum_data');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_request_data', compact($vars)));
// On add, add empty forum_options... else do not consider it (not updating it)
if ($action == 'add')
{
@ -386,6 +397,9 @@ class acp_forums
$forum_data['forum_flags'] += (request_var('enable_quick_reply', false)) ? FORUM_FLAG_QUICK_REPLY : 0;
}
// Initialise $row, so we always have it in the event
$row = array();
// Show form to create/modify a forum
if ($action == 'edit')
{
@ -453,6 +467,24 @@ class acp_forums
}
}
/**
* Initialise data before we display the add/edit form
*
* @event core.acp_manage_forums_initialise_data
* @var string action Type of the action: add|edit
* @var bool update Do we display the form only
* or did the user press submit
* @var int forum_id When editing: the forum id,
* when creating: the parent forum id
* @var array row Array with current forum data
* empty when creating new forum
* @var array forum_data Array with new forum data
* @var string parents_list List of parent options
* @since 3.1-A1
*/
$vars = array('action', 'update', 'forum_id', 'row', 'forum_data', 'parents_list');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_initialise_data', compact($vars)));
$forum_rules_data = array(
'text' => $forum_data['forum_rules'],
'allow_bbcode' => true,
@ -582,7 +614,7 @@ class acp_forums
$errors[] = $user->lang['FORUM_PASSWORD_OLD'];
}
$template->assign_vars(array(
$template_data = array(
'S_EDIT_FORUM' => true,
'S_ERROR' => (sizeof($errors)) ? true : false,
'S_PARENT_ID' => $this->parent_id,
@ -647,7 +679,31 @@ class acp_forums
'S_ENABLE_POST_REVIEW' => ($forum_data['forum_flags'] & FORUM_FLAG_POST_REVIEW) ? true : false,
'S_ENABLE_QUICK_REPLY' => ($forum_data['forum_flags'] & FORUM_FLAG_QUICK_REPLY) ? true : false,
'S_CAN_COPY_PERMISSIONS' => ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))) ? true : false,
));
);
/**
* Modify forum template data before we display the form
*
* @event core.acp_manage_forums_display_form
* @var string action Type of the action: add|edit
* @var bool update Do we display the form only
* or did the user press submit
* @var int forum_id When editing: the forum id,
* when creating: the parent forum id
* @var array row Array with current forum data
* empty when creating new forum
* @var array forum_data Array with new forum data
* @var string parents_list List of parent options
* @var array errors Array of errors, if you add errors
* ensure to update the template variables
* S_ERROR and ERROR_MSG to display it
* @var array template_data Array with new forum data
* @since 3.1-A1
*/
$vars = array('action', 'update', 'forum_id', 'row', 'forum_data', 'parents_list', 'errors', 'template_data');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_display_form', compact($vars)));
$template->assign_vars($template_data);
return;
@ -872,10 +928,22 @@ class acp_forums
*/
function update_forum_data(&$forum_data)
{
global $db, $user, $cache, $phpbb_root_path;
global $db, $user, $cache, $phpbb_root_path, $phpbb_dispatcher;
$errors = array();
/**
* Validate the forum data before we create/update the forum
*
* @event core.acp_manage_forums_validate_data
* @var array forum_data Array with new forum data
* @var array errors Array of errors, should be strings and not
* language key.
* @since 3.1-A1
*/
$vars = array('forum_data', 'errors');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_validate_data', compact($vars)));
if ($forum_data['forum_name'] == '')
{
$errors[] = $user->lang['FORUM_NAME_EMPTY'];
@ -968,7 +1036,22 @@ class acp_forums
}
unset($forum_data_sql['forum_password_unset']);
if (!isset($forum_data_sql['forum_id']))
/**
* Remove invalid values from forum_data_sql that should not be updated
*
* @event core.acp_manage_forums_update_data_before
* @var array forum_data Array with forum data
* @var array forum_data_sql Array with data we are going to update
* If forum_data_sql[forum_id] is set, we update
* that forum, otherwise a new one is created.
* @since 3.1-A1
*/
$vars = array('forum_data', 'forum_data_sql');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_before', compact($vars)));
$is_new_forum = !isset($forum_data_sql['forum_id']);
if ($is_new_forum)
{
// no forum_id means we're creating a new forum
unset($forum_data_sql['type_action']);
@ -1239,6 +1322,22 @@ class acp_forums
add_log('admin', 'LOG_FORUM_EDIT', $forum_data['forum_name']);
}
/**
* Event after a forum was updated or created
*
* @event core.acp_manage_forums_update_data_after
* @var array forum_data Array with forum data
* @var array forum_data_sql Array with data we updated
* @var bool is_new_forum Did we create a forum or update one
* If you want to overwrite this value,
* ensure to set forum_data_sql[forum_id]
* @var array errors Array of errors, should be strings and not
* language key.
* @since 3.1-A1
*/
$vars = array('forum_data', 'forum_data_sql', 'is_new_forum', 'errors');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_after', compact($vars)));
return $errors;
}
@ -1247,7 +1346,7 @@ class acp_forums
*/
function move_forum($from_id, $to_id)
{
global $db, $user;
global $db, $user, $phpbb_dispatcher;
$to_data = $moved_ids = $errors = array();
@ -1259,10 +1358,30 @@ class acp_forums
if ($to_data['forum_type'] == FORUM_LINK)
{
$errors[] = $user->lang['PARENT_IS_LINK_FORUM'];
return $errors;
}
}
/**
* Event when we move all children of one forum to another
*
* This event may be triggered, when a forum is deleted
*
* @event core.acp_manage_forums_move_children
* @var int from_id If of the current parent forum
* @var int to_id If of the new parent forum
* @var array errors Array of errors, should be strings and not
* language key.
* @since 3.1-A1
*/
$vars = array('from_id', 'to_id', 'errors');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_children', compact($vars)));
// Return if there were errors
if (!empty($errors))
{
return $errors;
}
$moved_forums = get_forum_branch($from_id, 'children', 'descending');
$from_data = $moved_forums[0];
$diff = sizeof($moved_forums) * 2;
@ -1342,7 +1461,30 @@ class acp_forums
*/
function move_forum_content($from_id, $to_id, $sync = true)
{
global $db;
global $db, $phpbb_dispatcher;
$errors = array();
/**
* Event when we move content from one forum to another
*
* @event core.acp_manage_forums_move_children
* @var int from_id If of the current parent forum
* @var int to_id If of the new parent forum
* @var bool sync Shall we sync the "to"-forum's data
* @var array errors Array of errors, should be strings and not
* language key. If this array is not empty,
* The content will not be moved.
* @since 3.1-A1
*/
$vars = array('from_id', 'to_id', 'sync', 'errors');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_content', compact($vars)));
// Return if there were errors
if (!empty($errors))
{
return $errors;
}
$table_ary = array(LOG_TABLE, POSTS_TABLE, TOPICS_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE);

View file

@ -596,16 +596,16 @@ class acp_search
*/
function init_search($type, &$search, &$error)
{
global $phpbb_root_path, $phpEx, $user;
global $phpbb_root_path, $phpEx, $user, $auth, $config, $db;
if (!class_exists($type) || !method_exists($type, 'get_name'))
if (!class_exists($type) || !method_exists($type, 'keyword_search'))
{
$error = $user->lang['NO_SUCH_SEARCH_MODULE'];
return $error;
}
$error = false;
$search = new $type($error);
$search = new $type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
return $error;
}

View file

@ -40,7 +40,7 @@ class acp_styles
public function main($id, $mode)
{
global $db, $user, $phpbb_admin_path, $phpbb_root_path, $php_ext, $template, $request, $cache, $auth, $config;
global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config;
$this->db = $db;
$this->user = $user;
@ -50,12 +50,12 @@ class acp_styles
$this->auth = $auth;
$this->config = $config;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->php_ext = $phpEx;
$this->default_style = $config['default_style'];
$this->styles_path = $this->phpbb_root_path . $this->styles_path_absolute . '/';
$this->u_base_action = append_sid("{$phpbb_admin_path}index.$php_ext", "i={$id}");
$this->u_base_action = append_sid("{$phpbb_admin_path}index.{$this->php_ext}", "i={$id}");
$this->s_hidden_fields = array(
'mode' => $mode,
);

View file

@ -32,6 +32,7 @@ class acp_users
{
global $config, $db, $user, $auth, $template, $cache;
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads;
global $phpbb_dispatcher;
$user->add_lang(array('posting', 'ucp', 'acp/users'));
$this->tpl_name = 'acp_users';
@ -749,6 +750,19 @@ class acp_users
}
break;
default:
/**
* Run custom quicktool code
*
* @event core.acp_users_overview_run_quicktool
* @var array user_row Current user data
* @var string action Quick tool that should be run
* @since 3.1-A1
*/
$vars = array('action', 'user_row');
extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_run_quicktool', compact($vars)));
break;
}
// Handle registration info updates
@ -855,6 +869,18 @@ class acp_users
}
}
/**
* Modify user data before we update it
*
* @event core.acp_users_overview_modify_data
* @var array user_row Current user data
* @var array data Submitted user data
* @var array sql_ary User data we udpate
* @since 3.1-A1
*/
$vars = array('user_row', 'data', 'sql_ary');
extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_modify_data', compact($vars)));
if ($update_username !== false)
{
$sql_ary['username'] = $update_username;
@ -945,12 +971,6 @@ class acp_users
}
}
$s_action_options = '<option class="sep" value="">' . $user->lang['SELECT_OPTION'] . '</option>';
foreach ($quick_tool_ary as $value => $lang)
{
$s_action_options .= '<option value="' . $value . '">' . $user->lang['USER_ADMIN_' . $lang] . '</option>';
}
if ($config['load_onlinetrack'])
{
$sql = 'SELECT MAX(session_time) AS session_time, MIN(session_viewonline) AS session_viewonline
@ -965,6 +985,23 @@ class acp_users
unset($row);
}
/**
* Add additional quick tool options and overwrite user data
*
* @event core.acp_users_display_overview
* @var array user_row Array with user data
* @var array quick_tool_ary Ouick tool options
* @since 3.1-A1
*/
$vars = array('user_row', 'quick_tool_ary');
extract($phpbb_dispatcher->trigger_event('core.acp_users_display_overview', compact($vars)));
$s_action_options = '<option class="sep" value="">' . $user->lang['SELECT_OPTION'] . '</option>';
foreach ($quick_tool_ary as $value => $lang)
{
$s_action_options .= '<option value="' . $value . '">' . $user->lang['USER_ADMIN_' . $lang] . '</option>';
}
$last_visit = (!empty($user_row['session_time'])) ? $user_row['session_time'] : $user_row['user_lastvisit'];
$inactive_reason = '';

View file

@ -364,7 +364,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base
/**
* Save sql query
*/
function sql_save($query, &$query_result, $ttl)
function sql_save($query, $query_result, $ttl)
{
global $db;
@ -385,6 +385,8 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base
{
$query_result = $query_id;
}
return $query_id;
}
/**

View file

@ -75,7 +75,7 @@ interface phpbb_cache_driver_interface
/**
* Save sql query
*/
public function sql_save($query, &$query_result, $ttl);
public function sql_save($query, $query_result, $ttl);
/**
* Ceck if a given sql query exist in cache

View file

@ -280,7 +280,7 @@ class phpbb_cache_driver_memory extends phpbb_cache_driver_base
/**
* Save sql query
*/
function sql_save($query, &$query_result, $ttl)
function sql_save($query, $query_result, $ttl)
{
global $db;
@ -335,6 +335,8 @@ class phpbb_cache_driver_memory extends phpbb_cache_driver_base
$this->_write('sql_' . $hash, $this->sql_rowset[$query_id], $ttl);
$query_result = $query_id;
return $query_id;
}
/**

View file

@ -107,7 +107,7 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base
/**
* Save sql query
*/
function sql_save($query, &$query_result, $ttl)
function sql_save($query, $query_result, $ttl)
{
}

View file

@ -332,27 +332,22 @@ class phpbb_cache_service
$parsed_array = array();
}
$reparse = false;
$filename = $phpbb_root_path . 'styles/' . $style['style_path'] . '/style.cfg';
if (!file_exists($filename))
{
continue;
return $parsed_array;
}
if (!isset($parsed_array['filetime']) || (($config['load_tplcompile'] && @filemtime($filename) > $parsed_array['filetime'])))
{
$reparse = true;
}
// Re-parse cfg file
if ($reparse)
{
// Re-parse cfg file
$parsed_array = parse_cfg_file($filename);
$parsed_array['filetime'] = @filemtime($filename);
$this->driver->put('_cfg_' . $style['style_path'], $parsed_array);
}
return $parsed_array;
}

View file

@ -260,6 +260,7 @@ define('SESSIONS_TABLE', $table_prefix . 'sessions');
define('SESSIONS_KEYS_TABLE', $table_prefix . 'sessions_keys');
define('SITELIST_TABLE', $table_prefix . 'sitelist');
define('SMILIES_TABLE', $table_prefix . 'smilies');
define('SPHINX_TABLE', $table_prefix . 'sphinx');
define('STYLES_TABLE', $table_prefix . 'styles');
define('STYLES_TEMPLATE_TABLE', $table_prefix . 'styles_template');
define('STYLES_TEMPLATE_DATA_TABLE',$table_prefix . 'styles_template_data');

View file

@ -51,7 +51,7 @@ class phpbb_cron_task_core_tidy_cache extends phpbb_cron_task_base
*/
public function is_runnable()
{
return method_exists($this->cache, 'tidy');
return true;
}
/**

View file

@ -26,13 +26,19 @@ class phpbb_cron_task_core_tidy_search extends phpbb_cron_task_base
{
protected $phpbb_root_path;
protected $php_ext;
protected $auth;
protected $config;
protected $db;
protected $user;
public function __construct($phpbb_root_path, $php_ext, phpbb_config $config)
public function __construct($phpbb_root_path, $php_ext, phpbb_auth $auth, phpbb_config $config, dbal $db, phpbb_user $user)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->auth = $auth;
$this->config = $config;
$this->db = $db;
$this->user = $user;
}
/**
@ -52,7 +58,7 @@ class phpbb_cron_task_core_tidy_search extends phpbb_cron_task_base
// We do some additional checks in the module to ensure it can actually be utilised
$error = false;
$search = new $search_type($error);
$search = new $search_type($error, $this->phpbb_root_path, $this->php_ext, $this->auth, $this->config, $this->db, $this->user);
if (!$error)
{

View file

@ -20,7 +20,6 @@ if (!defined('IN_PHPBB'))
* Currently not supported is returning SQL for creating tables.
*
* @package dbal
* @note currently not used within phpBB3, but may be utilized later.
*/
class phpbb_db_tools
{

View file

@ -206,7 +206,7 @@ class dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
@ -256,7 +256,7 @@ class dbal
$this->sql_rowseek($rownum, $query_id);
}
if (!is_object($query_id) && isset($cache->sql_rowset[$query_id]))
if (!is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_fetchfield($query_id, $field);
}

View file

@ -156,7 +156,7 @@ class dbal_firebird extends dbal
}
$this->last_query_text = $query;
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
@ -269,10 +269,10 @@ class dbal_firebird extends dbal
}
}
if ($cache_ttl && method_exists($cache, 'sql_save'))
if ($cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$cache->sql_save($query, $this->query_result, $cache_ttl);
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{
@ -332,7 +332,7 @@ class dbal_firebird extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
@ -398,7 +398,7 @@ class dbal_firebird extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}

View file

@ -144,7 +144,7 @@ class dbal_mssql extends dbal
$this->sql_report('start', $query);
}
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
@ -159,10 +159,10 @@ class dbal_mssql extends dbal
$this->sql_report('stop', $query);
}
if ($cache_ttl && method_exists($cache, 'sql_save'))
if ($cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$cache->sql_save($query, $this->query_result, $cache_ttl);
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{
@ -234,7 +234,7 @@ class dbal_mssql extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
@ -271,7 +271,7 @@ class dbal_mssql extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
@ -310,7 +310,7 @@ class dbal_mssql extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}

View file

@ -163,7 +163,7 @@ class dbal_mssql_odbc extends dbal
}
$this->last_query_text = $query;
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
@ -178,10 +178,10 @@ class dbal_mssql_odbc extends dbal
$this->sql_report('stop', $query);
}
if ($cache_ttl && method_exists($cache, 'sql_save'))
if ($cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$cache->sql_save($query, $this->query_result, $cache_ttl);
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{
@ -254,7 +254,7 @@ class dbal_mssql_odbc extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
@ -295,7 +295,7 @@ class dbal_mssql_odbc extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}

View file

@ -318,7 +318,7 @@ class dbal_mssqlnative extends dbal
}
$this->last_query_text = $query;
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
@ -335,10 +335,10 @@ class dbal_mssqlnative extends dbal
$this->sql_report('stop', $query);
}
if ($cache_ttl && method_exists($cache, 'sql_save'))
if ($cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$cache->sql_save($query, $this->query_result, $cache_ttl);
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{
@ -418,7 +418,7 @@ class dbal_mssqlnative extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
@ -478,7 +478,7 @@ class dbal_mssqlnative extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}

View file

@ -172,7 +172,7 @@ class dbal_mysql extends dbal
$this->sql_report('start', $query);
}
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
@ -187,10 +187,10 @@ class dbal_mysql extends dbal
$this->sql_report('stop', $query);
}
if ($cache_ttl && method_exists($cache, 'sql_save'))
if ($cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$cache->sql_save($query, $this->query_result, $cache_ttl);
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{
@ -249,7 +249,7 @@ class dbal_mysql extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
@ -270,7 +270,7 @@ class dbal_mysql extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
@ -298,7 +298,7 @@ class dbal_mysql extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}

View file

@ -179,7 +179,7 @@ class dbal_mysqli extends dbal
$this->sql_report('start', $query);
}
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
@ -194,9 +194,9 @@ class dbal_mysqli extends dbal
$this->sql_report('stop', $query);
}
if ($cache_ttl && method_exists($cache, 'sql_save'))
if ($cache_ttl)
{
$cache->sql_save($query, $this->query_result, $cache_ttl);
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl);
}
}
else if (defined('DEBUG_EXTRA'))
@ -251,7 +251,7 @@ class dbal_mysqli extends dbal
$query_id = $this->query_result;
}
if (!is_object($query_id) && isset($cache->sql_rowset[$query_id]))
if (!is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
@ -278,7 +278,7 @@ class dbal_mysqli extends dbal
$query_id = $this->query_result;
}
if (!is_object($query_id) && isset($cache->sql_rowset[$query_id]))
if (!is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
@ -306,7 +306,7 @@ class dbal_mysqli extends dbal
$query_id = $this->query_result;
}
if (!is_object($query_id) && isset($cache->sql_rowset[$query_id]))
if (!is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}

View file

@ -242,7 +242,7 @@ class dbal_oracle extends dbal
}
$this->last_query_text = $query;
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
@ -418,10 +418,10 @@ class dbal_oracle extends dbal
$this->sql_report('stop', $query);
}
if ($cache_ttl && method_exists($cache, 'sql_save'))
if ($cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$cache->sql_save($query, $this->query_result, $cache_ttl);
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{
@ -473,7 +473,7 @@ class dbal_oracle extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
@ -525,7 +525,7 @@ class dbal_oracle extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
@ -594,7 +594,7 @@ class dbal_oracle extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}

View file

@ -200,7 +200,7 @@ class dbal_postgres extends dbal
}
$this->last_query_text = $query;
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
@ -215,10 +215,10 @@ class dbal_postgres extends dbal
$this->sql_report('stop', $query);
}
if ($cache_ttl && method_exists($cache, 'sql_save'))
if ($cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$cache->sql_save($query, $this->query_result, $cache_ttl);
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{
@ -285,7 +285,7 @@ class dbal_postgres extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
@ -306,7 +306,7 @@ class dbal_postgres extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
@ -355,7 +355,7 @@ class dbal_postgres extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}

View file

@ -117,7 +117,7 @@ class dbal_sqlite extends dbal
$this->sql_report('start', $query);
}
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
@ -132,10 +132,10 @@ class dbal_sqlite extends dbal
$this->sql_report('stop', $query);
}
if ($cache_ttl && method_exists($cache, 'sql_save'))
if ($cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$cache->sql_save($query, $this->query_result, $cache_ttl);
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{
@ -193,7 +193,7 @@ class dbal_sqlite extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
@ -214,7 +214,7 @@ class dbal_sqlite extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
@ -242,7 +242,7 @@ class dbal_sqlite extends dbal
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
if ($cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}

View file

@ -23,37 +23,44 @@ if (!defined('IN_PHPBB'))
abstract class phpbb_extension_controller implements phpbb_extension_controller_interface
{
/**
* @var phpbb_request Request class object
* Request class object
* @var phpbb_request
*/
protected $request;
/**
* @var dbal DBAL class object
* DBAL class object
* @var dbal
*/
protected $db;
/**
* @var user User class object
* User class object
* @var phpbb_user
*/
protected $user;
/**
* @var phpbb_template Template class object
* Template class object
* @var phpbb_template
*/
protected $template;
/**
* @var array Config array
* Config object
* @var phpbb_config
*/
protected $config;
/**
* @var string PHP Extension
* PHP Extension
* @var string
*/
protected $php_ext;
/**
* @var string Relative path to board root
* Relative path to board root
* @var string
*/
protected $phpbb_root_path;
@ -64,14 +71,14 @@ abstract class phpbb_extension_controller implements phpbb_extension_controller_
public function __construct()
{
global $request, $db, $user, $template, $config;
global $php_ext, $phpbb_root_path;
global $phpEx, $phpbb_root_path;
$this->request = $request;
$this->db = $db;
$this->user = $user;
$this->template = $template;
$this->config = $config;
$this->php_ext = $php_ext;
$this->php_ext = $phpEx;
$this->phpbb_root_path = $phpbb_root_path;
}
}

View file

@ -4753,6 +4753,31 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
define('HEADER_INC', true);
// A listener can set this variable to `true` when it overrides this function
$page_header_override = false;
/**
* Execute code and/or overwrite page_header()
*
* @event core.page_header
* @var string page_title Page title
* @var bool display_online_list Do we display online users list
* @var string item Restrict online users to a certain
* session item, e.g. forum for
* session_forum_id
* @var int item_id Restrict online users to item id
* @var bool page_header_override Shall we return instead of running
* the rest of page_header()
* @since 3.1-A1
*/
$vars = array('page_title', 'display_online_list', 'item_id', 'item', 'page_header_override');
extract($phpbb_dispatcher->trigger_event('core.page_header', compact($vars)));
if ($page_header_override)
{
return;
}
// gzip_compression
if ($config['gzip_compress'])
{
@ -5033,9 +5058,6 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'A_COOKIE_SETTINGS' => addslashes('; path=' . $config['cookie_path'] . ((!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain']) . ((!$config['cookie_secure']) ? '' : '; secure')),
));
$vars = array('page_title', 'display_online_list', 'item_id', 'item');
extract($phpbb_dispatcher->trigger_event('core.page_header', compact($vars)));
// application/xhtml+xml not used because of IE
header('Content-type: text/html; charset=UTF-8');
@ -5058,7 +5080,27 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
function page_footer($run_cron = true)
{
global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx;
global $request;
global $request, $phpbb_dispatcher;
// A listener can set this variable to `true` when it overrides this function
$page_footer_override = false;
/**
* Execute code and/or overwrite page_footer()
*
* @event core.page_footer
* @var bool run_cron Shall we run cron tasks
* @var bool page_footer_override Shall we return instead of running
* the rest of page_footer()
* @since 3.1-A1
*/
$vars = array('run_cron', 'page_footer_override');
extract($phpbb_dispatcher->trigger_event('core.page_footer', compact($vars)));
if ($page_footer_override)
{
return;
}
// Output page creation time
if (defined('DEBUG'))
@ -5143,6 +5185,15 @@ function page_footer($run_cron = true)
function garbage_collection()
{
global $cache, $db;
global $phpbb_dispatcher;
/**
* Unload some objects, to free some memory, before we finish our task
*
* @event core.garbage_collection
* @since 3.1-A1
*/
$phpbb_dispatcher->dispatch('core.garbage_collection');
// Unload cache, must be done before the DB connection if closed
if (!empty($cache))

View file

@ -22,6 +22,7 @@ function adm_page_header($page_title)
{
global $config, $db, $user, $template;
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $SID, $_SID;
global $phpbb_dispatcher;
if (defined('HEADER_INC'))
{
@ -30,6 +31,26 @@ function adm_page_header($page_title)
define('HEADER_INC', true);
// A listener can set this variable to `true` when it overrides this function
$adm_page_header_override = false;
/**
* Execute code and/or overwrite adm_page_header()
*
* @event core.adm_page_header
* @var string page_title Page title
* @var bool adm_page_header_override Shall we return instead of
* running the rest of adm_page_header()
* @since 3.1-A1
*/
$vars = array('page_title', 'adm_page_header_override');
extract($phpbb_dispatcher->trigger_event('core.adm_page_header', compact($vars)));
if ($adm_page_header_override)
{
return;
}
// gzip_compression
if ($config['gzip_compress'])
{
@ -96,7 +117,27 @@ function adm_page_footer($copyright_html = true)
{
global $db, $config, $template, $user, $auth, $cache;
global $starttime, $phpbb_root_path, $phpbb_admin_path, $phpEx;
global $request;
global $request, $phpbb_dispatcher;
// A listener can set this variable to `true` when it overrides this function
$adm_page_footer_override = false;
/**
* Execute code and/or overwrite adm_page_footer()
*
* @event core.adm_page_footer
* @var bool copyright_html Shall we display the copyright?
* @var bool adm_page_footer_override Shall we return instead of
* running the rest of adm_page_footer()
* @since 3.1-A1
*/
$vars = array('copyright_html', 'adm_page_footer_override');
extract($phpbb_dispatcher->trigger_event('core.adm_page_footer', compact($vars)));
if ($adm_page_footer_override)
{
return;
}
// Output page creation time
if (defined('DEBUG'))
@ -193,7 +234,7 @@ function h_radio($name, $input_ary, $input_default = false, $id = false, $key =
*/
function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
{
global $user, $module;
global $user, $module, $phpbb_dispatcher;
$tpl = '';
$name = 'config[' . $config_key . ']';
@ -305,6 +346,24 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$tpl .= $vars['append'];
}
/**
* Overwrite the html code we display for the config value
*
* @event core.build_config_template
* @var array tpl_type Config type array:
* 0 => data type
* 1 [optional] => string: size, int: minimum
* 2 [optional] => string: max. length, int: maximum
* @var string key Should be used for the id attribute in html
* @var array new Array with the config values we display
* @var string name Should be used for the name attribute
* @var array vars Array with the options for the config
* @var string tpl The resulting html code we display
* @since 3.1-A1
*/
$vars = array('tpl_type', 'key', 'new', 'name', 'vars', 'tpl');
extract($phpbb_dispatcher->trigger_event('core.build_config_template', compact($vars)));
return $tpl;
}
@ -314,7 +373,8 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
*/
function validate_config_vars($config_vars, &$cfg_array, &$error)
{
global $phpbb_root_path, $user;
global $phpbb_root_path, $user, $phpbb_dispatcher;
$type = 0;
$min = 1;
$max = 2;
@ -489,6 +549,24 @@ function validate_config_vars($config_vars, &$cfg_array, &$error)
}
break;
default:
/**
* Validate a config value
*
* @event core.validate_config_variable
* @var array cfg_array Array with config values
* @var string config_name Name of the config we validate
* @var array config_definition Array with the options for
* this config
* @var array error Array of errors, the errors should
* be strings only, language keys are
* not replaced afterwards
* @since 3.1-A1
*/
$vars = array('cfg_array', 'config_name', 'config_definition', 'error');
extract($phpbb_dispatcher->trigger_event('core.validate_config_variable', compact($vars)));
break;
}
}

View file

@ -723,7 +723,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s
*/
function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = true, $post_count_sync = true, $call_delete_topics = true)
{
global $db, $config, $phpbb_root_path, $phpEx;
global $db, $config, $phpbb_root_path, $phpEx, $auth, $user;
if ($where_type === 'range')
{
@ -855,7 +855,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =
}
$error = false;
$search = new $search_type($error);
$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
if ($error)
{

View file

@ -23,6 +23,11 @@ class compress
{
var $fp = 0;
/**
* @var array
*/
protected $filelist = array();
/**
* Add file to archive
*/
@ -122,6 +127,36 @@ class compress
return true;
}
/**
* Checks if a file by that name as already been added and, if it has,
* returns a new, unique name.
*
* @param string $name The filename
* @return string A unique filename
*/
protected function unique_filename($name)
{
if (isset($this->filelist[$name]))
{
$start = $name;
$ext = '';
$this->filelist[$name]++;
// Separate the extension off the end of the filename to preserve it
$pos = strrpos($name, '.');
if ($pos !== false)
{
$start = substr($name, 0, $pos);
$ext = substr($name, $pos);
}
return $start . '_' . $this->filelist[$name] . $ext;
}
$this->filelist[$name] = 0;
return $name;
}
/**
* Return available methods
*/
@ -361,6 +396,7 @@ class compress_zip extends compress
function data($name, $data, $is_dir = false, $stat)
{
$name = str_replace('\\', '/', $name);
$name = $this->unique_filename($name);
$hexdtime = pack('V', $this->unix_to_dos_time($stat[9]));
@ -633,6 +669,7 @@ class compress_tar extends compress
*/
function data($name, $data, $is_dir = false, $stat)
{
$name = $this->unique_filename($name);
$this->wrote = true;
$fzwrite = ($this->isbz && function_exists('bzwrite')) ? 'bzwrite' : (($this->isgz && @extension_loaded('zlib')) ? 'gzwrite' : 'fwrite');

View file

@ -22,7 +22,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
{
global $db, $auth, $user, $template;
global $phpbb_root_path, $phpEx, $config;
global $request;
global $request, $phpbb_dispatcher;
$forum_rows = $subforums = $forum_ids = $forum_ids_moderator = $forum_moderators = $active_forum_ary = array();
$parent_id = $visible_forums = 0;
@ -119,6 +119,16 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
'ORDER_BY' => 'f.left_id',
);
/**
* Event to modify the SQL query before the forum data is queried
*
* @event core.display_forums_modify_sql
* @var array sql_ary The SQL array to get the data of the forums
* @since 3.1-A1
*/
$vars = array('sql_ary');
extract($phpbb_dispatcher->trigger_event('core.display_forums_modify_sql', compact($vars)));
$sql = $db->sql_build_query('SELECT', $sql_ary);
$result = $db->sql_query($sql);
@ -127,6 +137,19 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
while ($row = $db->sql_fetchrow($result))
{
/**
* Event to modify the data set of a forum
*
* This event is triggered once per forum
*
* @event core.display_forums_modify_row
* @var int branch_root_id Last top-level forum
* @var array row The data of the forum
* @since 3.1-A1
*/
$vars = array('branch_root_id', 'row');
extract($phpbb_dispatcher->trigger_event('core.display_forums_modify_row', compact($vars)));
$forum_id = $row['forum_id'];
// Mark forums read?
@ -260,6 +283,22 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$forum_rows[$parent_id]['forum_id_last_post'] = $forum_id;
}
}
/**
* Event to modify the forum rows data set
*
* This event is triggered once per forum
*
* @event core.display_forums_modify_forum_rows
* @var array forum_rows Data array of all forums we display
* @var array subforums Data array of all subforums we display
* @var int branch_root_id Current top-level forum
* @var int parent_id Current parent forum
* @var array row The data of the forum
* @since 3.1-A1
*/
$vars = array('forum_rows', 'subforums', 'branch_root_id', 'parent_id', 'row');
extract($phpbb_dispatcher->trigger_event('core.display_forums_modify_forum_rows', compact($vars)));
}
$db->sql_freeresult($result);
@ -443,7 +482,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
}
}
$template->assign_block_vars('forumrow', array(
$forum_row = array(
'S_IS_CAT' => false,
'S_NO_CAT' => $catless && !$last_catless,
'S_IS_LINK' => ($row['forum_type'] == FORUM_LINK) ? true : false,
@ -480,9 +519,24 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
'U_UNAPPROVED_TOPICS' => ($row['forum_id_unapproved_topics']) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=unapproved_topics&amp;f=' . $row['forum_id_unapproved_topics']) : '',
'U_VIEWFORUM' => $u_viewforum,
'U_LAST_POSTER' => get_username_string('profile', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']),
'U_LAST_POST' => $last_post_url)
'U_LAST_POST' => $last_post_url,
);
/**
* Modify the template data block of the forum
*
* This event is triggered once per forum
*
* @event core.display_forums_modify_template_vars
* @var array forum_row Template data of the forum
* @var array row The data of the forum
* @since 3.1-A1
*/
$vars = array('forum_row', 'row');
extract($phpbb_dispatcher->trigger_event('core.display_forums_modify_template_vars', compact($vars)));
$template->assign_block_vars('forumrow', $forum_row);
// Assign subforums loop for style authors
foreach ($subforums_list as $subforum)
{
@ -830,7 +884,7 @@ function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$fold
*/
function display_custom_bbcodes()
{
global $db, $template, $user;
global $db, $template, $user, $phpbb_dispatcher;
// Start counting from 22 for the bbcode ids (every bbcode takes two ids - opening/closing)
$num_predefined_bbcodes = 22;
@ -850,17 +904,40 @@ function display_custom_bbcodes()
$row['bbcode_helpline'] = $user->lang[strtoupper($row['bbcode_helpline'])];
}
$template->assign_block_vars('custom_tags', array(
$custom_tags = array(
'BBCODE_NAME' => "'[{$row['bbcode_tag']}]', '[/" . str_replace('=', '', $row['bbcode_tag']) . "]'",
'BBCODE_ID' => $num_predefined_bbcodes + ($i * 2),
'BBCODE_TAG' => $row['bbcode_tag'],
'BBCODE_HELPLINE' => $row['bbcode_helpline'],
'A_BBCODE_HELPLINE' => str_replace(array('&amp;', '&quot;', "'", '&lt;', '&gt;'), array('&', '"', "\'", '<', '>'), $row['bbcode_helpline']),
));
);
/**
* Modify the template data block of a bbcode
*
* This event is triggered once per bbcode
*
* @event core.display_custom_bbcodes_modify_row
* @var array custom_tags Template data of the bbcode
* @var array row The data of the bbcode
* @since 3.1-A1
*/
$vars = array('custom_tags', 'row');
extract($phpbb_dispatcher->trigger_event('core.display_custom_bbcodes_modify_row', compact($vars)));
$template->assign_block_vars('custom_tags', $custom_tags);
$i++;
}
$db->sql_freeresult($result);
/**
* Display custom bbcodes
*
* @event core.display_custom_bbcodes
* @since 3.1-A1
*/
$phpbb_dispatcher->dispatch('core.display_custom_bbcodes');
}
/**
@ -1248,6 +1325,31 @@ function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank
function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $alt = 'USER_AVATAR', $ignore_config = false)
{
global $user, $config, $phpbb_root_path, $phpEx;
global $phpbb_dispatcher;
$overwrite_avatar = '';
/**
* Overwrite users avatar
*
* @event core.display_custom_bbcodes_modify_row
* @var string avatar Users assigned avatar name
* @var int avatar_type Type of avatar
* @var string avatar_width Width of users avatar
* @var string avatar_height Height of users avatar
* @var string alt Language string for alt tag within image
* Can be a language key or text
* @var bool ignore_config Ignores config and force displaying avatar
* @var string overwrite_avatar If set, this string will be the avatar
* @since 3.1-A1
*/
$vars = array('avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'alt', 'ignore_config', 'overwrite_avatar');
extract($phpbb_dispatcher->trigger_event('core.user_get_avatar', compact($vars)));
if ($overwrite_avatar)
{
return $overwrite_avatar;
}
if (empty($avatar) || !$avatar_type || (!$config['allow_avatar'] && !$ignore_config))
{

View file

@ -20,7 +20,7 @@ if (!defined('IN_PHPBB'))
*/
function generate_smilies($mode, $forum_id)
{
global $db, $user, $config, $template;
global $db, $user, $config, $template, $phpbb_dispatcher;
global $phpEx, $phpbb_root_path;
$start = request_var('start', 0);
@ -123,6 +123,18 @@ function generate_smilies($mode, $forum_id)
}
}
/**
* This event is called after the smilies are populated
*
* @event core.generate_smilies_after
* @var string mode Mode of the smilies: window|inline
* @var int forum_id The forum ID we are currently in
* @var bool display_link Shall we display the "more smilies" link?
* @since 3.1-A1
*/
$vars = array('mode', 'forum_id', 'display_link');
extract($phpbb_dispatcher->trigger_event('core.generate_smilies_after', compact($vars)));
if ($mode == 'inline' && $display_link)
{
$template->assign_vars(array(
@ -2370,7 +2382,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
$error = false;
$search = new $search_type($error);
$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
if ($error)
{

View file

@ -112,7 +112,7 @@ function update_last_username()
*/
function user_update_name($old_name, $new_name)
{
global $config, $db, $cache;
global $config, $db, $cache, $phpbb_dispatcher;
$update_ary = array(
FORUMS_TABLE => array('forum_last_poster_name'),
@ -137,6 +137,17 @@ function user_update_name($old_name, $new_name)
set_config('newest_username', $new_name, true);
}
/**
* Update a username when it is changed
*
* @event core.update_username
* @var string old_name The old username that is replaced
* @var string new_name The new username
* @since 3.1-A1
*/
$vars = array('old_name', 'new_name');
extract($phpbb_dispatcher->trigger_event('core.update_username', compact($vars)));
// Because some tables/caches use username-specific data we need to purge this here.
$cache->destroy('sql', MODERATOR_CACHE_TABLE);
}
@ -331,7 +342,7 @@ function user_add($user_row, $cp_data = false)
*/
function user_delete($mode, $user_id, $post_username = false)
{
global $cache, $config, $db, $user, $auth;
global $cache, $config, $db, $user, $auth, $phpbb_dispatcher;
global $phpbb_root_path, $phpEx;
$sql = 'SELECT *
@ -346,6 +357,18 @@ function user_delete($mode, $user_id, $post_username = false)
return false;
}
/**
* Event before a user is deleted
*
* @event core.delete_user_before
* @var string mode Mode of deletion (retain/delete posts)
* @var int user_id ID of the deleted user
* @var mixed post_username Guest username that is being used or false
* @since 3.1-A1
*/
$vars = array('mode', 'user_id', 'post_username');
extract($phpbb_dispatcher->trigger_event('core.delete_user_before', compact($vars)));
// Before we begin, we will remove the reports the user issued.
$sql = 'SELECT r.post_id, p.topic_id
FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p
@ -535,6 +558,18 @@ function user_delete($mode, $user_id, $post_username = false)
$db->sql_transaction('commit');
/**
* Event after a user is deleted
*
* @event core.delete_user_after
* @var string mode Mode of deletion (retain/delete posts)
* @var int user_id ID of the deleted user
* @var mixed post_username Guest username that is being used or false
* @since 3.1-A1
*/
$vars = array('mode', 'user_id', 'post_username');
extract($phpbb_dispatcher->trigger_event('core.delete_user_after', compact($vars)));
// Reset newest user info if appropriate
if ($config['newest_user_id'] == $user_id)
{
@ -2759,7 +2794,7 @@ function avatar_remove_db($avatar_name)
*/
function group_delete($group_id, $group_name = false)
{
global $db, $phpbb_root_path, $phpEx;
global $db, $phpbb_root_path, $phpEx, $phpbb_dispatcher;
if (!$group_name)
{
@ -2818,6 +2853,17 @@ function group_delete($group_id, $group_name = false)
WHERE group_id = $group_id";
$db->sql_query($sql);
/**
* Event after a group is deleted
*
* @event core.delete_group_after
* @var int group_id ID of the deleted group
* @var string group_name Name of the deleted group
* @since 3.1-A1
*/
$vars = array('group_id', 'group_name');
extract($phpbb_dispatcher->trigger_event('core.delete_group_after', compact($vars)));
// Re-cache moderators
if (!function_exists('cache_moderators'))
{
@ -2940,7 +2986,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false,
*/
function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false)
{
global $db, $auth, $config;
global $db, $auth, $config, $phpbb_dispatcher;
if ($config['coppa_enable'])
{
@ -3039,6 +3085,19 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false,
}
unset($special_group_data);
/**
* Event before users are removed from a group
*
* @event core.group_delete_user_before
* @var int group_id ID of the group from which users are deleted
* @var string group_name Name of the group
* @var array user_id_ary IDs of the users which are removed
* @var array username_ary names of the users which are removed
* @since 3.1-A1
*/
$vars = array('group_id', 'group_name', 'user_id_ary', 'username_ary');
extract($phpbb_dispatcher->trigger_event('core.group_delete_user_before', compact($vars)));
$sql = 'DELETE FROM ' . USER_GROUP_TABLE . "
WHERE group_id = $group_id
AND " . $db->sql_in_set('user_id', $user_id_ary);
@ -3356,7 +3415,7 @@ function group_validate_groupname($group_id, $group_name)
*/
function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false)
{
global $cache, $db;
global $cache, $db, $phpbb_dispatcher;
if (empty($user_id_ary))
{
@ -3452,6 +3511,20 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
}
}
/**
* Event when the default group is set for an array of users
*
* @event core.user_set_default_group
* @var int group_id ID of the group
* @var array user_id_ary IDs of the users
* @var array group_attributes Group attributes which were changed
* @var array update_listing Update the list of moderators and foes
* @var array sql_ary User attributes which were changed
* @since 3.1-A1
*/
$vars = array('group_id', 'user_id_ary', 'group_attributes', 'update_listing', 'sql_ary');
extract($phpbb_dispatcher->trigger_event('core.user_set_default_group', compact($vars)));
if ($update_listing)
{
group_update_listings($group_id);

View file

@ -22,7 +22,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
{
global $template, $db, $user, $auth, $cache, $module;
global $phpEx, $phpbb_root_path, $config;
global $request;
global $request, $phpbb_dispatcher;
$user->add_lang(array('viewtopic', 'viewforum'));
@ -288,6 +288,17 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
));
}
/**
* Modify the topic data before it is assigned to the template in MCP
*
* @event core.mcp_view_forum_modify_topicrow
* @var array row Array with topic data
* @var array topic_row Template array with topic data
* @since 3.1-A1
*/
$vars = array('row', 'topic_row');
extract($phpbb_dispatcher->trigger_event('core.mcp_view_forum_modify_topicrow', compact($vars)));
$template->assign_block_vars('topicrow', $topic_row);
}
unset($topic_rows);

View file

@ -915,7 +915,7 @@ function mcp_fork_topic($topic_ids)
}
$error = false;
$search = new $search_type($error);
$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
$search_mode = 'post';
if ($error)

View file

@ -393,7 +393,7 @@ function mcp_post_details($id, $mode, $action)
*/
function change_poster(&$post_info, $userdata)
{
global $auth, $db, $config, $phpbb_root_path, $phpEx;
global $auth, $db, $config, $phpbb_root_path, $phpEx, $user;
if (empty($userdata) || $userdata['user_id'] == $post_info['user_id'])
{
@ -470,7 +470,7 @@ function change_poster(&$post_info, $userdata)
{
// We do some additional checks in the module to ensure it can actually be utilised
$error = false;
$search = new $search_type($error);
$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
if (!$error && method_exists($search, 'destroy_cache'))
{

View file

@ -22,17 +22,28 @@ if (!defined('IN_PHPBB'))
*/
class phpbb_search_fulltext_mysql extends phpbb_search_base
{
var $stats = array();
var $word_length = array();
var $split_words = array();
var $search_query;
var $common_words = array();
protected $stats = array();
protected $split_words = array();
protected $config;
protected $db;
protected $user;
public $word_length = array();
public $search_query;
public $common_words = array();
public function __construct(&$error)
/**
* Constructor
* Creates a new phpbb_search_fulltext_mysql, which is used as a search backend.
*
* @param string|bool $error Any error that occurs is passed on through this reference variable otherwise false
*/
public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user)
{
global $config;
$this->config = $config;
$this->db = $db;
$this->user = $user;
$this->word_length = array('min' => $config['fulltext_mysql_min_word_len'], 'max' => $config['fulltext_mysql_max_word_len']);
$this->word_length = array('min' => $this->config['fulltext_mysql_min_word_len'], 'max' => $this->config['fulltext_mysql_max_word_len']);
$error = false;
}
@ -49,19 +60,19 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
/**
* Checks for correct MySQL version and stores min/max word length in the config
*
* @return string|bool Language key of the error/incompatiblity occured
*/
function init()
public function init()
{
global $db, $user;
if ($db->sql_layer != 'mysql4' && $db->sql_layer != 'mysqli')
if ($this->db->sql_layer != 'mysql4' && $this->db->sql_layer != 'mysqli')
{
return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE'];
return $this->user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE'];
}
$result = $db->sql_query('SHOW TABLE STATUS LIKE \'' . POSTS_TABLE . '\'');
$info = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
$result = $this->db->sql_query('SHOW TABLE STATUS LIKE \'' . POSTS_TABLE . '\'');
$info = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
$engine = '';
if (isset($info['Engine']))
@ -75,19 +86,19 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
if ($engine != 'MyISAM')
{
return $user->lang['FULLTEXT_MYSQL_NOT_MYISAM'];
return $this->user->lang['FULLTEXT_MYSQL_NOT_MYISAM'];
}
$sql = 'SHOW VARIABLES
LIKE \'ft\_%\'';
$result = $db->sql_query($sql);
$result = $this->db->sql_query($sql);
$mysql_info = array();
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$mysql_info[$row['Variable_name']] = $row['Value'];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
set_config('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']);
set_config('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']);
@ -103,10 +114,8 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
* @param string $terms is either 'all' or 'any'
* @return bool false if no valid keywords were found and otherwise true
*/
function split_keywords(&$keywords, $terms)
public function split_keywords(&$keywords, $terms)
{
global $config, $user;
if ($terms == 'all')
{
$match = array('#\sand\s#iu', '#\sor\s#iu', '#\snot\s#iu', '#(^|\s)\+#', '#(^|\s)-#', '#(^|\s)\|#');
@ -125,9 +134,9 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
$this->split_words = $matches[1];
// We limit the number of allowed keywords to minimize load on the database
if ($config['max_num_search_keywords'] && sizeof($this->split_words) > $config['max_num_search_keywords'])
if ($this->config['max_num_search_keywords'] && sizeof($this->split_words) > $this->config['max_num_search_keywords'])
{
trigger_error($user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $config['max_num_search_keywords'], sizeof($this->split_words)));
trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $this->config['max_num_search_keywords'], sizeof($this->split_words)));
}
// to allow phrase search, we need to concatenate quoted words
@ -169,7 +178,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
// check word length
$clean_len = utf8_strlen(str_replace('*', '', $clean_word));
if (($clean_len < $config['fulltext_mysql_min_word_len']) || ($clean_len > $config['fulltext_mysql_max_word_len']))
if (($clean_len < $this->config['fulltext_mysql_min_word_len']) || ($clean_len > $this->config['fulltext_mysql_max_word_len']))
{
$this->common_words[] = $word;
unset($this->split_words[$i]);
@ -221,11 +230,10 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
/**
* Turns text into an array of words
* @param string $text contains post text/subject
*/
function split_message($text)
public function split_message($text)
{
global $config;
// Split words
$text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text)));
$matches = array();
@ -237,7 +245,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
for ($i = 0, $n = sizeof($text); $i < $n; $i++)
{
$text[$i] = trim($text[$i]);
if (utf8_strlen($text[$i]) < $config['fulltext_mysql_min_word_len'] || utf8_strlen($text[$i]) > $config['fulltext_mysql_max_word_len'])
if (utf8_strlen($text[$i]) < $this->config['fulltext_mysql_min_word_len'] || utf8_strlen($text[$i]) > $this->config['fulltext_mysql_max_word_len'])
{
unset($text[$i]);
}
@ -265,13 +273,9 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
* @return boolean|int total number of results
*
* @access public
*/
function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
// No keywords? No posts.
if (!$this->search_query)
{
@ -360,7 +364,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
}
else
{
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
}
$sql_select = (!$result_count) ? 'SQL_CALC_FOUND_ROWS ' : '';
@ -370,11 +374,11 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
if (sizeof($author_ary) && $author_name)
{
// first one matches post of registered users, second one guests and deleted users
$sql_author = ' AND (' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
$sql_author = ' AND (' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
}
else if (sizeof($author_ary))
{
$sql_author = ' AND ' . $db->sql_in_set('p.poster_id', $author_ary);
$sql_author = ' AND ' . $this->db->sql_in_set('p.poster_id', $author_ary);
}
else
{
@ -384,7 +388,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
$sql_where_options = $sql_sort_join;
$sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : '';
$sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : '';
$sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_where_options .= $m_approve_fid_sql;
$sql_where_options .= $sql_author;
$sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
@ -392,16 +396,16 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
$sql = "SELECT $sql_select
FROM $sql_from$sql_sort_table" . POSTS_TABLE . " p
WHERE MATCH ($sql_match) AGAINST ('" . $db->sql_escape(htmlspecialchars_decode($this->search_query)) . "' IN BOOLEAN MODE)
WHERE MATCH ($sql_match) AGAINST ('" . $this->db->sql_escape(htmlspecialchars_decode($this->search_query)) . "' IN BOOLEAN MODE)
$sql_where_options
ORDER BY $sql_sort";
$result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
$result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start);
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$id_ary[] = (int) $row[$field];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
$id_ary = array_unique($id_ary);
@ -414,9 +418,9 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
if (!$result_count)
{
$sql = 'SELECT FOUND_ROWS() as result_count';
$result = $db->sql_query($sql);
$result_count = (int) $db->sql_fetchfield('result_count');
$db->sql_freeresult($result);
$result = $this->db->sql_query($sql);
$result_count = (int) $this->db->sql_fetchfield('result_count');
$this->db->sql_freeresult($result);
if (!$result_count)
{
@ -449,13 +453,9 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
* @return boolean|int total number of results
*
* @access public
*/
function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
// No author? No posts.
if (!sizeof($author_ary))
{
@ -491,13 +491,13 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
if ($author_name)
{
// first one matches post of registered users, second one guests and deleted users
$sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
$sql_author = '(' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
}
else
{
$sql_author = $db->sql_in_set('p.poster_id', $author_ary);
$sql_author = $this->db->sql_in_set('p.poster_id', $author_ary);
}
$sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
$sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : '';
@ -533,7 +533,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
}
else
{
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
}
// If the cache was completely empty count the results
@ -572,21 +572,21 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
}
// Only read one block of posts from the db and then cache it
$result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
$result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start);
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$id_ary[] = (int) $row[$field];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
// retrieve the total result count if needed
if (!$result_count)
{
$sql = 'SELECT FOUND_ROWS() as result_count';
$result = $db->sql_query($sql);
$result_count = (int) $db->sql_fetchfield('result_count');
$db->sql_freeresult($result);
$result = $this->db->sql_query($sql);
$result_count = (int) $this->db->sql_fetchfield('result_count');
$this->db->sql_freeresult($result);
if (!$result_count)
{
@ -607,12 +607,15 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
/**
* Destroys cached search results, that contained one of the new words in a post so the results won't be outdated.
*
* @param string $mode contains the post mode: edit, post, reply, quote ...
* @param string $mode contains the post mode: edit, post, reply, quote ...
* @param int $post_id contains the post id of the post to index
* @param string $message contains the post text of the post
* @param string $subject contains the subject of the post to index
* @param int $poster_id contains the user id of the poster
* @param int $forum_id contains the forum id of parent forum of the post
*/
function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
{
global $db;
// Split old and new post/subject to obtain array of words
$split_text = $this->split_message($message);
$split_title = ($subject) ? $this->split_message($subject) : array();
@ -631,7 +634,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
/**
* Destroy cached results, that might be outdated after deleting a post
*/
function index_remove($post_ids, $author_ids, $forum_ids)
public function index_remove($post_ids, $author_ids, $forum_ids)
{
$this->destroy_cache(array(), array_unique($author_ids));
}
@ -639,10 +642,8 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
/**
* Destroy old cache entries
*/
function tidy()
public function tidy()
{
global $db, $config;
// destroy too old cached search results
$this->destroy_cache(array());
@ -651,11 +652,11 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
/**
* Create fulltext index
*
* @return string|bool error string is returned incase of errors otherwise false
*/
function create_index($acp_module, $u_action)
public function create_index($acp_module, $u_action)
{
global $db;
// Make sure we can actually use MySQL with fulltext indexes
if ($error = $this->init())
{
@ -671,7 +672,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
if (!isset($this->stats['post_subject']))
{
if ($db->sql_layer == 'mysqli' || version_compare($db->sql_server_info(true), '4.1.3', '>='))
if ($this->db->sql_layer == 'mysqli' || version_compare($this->db->sql_server_info(true), '4.1.3', '>='))
{
$alter[] = 'MODIFY post_subject varchar(255) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL';
}
@ -684,7 +685,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
if (!isset($this->stats['post_text']))
{
if ($db->sql_layer == 'mysqli' || version_compare($db->sql_server_info(true), '4.1.3', '>='))
if ($this->db->sql_layer == 'mysqli' || version_compare($this->db->sql_server_info(true), '4.1.3', '>='))
{
$alter[] = 'MODIFY post_text mediumtext COLLATE utf8_unicode_ci NOT NULL';
}
@ -702,21 +703,21 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
if (sizeof($alter))
{
$db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter));
$this->db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter));
}
$db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
return false;
}
/**
* Drop fulltext index
*
* @return string|bool error string is returned incase of errors otherwise false
*/
function delete_index($acp_module, $u_action)
public function delete_index($acp_module, $u_action)
{
global $db;
// Make sure we can actually use MySQL with fulltext indexes
if ($error = $this->init())
{
@ -747,10 +748,10 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
if (sizeof($alter))
{
$db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter));
$this->db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter));
}
$db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
return false;
}
@ -758,7 +759,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
/**
* Returns true if both FULLTEXT indexes exist
*/
function index_created()
public function index_created()
{
if (empty($this->stats))
{
@ -771,25 +772,24 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
/**
* Returns an associative array containing information about the indexes
*/
function index_stats()
public function index_stats()
{
global $user;
if (empty($this->stats))
{
$this->get_stats();
}
return array(
$user->lang['FULLTEXT_MYSQL_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0,
$this->user->lang['FULLTEXT_MYSQL_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0,
);
}
function get_stats()
/**
* Computes the stats and store them in the $this->stats associative array
*/
protected function get_stats()
{
global $db;
if (strpos($db->sql_layer, 'mysql') === false)
if (strpos($this->db->sql_layer, 'mysql') === false)
{
$this->stats = array();
return;
@ -797,9 +797,9 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
$sql = 'SHOW INDEX
FROM ' . POSTS_TABLE;
$result = $db->sql_query($sql);
$result = $this->db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
// deal with older MySQL versions which didn't use Index_type
$index_type = (isset($row['Index_type'])) ? $row['Index_type'] : $row['Comment'];
@ -820,26 +820,26 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
}
}
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
$this->stats['total_posts'] = empty($this->stats) ? 0 : $db->get_estimated_row_count(POSTS_TABLE);
$this->stats['total_posts'] = empty($this->stats) ? 0 : $this->db->get_estimated_row_count(POSTS_TABLE);
}
/**
* Display a note, that UTF-8 support is not available with certain versions of PHP
*
* @return associative array containing template and config variables
*/
function acp()
public function acp()
{
global $user, $config;
$tpl = '
<dl>
<dt><label>' . $user->lang['MIN_SEARCH_CHARS'] . ':</label><br /><span>' . $user->lang['FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
<dd>' . $config['fulltext_mysql_min_word_len'] . '</dd>
<dt><label>' . $this->user->lang['MIN_SEARCH_CHARS'] . ':</label><br /><span>' . $this->user->lang['FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
<dd>' . $this->config['fulltext_mysql_min_word_len'] . '</dd>
</dl>
<dl>
<dt><label>' . $user->lang['MAX_SEARCH_CHARS'] . ':</label><br /><span>' . $user->lang['FULLTEXT_MYSQL_MAX_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
<dd>' . $config['fulltext_mysql_max_word_len'] . '</dd>
<dt><label>' . $this->user->lang['MAX_SEARCH_CHARS'] . ':</label><br /><span>' . $this->user->lang['FULLTEXT_MYSQL_MAX_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
<dd>' . $this->config['fulltext_mysql_max_word_len'] . '</dd>
</dl>
';

View file

@ -22,32 +22,42 @@ if (!defined('IN_PHPBB'))
*/
class phpbb_search_fulltext_native extends phpbb_search_base
{
var $stats = array();
var $word_length = array();
var $search_query;
var $common_words = array();
protected $stats = array();
public $word_length = array();
public $search_query;
public $common_words = array();
var $must_contain_ids = array();
var $must_not_contain_ids = array();
var $must_exclude_one_ids = array();
protected $must_contain_ids = array();
protected $must_not_contain_ids = array();
protected $must_exclude_one_ids = array();
protected $phpbb_root_path;
protected $php_ext;
protected $config;
protected $db;
protected $user;
/**
* Initialises the fulltext_native search backend with min/max word length and makes sure the UTF-8 normalizer is loaded.
*
* @param boolean|string &$error is passed by reference and should either be set to false on success or an error message on failure.
*/
public function __construct(&$error)
public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user)
{
global $phpbb_root_path, $phpEx, $config;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $phpEx;
$this->config = $config;
$this->db = $db;
$this->user = $user;
$this->word_length = array('min' => $config['fulltext_native_min_chars'], 'max' => $config['fulltext_native_max_chars']);
$this->word_length = array('min' => $this->config['fulltext_native_min_chars'], 'max' => $this->config['fulltext_native_max_chars']);
/**
* Load the UTF tools
*/
if (!class_exists('utf_normalizer'))
{
include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
include($this->phpbb_root_path . 'includes/utf/utf_normalizer.' . $this->php_ext);
}
$error = false;
@ -77,13 +87,9 @@ class phpbb_search_fulltext_native extends phpbb_search_base
* @param string $terms is either 'all' (use search query as entered, default words to 'must be contained in post')
* or 'any' (find all posts containing at least one of the given words)
* @return boolean false if no valid keywords were found and otherwise true
*
* @access public
*/
function split_keywords($keywords, $terms)
public function split_keywords($keywords, $terms)
{
global $db, $user, $config;
$tokens = '+-|()*';
$keywords = trim($this->cleanup($keywords, $tokens));
@ -182,9 +188,9 @@ class phpbb_search_fulltext_native extends phpbb_search_base
$num_keywords = sizeof(explode(' ', $keywords));
// We limit the number of allowed keywords to minimize load on the database
if ($config['max_num_search_keywords'] && $num_keywords > $config['max_num_search_keywords'])
if ($this->config['max_num_search_keywords'] && $num_keywords > $this->config['max_num_search_keywords'])
{
trigger_error($user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $config['max_num_search_keywords'], $num_keywords));
trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $this->config['max_num_search_keywords'], $num_keywords));
}
// $keywords input format: each word separated by a space, words in a bracket are not separated
@ -214,12 +220,12 @@ class phpbb_search_fulltext_native extends phpbb_search_base
{
$sql = 'SELECT word_id, word_text, word_common
FROM ' . SEARCH_WORDLIST_TABLE . '
WHERE ' . $db->sql_in_set('word_text', $exact_words) . '
WHERE ' . $this->db->sql_in_set('word_text', $exact_words) . '
ORDER BY word_count ASC';
$result = $db->sql_query($sql);
$result = $this->db->sql_query($sql);
// store an array of words and ids, remove common words
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
if ($row['word_common'])
{
@ -230,7 +236,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
$words[$row['word_text']] = (int) $row['word_id'];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
}
unset($exact_words);
@ -301,7 +307,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
{
if (strpos($word_part, '*') !== false)
{
$id_words[] = '\'' . $db->sql_escape(str_replace('*', '%', $word_part)) . '\'';
$id_words[] = '\'' . $this->db->sql_escape(str_replace('*', '%', $word_part)) . '\'';
$non_common_words[] = $word_part;
}
else if (isset($words[$word_part]))
@ -346,7 +352,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
$len = utf8_strlen(str_replace('*', '', $word));
if ($len >= $this->word_length['min'] && $len <= $this->word_length['max'])
{
$this->{$mode . '_ids'}[] = '\'' . $db->sql_escape(str_replace('*', '%', $word)) . '\'';
$this->{$mode . '_ids'}[] = '\'' . $this->db->sql_escape(str_replace('*', '%', $word)) . '\'';
}
else
{
@ -366,7 +372,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
$len = utf8_strlen($word);
if ($len >= $this->word_length['min'] && $len <= $this->word_length['max'])
{
trigger_error(sprintf($user->lang['WORD_IN_NO_POST'], $word));
trigger_error(sprintf($this->user->lang['WORD_IN_NO_POST'], $word));
}
else
{
@ -416,13 +422,9 @@ class phpbb_search_fulltext_native extends phpbb_search_base
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
* @return boolean|int total number of results
*
* @access public
*/
function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
// No keywords? No posts.
if (empty($this->search_query))
{
@ -537,7 +539,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
}
}
$sql_where[] = $db->sql_in_set("m$m_num.word_id", $word_ids);
$sql_where[] = $this->db->sql_in_set("m$m_num.word_id", $word_ids);
unset($word_id_sql);
unset($word_ids);
@ -591,7 +593,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
{
$sql_array['LEFT_JOIN'][] = array(
'FROM' => array(SEARCH_WORDMATCH_TABLE => 'm' . $m_num),
'ON' => $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"
'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"
);
$sql_where[] = "m$m_num.word_id IS NULL";
@ -632,7 +634,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
}
else if ($m_approve_fid_ary !== array(-1))
{
$sql_where[] = '(p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
$sql_where[] = '(p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
}
if ($topic_id)
@ -645,18 +647,18 @@ class phpbb_search_fulltext_native extends phpbb_search_base
if ($author_name)
{
// first one matches post of registered users, second one guests and deleted users
$sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
$sql_author = '(' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
}
else
{
$sql_author = $db->sql_in_set('p.poster_id', $author_ary);
$sql_author = $this->db->sql_in_set('p.poster_id', $author_ary);
}
$sql_where[] = $sql_author;
}
if (sizeof($ex_fid_ary))
{
$sql_where[] = $db->sql_in_set('p.forum_id', $ex_fid_ary, true);
$sql_where[] = $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true);
}
if ($sort_days)
@ -681,7 +683,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
);
}
switch ($db->sql_layer)
switch ($this->db->sql_layer)
{
case 'mysql4':
case 'mysqli':
@ -695,17 +697,17 @@ class phpbb_search_fulltext_native extends phpbb_search_base
case 'sqlite':
$sql_array_count['SELECT'] = ($type == 'posts') ? 'DISTINCT p.post_id' : 'DISTINCT p.topic_id';
$sql = 'SELECT COUNT(' . (($type == 'posts') ? 'post_id' : 'topic_id') . ') as total_results
FROM (' . $db->sql_build_query('SELECT', $sql_array_count) . ')';
FROM (' . $this->db->sql_build_query('SELECT', $sql_array_count) . ')';
// no break
default:
$sql_array_count['SELECT'] = ($type == 'posts') ? 'COUNT(DISTINCT p.post_id) AS total_results' : 'COUNT(DISTINCT p.topic_id) AS total_results';
$sql = (!$sql) ? $db->sql_build_query('SELECT', $sql_array_count) : $sql;
$sql = (!$sql) ? $this->db->sql_build_query('SELECT', $sql_array_count) : $sql;
$result = $db->sql_query($sql);
$total_results = (int) $db->sql_fetchfield('total_results');
$db->sql_freeresult($result);
$result = $this->db->sql_query($sql);
$total_results = (int) $this->db->sql_fetchfield('total_results');
$this->db->sql_freeresult($result);
if (!$total_results)
{
@ -751,14 +753,14 @@ class phpbb_search_fulltext_native extends phpbb_search_base
unset($sql_where, $sql_sort, $group_by);
$sql = $db->sql_build_query('SELECT', $sql_array);
$result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start);
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$id_ary[] = (int) $row[(($type == 'posts') ? 'post_id' : 'topic_id')];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
if (!sizeof($id_ary))
{
@ -772,16 +774,16 @@ class phpbb_search_fulltext_native extends phpbb_search_base
$sql_array_copy = $sql_array;
$sql_array_copy['SELECT'] = 'SQL_CALC_FOUND_ROWS p.post_id ';
$sql = $db->sql_build_query('SELECT', $sql_array_copy);
$sql = $this->db->sql_build_query('SELECT', $sql_array_copy);
unset($sql_array_copy);
$db->sql_query($sql);
$db->sql_freeresult($result);
$this->db->sql_query($sql);
$this->db->sql_freeresult($result);
$sql = 'SELECT FOUND_ROWS() as total_results';
$result = $db->sql_query($sql);
$total_results = (int) $db->sql_fetchfield('total_results');
$db->sql_freeresult($result);
$result = $this->db->sql_query($sql);
$total_results = (int) $this->db->sql_fetchfield('total_results');
$this->db->sql_freeresult($result);
if (!$total_results)
{
@ -814,13 +816,9 @@ class phpbb_search_fulltext_native extends phpbb_search_base
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
* @return boolean|int total number of results
*
* @access public
*/
function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
// No author? No posts.
if (!sizeof($author_ary))
{
@ -856,13 +854,13 @@ class phpbb_search_fulltext_native extends phpbb_search_base
if ($author_name)
{
// first one matches post of registered users, second one guests and deleted users
$sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
$sql_author = '(' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
}
else
{
$sql_author = $db->sql_in_set('p.poster_id', $author_ary);
$sql_author = $this->db->sql_in_set('p.poster_id', $author_ary);
}
$sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
$sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : '';
@ -898,7 +896,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
}
else
{
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
}
$select = ($type == 'posts') ? 'p.post_id' : 't.topic_id';
@ -907,7 +905,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
// If the cache was completely empty count the results
if (!$total_results)
{
switch ($db->sql_layer)
switch ($this->db->sql_layer)
{
case 'mysql4':
case 'mysqli':
@ -929,7 +927,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
}
else
{
if ($db->sql_layer == 'sqlite')
if ($this->db->sql_layer == 'sqlite')
{
$sql = 'SELECT COUNT(topic_id) as total_results
FROM (SELECT DISTINCT t.topic_id';
@ -946,12 +944,12 @@ class phpbb_search_fulltext_native extends phpbb_search_base
$m_approve_fid_sql
$sql_fora
AND t.topic_id = p.topic_id
$sql_time" . (($db->sql_layer == 'sqlite') ? ')' : '');
$sql_time" . (($this->db->sql_layer == 'sqlite') ? ')' : '');
}
$result = $db->sql_query($sql);
$result = $this->db->sql_query($sql);
$total_results = (int) $db->sql_fetchfield('total_results');
$db->sql_freeresult($result);
$total_results = (int) $this->db->sql_fetchfield('total_results');
$this->db->sql_freeresult($result);
if (!$total_results)
{
@ -994,26 +992,26 @@ class phpbb_search_fulltext_native extends phpbb_search_base
}
// Only read one block of posts from the db and then cache it
$result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
$result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start);
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$id_ary[] = (int) $row[$field];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
if (!$total_results && $is_mysql)
{
// Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it.
$sql = str_replace('SELECT ' . $select, 'SELECT DISTINCT SQL_CALC_FOUND_ROWS p.post_id', $sql);
$db->sql_query($sql);
$db->sql_freeresult($result);
$this->db->sql_query($sql);
$this->db->sql_freeresult($result);
$sql = 'SELECT FOUND_ROWS() as total_results';
$result = $db->sql_query($sql);
$total_results = (int) $db->sql_fetchfield('total_results');
$db->sql_freeresult($result);
$result = $this->db->sql_query($sql);
$total_results = (int) $this->db->sql_fetchfield('total_results');
$this->db->sql_freeresult($result);
if (!$total_results)
{
@ -1041,13 +1039,9 @@ class phpbb_search_fulltext_native extends phpbb_search_base
*
* @param string $text Text to split, encoded in UTF-8
* @return array Array of UTF-8 words
*
* @access private
*/
function split_message($text)
public function split_message($text)
{
global $phpbb_root_path, $phpEx, $user;
$match = $words = array();
/**
@ -1120,14 +1114,10 @@ class phpbb_search_fulltext_native extends phpbb_search_base
* @param string &$subject New or updated post subject
* @param int $poster_id Post author's user id
* @param int $forum_id The id of the forum in which the post is located
*
* @access public
*/
function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
{
global $config, $db, $user;
if (!$config['fulltext_native_load_upd'])
if (!$this->config['fulltext_native_load_upd'])
{
/**
* The search indexer is disabled, return
@ -1153,14 +1143,14 @@ class phpbb_search_fulltext_native extends phpbb_search_base
FROM ' . SEARCH_WORDLIST_TABLE . ' w, ' . SEARCH_WORDMATCH_TABLE . " m
WHERE m.post_id = $post_id
AND w.word_id = m.word_id";
$result = $db->sql_query($sql);
$result = $this->db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$which = ($row['title_match']) ? 'title' : 'post';
$cur_words[$which][$row['word_text']] = $row['word_id'];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
$words['add']['post'] = array_diff($split_text, array_keys($cur_words['post']));
$words['add']['title'] = array_diff($split_title, array_keys($cur_words['title']));
@ -1188,18 +1178,18 @@ class phpbb_search_fulltext_native extends phpbb_search_base
{
$sql = 'SELECT word_id, word_text
FROM ' . SEARCH_WORDLIST_TABLE . '
WHERE ' . $db->sql_in_set('word_text', $unique_add_words);
$result = $db->sql_query($sql);
WHERE ' . $this->db->sql_in_set('word_text', $unique_add_words);
$result = $this->db->sql_query($sql);
$word_ids = array();
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$word_ids[$row['word_text']] = $row['word_id'];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
$new_words = array_diff($unique_add_words, array_keys($word_ids));
$db->sql_transaction('begin');
$this->db->sql_transaction('begin');
if (sizeof($new_words))
{
$sql_ary = array();
@ -1208,15 +1198,15 @@ class phpbb_search_fulltext_native extends phpbb_search_base
{
$sql_ary[] = array('word_text' => (string) $word, 'word_count' => 0);
}
$db->sql_return_on_error(true);
$db->sql_multi_insert(SEARCH_WORDLIST_TABLE, $sql_ary);
$db->sql_return_on_error(false);
$this->db->sql_return_on_error(true);
$this->db->sql_multi_insert(SEARCH_WORDLIST_TABLE, $sql_ary);
$this->db->sql_return_on_error(false);
}
unset($new_words, $sql_ary);
}
else
{
$db->sql_transaction('begin');
$this->db->sql_transaction('begin');
}
// now update the search match table, remove links to removed words and add links to new words
@ -1233,22 +1223,22 @@ class phpbb_search_fulltext_native extends phpbb_search_base
}
$sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
WHERE ' . $db->sql_in_set('word_id', $sql_in) . '
WHERE ' . $this->db->sql_in_set('word_id', $sql_in) . '
AND post_id = ' . intval($post_id) . "
AND title_match = $title_match";
$db->sql_query($sql);
$this->db->sql_query($sql);
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
SET word_count = word_count - 1
WHERE ' . $db->sql_in_set('word_id', $sql_in) . '
WHERE ' . $this->db->sql_in_set('word_id', $sql_in) . '
AND word_count > 0';
$db->sql_query($sql);
$this->db->sql_query($sql);
unset($sql_in);
}
}
$db->sql_return_on_error(true);
$this->db->sql_return_on_error(true);
foreach ($words['add'] as $word_in => $word_ary)
{
$title_match = ($word_in == 'title') ? 1 : 0;
@ -1258,18 +1248,18 @@ class phpbb_search_fulltext_native extends phpbb_search_base
$sql = 'INSERT INTO ' . SEARCH_WORDMATCH_TABLE . ' (post_id, word_id, title_match)
SELECT ' . (int) $post_id . ', word_id, ' . (int) $title_match . '
FROM ' . SEARCH_WORDLIST_TABLE . '
WHERE ' . $db->sql_in_set('word_text', $word_ary);
$db->sql_query($sql);
WHERE ' . $this->db->sql_in_set('word_text', $word_ary);
$this->db->sql_query($sql);
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
SET word_count = word_count + 1
WHERE ' . $db->sql_in_set('word_text', $word_ary);
$db->sql_query($sql);
WHERE ' . $this->db->sql_in_set('word_text', $word_ary);
$this->db->sql_query($sql);
}
}
$db->sql_return_on_error(false);
$this->db->sql_return_on_error(false);
$db->sql_transaction('commit');
$this->db->sql_transaction('commit');
// destroy cached search results containing any of the words removed or added
$this->destroy_cache(array_unique(array_merge($words['add']['post'], $words['add']['title'], $words['del']['post'], $words['del']['title'])), array($poster_id));
@ -1282,20 +1272,18 @@ class phpbb_search_fulltext_native extends phpbb_search_base
/**
* Removes entries from the wordmatch table for the specified post_ids
*/
function index_remove($post_ids, $author_ids, $forum_ids)
public function index_remove($post_ids, $author_ids, $forum_ids)
{
global $db;
if (sizeof($post_ids))
{
$sql = 'SELECT w.word_id, w.word_text, m.title_match
FROM ' . SEARCH_WORDMATCH_TABLE . ' m, ' . SEARCH_WORDLIST_TABLE . ' w
WHERE ' . $db->sql_in_set('m.post_id', $post_ids) . '
WHERE ' . $this->db->sql_in_set('m.post_id', $post_ids) . '
AND w.word_id = m.word_id';
$result = $db->sql_query($sql);
$result = $this->db->sql_query($sql);
$message_word_ids = $title_word_ids = $word_texts = array();
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
if ($row['title_match'])
{
@ -1307,32 +1295,32 @@ class phpbb_search_fulltext_native extends phpbb_search_base
}
$word_texts[] = $row['word_text'];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
if (sizeof($title_word_ids))
{
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
SET word_count = word_count - 1
WHERE ' . $db->sql_in_set('word_id', $title_word_ids) . '
WHERE ' . $this->db->sql_in_set('word_id', $title_word_ids) . '
AND word_count > 0';
$db->sql_query($sql);
$this->db->sql_query($sql);
}
if (sizeof($message_word_ids))
{
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
SET word_count = word_count - 1
WHERE ' . $db->sql_in_set('word_id', $message_word_ids) . '
WHERE ' . $this->db->sql_in_set('word_id', $message_word_ids) . '
AND word_count > 0';
$db->sql_query($sql);
$this->db->sql_query($sql);
}
unset($title_word_ids);
unset($message_word_ids);
$sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
WHERE ' . $db->sql_in_set('post_id', $post_ids);
$db->sql_query($sql);
WHERE ' . $this->db->sql_in_set('post_id', $post_ids);
$this->db->sql_query($sql);
}
$this->destroy_cache(array_unique($word_texts), array_unique($author_ids));
@ -1342,13 +1330,11 @@ class phpbb_search_fulltext_native extends phpbb_search_base
* Tidy up indexes: Tag 'common words' and remove
* words no longer referenced in the match table
*/
function tidy()
public function tidy()
{
global $db, $config;
// Is the fulltext indexer disabled? If yes then we need not
// carry on ... it's okay ... I know when I'm not wanted boo hoo
if (!$config['fulltext_native_load_upd'])
if (!$this->config['fulltext_native_load_upd'])
{
set_config('search_last_gc', time(), true);
return;
@ -1357,31 +1343,31 @@ class phpbb_search_fulltext_native extends phpbb_search_base
$destroy_cache_words = array();
// Remove common words
if ($config['num_posts'] >= 100 && $config['fulltext_native_common_thres'])
if ($this->config['num_posts'] >= 100 && $this->config['fulltext_native_common_thres'])
{
$common_threshold = ((double) $config['fulltext_native_common_thres']) / 100.0;
$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 . '
WHERE word_count > ' . floor($config['num_posts'] * $common_threshold) . '
WHERE word_count > ' . floor($this->config['num_posts'] * $common_threshold) . '
OR word_common = 1';
$result = $db->sql_query($sql);
$result = $this->db->sql_query($sql);
$sql_in = array();
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$sql_in[] = $row['word_id'];
$destroy_cache_words[] = $row['word_text'];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
if (sizeof($sql_in))
{
// Flag the words
$sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
SET word_common = 1
WHERE ' . $db->sql_in_set('word_id', $sql_in);
$db->sql_query($sql);
WHERE ' . $this->db->sql_in_set('word_id', $sql_in);
$this->db->sql_query($sql);
// by setting search_last_gc to the new time here we make sure that if a user reloads because the
// following query takes too long, he won't run into it again
@ -1389,8 +1375,8 @@ class phpbb_search_fulltext_native extends phpbb_search_base
// Delete the matches
$sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
WHERE ' . $db->sql_in_set('word_id', $sql_in);
$db->sql_query($sql);
WHERE ' . $this->db->sql_in_set('word_id', $sql_in);
$this->db->sql_query($sql);
}
unset($sql_in);
}
@ -1407,23 +1393,21 @@ class phpbb_search_fulltext_native extends phpbb_search_base
/**
* Deletes all words from the index
*/
function delete_index($acp_module, $u_action)
public function delete_index($acp_module, $u_action)
{
global $db;
switch ($db->sql_layer)
switch ($this->db->sql_layer)
{
case 'sqlite':
case 'firebird':
$db->sql_query('DELETE FROM ' . SEARCH_WORDLIST_TABLE);
$db->sql_query('DELETE FROM ' . SEARCH_WORDMATCH_TABLE);
$db->sql_query('DELETE FROM ' . SEARCH_RESULTS_TABLE);
$this->db->sql_query('DELETE FROM ' . SEARCH_WORDLIST_TABLE);
$this->db->sql_query('DELETE FROM ' . SEARCH_WORDMATCH_TABLE);
$this->db->sql_query('DELETE FROM ' . SEARCH_RESULTS_TABLE);
break;
default:
$db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDLIST_TABLE);
$db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDMATCH_TABLE);
$db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDLIST_TABLE);
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDMATCH_TABLE);
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
break;
}
}
@ -1431,7 +1415,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
/**
* Returns true if both FULLTEXT indexes exist
*/
function index_created()
public function index_created()
{
if (!sizeof($this->stats))
{
@ -1444,26 +1428,22 @@ class phpbb_search_fulltext_native extends phpbb_search_base
/**
* Returns an associative array containing information about the indexes
*/
function index_stats()
public function index_stats()
{
global $user;
if (!sizeof($this->stats))
{
$this->get_stats();
}
return array(
$user->lang['TOTAL_WORDS'] => $this->stats['total_words'],
$user->lang['TOTAL_MATCHES'] => $this->stats['total_matches']);
$this->user->lang['TOTAL_WORDS'] => $this->stats['total_words'],
$this->user->lang['TOTAL_MATCHES'] => $this->stats['total_matches']);
}
function get_stats()
protected function get_stats()
{
global $db;
$this->stats['total_words'] = $db->get_estimated_row_count(SEARCH_WORDLIST_TABLE);
$this->stats['total_matches'] = $db->get_estimated_row_count(SEARCH_WORDMATCH_TABLE);
$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);
}
/**
@ -1481,9 +1461,8 @@ class phpbb_search_fulltext_native extends phpbb_search_base
*
* @todo normalizer::cleanup being able to be used?
*/
function cleanup($text, $allowed_chars = null, $encoding = 'utf-8')
protected function cleanup($text, $allowed_chars = null, $encoding = 'utf-8')
{
global $phpbb_root_path, $phpEx;
static $conv = array(), $conv_loaded = array();
$words = $allow = array();
@ -1680,7 +1659,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
if (!isset($conv_loaded[$idx]))
{
$conv_loaded[$idx] = 1;
$file = $phpbb_root_path . 'includes/utf/data/search_indexer_' . $idx . '.' . $phpEx;
$file = $this->phpbb_root_path . 'includes/utf/data/search_indexer_' . $idx . '.' . $this->php_ext;
if (file_exists($file))
{
@ -1711,31 +1690,28 @@ class phpbb_search_fulltext_native extends phpbb_search_base
/**
* Returns a list of options for the ACP to display
*/
function acp()
public function acp()
{
global $user, $config;
/**
* if we need any options, copied from fulltext_native for now, will have to be adjusted or removed
*/
$tpl = '
<dl>
<dt><label for="fulltext_native_load_upd">' . $user->lang['YES_SEARCH_UPDATE'] . ':</label><br /><span>' . $user->lang['YES_SEARCH_UPDATE_EXPLAIN'] . '</span></dt>
<dd><label><input type="radio" id="fulltext_native_load_upd" name="config[fulltext_native_load_upd]" value="1"' . (($config['fulltext_native_load_upd']) ? ' checked="checked"' : '') . ' class="radio" /> ' . $user->lang['YES'] . '</label><label><input type="radio" name="config[fulltext_native_load_upd]" value="0"' . ((!$config['fulltext_native_load_upd']) ? ' checked="checked"' : '') . ' class="radio" /> ' . $user->lang['NO'] . '</label></dd>
<dt><label for="fulltext_native_load_upd">' . $this->user->lang['YES_SEARCH_UPDATE'] . ':</label><br /><span>' . $this->user->lang['YES_SEARCH_UPDATE_EXPLAIN'] . '</span></dt>
<dd><label><input type="radio" id="fulltext_native_load_upd" name="config[fulltext_native_load_upd]" value="1"' . (($this->config['fulltext_native_load_upd']) ? ' checked="checked"' : '') . ' class="radio" /> ' . $this->user->lang['YES'] . '</label><label><input type="radio" name="config[fulltext_native_load_upd]" value="0"' . ((!$this->config['fulltext_native_load_upd']) ? ' checked="checked"' : '') . ' class="radio" /> ' . $this->user->lang['NO'] . '</label></dd>
</dl>
<dl>
<dt><label for="fulltext_native_min_chars">' . $user->lang['MIN_SEARCH_CHARS'] . ':</label><br /><span>' . $user->lang['MIN_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_native_min_chars" type="text" size="3" maxlength="3" name="config[fulltext_native_min_chars]" value="' . (int) $config['fulltext_native_min_chars'] . '" /></dd>
<dt><label for="fulltext_native_min_chars">' . $this->user->lang['MIN_SEARCH_CHARS'] . ':</label><br /><span>' . $this->user->lang['MIN_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_native_min_chars" type="text" size="3" maxlength="3" name="config[fulltext_native_min_chars]" value="' . (int) $this->config['fulltext_native_min_chars'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_native_max_chars">' . $user->lang['MAX_SEARCH_CHARS'] . ':</label><br /><span>' . $user->lang['MAX_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_native_max_chars" type="text" size="3" maxlength="3" name="config[fulltext_native_max_chars]" value="' . (int) $config['fulltext_native_max_chars'] . '" /></dd>
<dt><label for="fulltext_native_max_chars">' . $this->user->lang['MAX_SEARCH_CHARS'] . ':</label><br /><span>' . $this->user->lang['MAX_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_native_max_chars" type="text" size="3" maxlength="3" name="config[fulltext_native_max_chars]" value="' . (int) $this->config['fulltext_native_max_chars'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_native_common_thres">' . $user->lang['COMMON_WORD_THRESHOLD'] . ':</label><br /><span>' . $user->lang['COMMON_WORD_THRESHOLD_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_native_common_thres" type="text" size="3" maxlength="3" name="config[fulltext_native_common_thres]" value="' . (double) $config['fulltext_native_common_thres'] . '" /> %</dd>
<dt><label for="fulltext_native_common_thres">' . $this->user->lang['COMMON_WORD_THRESHOLD'] . ':</label><br /><span>' . $this->user->lang['COMMON_WORD_THRESHOLD_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_native_common_thres" type="text" size="3" maxlength="3" name="config[fulltext_native_common_thres]" value="' . (double) $this->config['fulltext_native_common_thres'] . '" /> %</dd>
</dl>
';

View file

@ -22,12 +22,15 @@ if (!defined('IN_PHPBB'))
*/
class phpbb_search_fulltext_postgres extends phpbb_search_base
{
private $stats = array();
private $split_words = array();
private $tsearch_usable = false;
private $version;
private $tsearch_query;
private $phrase_search = false;
protected $stats = array();
protected $split_words = array();
protected $tsearch_usable = false;
protected $version;
protected $tsearch_query;
protected $phrase_search = false;
protected $config;
protected $db;
protected $user;
public $search_query;
public $common_words = array();
public $word_length = array();
@ -38,16 +41,17 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
*
* @param string|bool $error Any error that occurs is passed on through this reference variable otherwise false
*/
public function __construct(&$error)
public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user)
{
global $db, $config;
$this->config = $config;
$this->db = $db;
$this->user = $user;
$this->word_length = array('min' => $config['fulltext_postgres_min_word_len'], 'max' => $config['fulltext_postgres_max_word_len']);
$this->word_length = array('min' => $this->config['fulltext_postgres_min_word_len'], 'max' => $this->config['fulltext_postgres_max_word_len']);
if ($db->sql_layer == 'postgres')
if ($this->db->sql_layer == 'postgres')
{
$pgsql_version = explode(',', substr($db->sql_server_info(), 10));
$pgsql_version = explode(',', substr($this->db->sql_server_info(), 10));
$this->version = trim($pgsql_version[0]);
if (version_compare($this->version, '8.3', '>='))
{
@ -62,8 +66,6 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
* Returns the name of this search backend to be displayed to administrators
*
* @return string Name
*
* @access public
*/
public function get_name()
{
@ -74,8 +76,6 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
* Returns if phrase search is supported or not
*
* @return bool
*
* @access public
*/
public function supports_phrase_search()
{
@ -86,21 +86,17 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
* Checks for correct PostgreSQL version and stores min/max word length in the config
*
* @return string|bool Language key of the error/incompatiblity occured
*
* @access public
*/
function init()
public function init()
{
global $db, $user;
if ($db->sql_layer != 'postgres')
if ($this->db->sql_layer != 'postgres')
{
return $user->lang['FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE'];
return $this->user->lang['FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE'];
}
if (!$this->tsearch_usable)
{
return $user->lang['FULLTEXT_POSTGRES_TS_NOT_USABLE'];
return $this->user->lang['FULLTEXT_POSTGRES_TS_NOT_USABLE'];
}
return false;
@ -113,13 +109,9 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
* @param string &$keywords Contains the keyword as entered by the user
* @param string $terms is either 'all' or 'any'
* @return bool false if no valid keywords were found and otherwise true
*
* @access public
*/
function split_keywords(&$keywords, $terms)
public function split_keywords(&$keywords, $terms)
{
global $config;
if ($terms == 'all')
{
$match = array('#\sand\s#iu', '#\sor\s#iu', '#\snot\s#iu', '#\+#', '#-#', '#\|#');
@ -143,7 +135,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
// check word length
$clean_len = utf8_strlen(str_replace('*', '', $clean_word));
if (($clean_len < $config['fulltext_postgres_min_word_len']) || ($clean_len > $config['fulltext_postgres_max_word_len']))
if (($clean_len < $this->config['fulltext_postgres_min_word_len']) || ($clean_len > $this->config['fulltext_postgres_max_word_len']))
{
$this->common_words[] = $word;
unset($this->split_words[$i]);
@ -208,13 +200,9 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
/**
* Turns text into an array of words
* @param string $text contains post text/subject
*
* @access public
*/
function split_message($text)
public function split_message($text)
{
global $config;
// Split words
$text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text)));
$matches = array();
@ -226,7 +214,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
for ($i = 0, $n = sizeof($text); $i < $n; $i++)
{
$text[$i] = trim($text[$i]);
if (utf8_strlen($text[$i]) < $config['fulltext_postgres_min_word_len'] || utf8_strlen($text[$i]) > $config['fulltext_postgres_max_word_len'])
if (utf8_strlen($text[$i]) < $this->config['fulltext_postgres_min_word_len'] || utf8_strlen($text[$i]) > $this->config['fulltext_postgres_max_word_len'])
{
unset($text[$i]);
}
@ -254,13 +242,9 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
* @return boolean|int total number of results
*
* @access public
*/
function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
// No keywords? No posts.
if (!$this->search_query)
{
@ -349,7 +333,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
}
else
{
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
}
$sql_select = ($type == 'posts') ? 'p.post_id' : 'DISTINCT t.topic_id';
@ -360,11 +344,11 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
if (sizeof($author_ary) && $author_name)
{
// first one matches post of registered users, second one guests and deleted users
$sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
$sql_author = '(' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
}
else if (sizeof($author_ary))
{
$sql_author = ' AND ' . $db->sql_in_set('p.poster_id', $author_ary);
$sql_author = ' AND ' . $this->db->sql_in_set('p.poster_id', $author_ary);
}
else
{
@ -374,7 +358,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
$sql_where_options = $sql_sort_join;
$sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : '';
$sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : '';
$sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_where_options .= $m_approve_fid_sql;
$sql_where_options .= $sql_author;
$sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
@ -383,7 +367,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
$tmp_sql_match = array();
foreach (explode(',', $sql_match) as $sql_match_column)
{
$tmp_sql_match[] = "to_tsvector ('" . $db->sql_escape($config['fulltext_postgres_ts_name']) . "', " . $sql_match_column . ") @@ to_tsquery ('" . $db->sql_escape($config['fulltext_postgres_ts_name']) . "', '" . $db->sql_escape($this->tsearch_query) . "')";
$tmp_sql_match[] = "to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', " . $sql_match_column . ") @@ to_tsquery ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', '" . $this->db->sql_escape($this->tsearch_query) . "')";
}
$sql = "SELECT $sql_select
@ -391,13 +375,13 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
WHERE (" . implode(' OR ', $tmp_sql_match) . ")
$sql_where_options
ORDER BY $sql_sort";
$result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
$result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start);
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$id_ary[] = $row[$field];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
$id_ary = array_unique($id_ary);
@ -442,13 +426,9 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
* @return boolean|int total number of results
*
* @access public
*/
function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
// No author? No posts.
if (!sizeof($author_ary))
{
@ -484,13 +464,13 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
if ($author_name)
{
// first one matches post of registered users, second one guests and deleted users
$sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
$sql_author = '(' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
}
else
{
$sql_author = $db->sql_in_set('p.poster_id', $author_ary);
$sql_author = $this->db->sql_in_set('p.poster_id', $author_ary);
}
$sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
$sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : '';
@ -526,7 +506,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
}
else
{
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
}
// Build the query for really selecting the post_ids
@ -562,13 +542,13 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
}
// Only read one block of posts from the db and then cache it
$result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
$result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start);
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$id_ary[] = $row[$field];
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
// retrieve the total result count if needed
if (!$result_count)
@ -600,13 +580,9 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
* @param string $subject contains the subject of the post to index
* @param int $poster_id contains the user id of the poster
* @param int $forum_id contains the forum id of parent forum of the post
*
* @access public
*/
function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
{
global $db;
// Split old and new post/subject to obtain array of words
$split_text = $this->split_message($message);
$split_title = ($subject) ? $this->split_message($subject) : array();
@ -624,23 +600,17 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
/**
* Destroy cached results, that might be outdated after deleting a post
*
* @access public
*/
function index_remove($post_ids, $author_ids, $forum_ids)
public function index_remove($post_ids, $author_ids, $forum_ids)
{
$this->destroy_cache(array(), $author_ids);
}
/**
* Destroy old cache entries
*
* @access public
*/
function tidy()
public function tidy()
{
global $db, $config;
// destroy too old cached search results
$this->destroy_cache(array());
@ -651,13 +621,9 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
* Create fulltext index
*
* @return string|bool error string is returned incase of errors otherwise false
*
* @access public
*/
function create_index($acp_module, $u_action)
public function create_index($acp_module, $u_action)
{
global $db, $config;
// Make sure we can actually use PostgreSQL with fulltext indexes
if ($error = $this->init())
{
@ -671,15 +637,15 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
if (!isset($this->stats['post_subject']))
{
$db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $config['fulltext_postgres_ts_name'] . "_post_subject ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $db->sql_escape($config['fulltext_postgres_ts_name']) . "', post_subject))");
$this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_subject ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_subject))");
}
if (!isset($this->stats['post_text']))
{
$db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $config['fulltext_postgres_ts_name'] . "_post_text ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $db->sql_escape($config['fulltext_postgres_ts_name']) . "', post_text))");
$this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_text ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_text))");
}
$db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
return false;
}
@ -688,13 +654,9 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
* Drop fulltext index
*
* @return string|bool error string is returned incase of errors otherwise false
*
* @access public
*/
function delete_index($acp_module, $u_action)
public function delete_index($acp_module, $u_action)
{
global $db;
// Make sure we can actually use PostgreSQL with fulltext indexes
if ($error = $this->init())
{
@ -708,25 +670,23 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
if (isset($this->stats['post_subject']))
{
$db->sql_query('DROP INDEX ' . $this->stats['post_subject']['relname']);
$this->db->sql_query('DROP INDEX ' . $this->stats['post_subject']['relname']);
}
if (isset($this->stats['post_text']))
{
$db->sql_query('DROP INDEX ' . $this->stats['post_text']['relname']);
$this->db->sql_query('DROP INDEX ' . $this->stats['post_text']['relname']);
}
$db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
$this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
return false;
}
/**
* Returns true if both FULLTEXT indexes exist
*
* @access public
*/
function index_created()
public function index_created()
{
if (empty($this->stats))
{
@ -738,33 +698,25 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
/**
* Returns an associative array containing information about the indexes
*
* @access public
*/
function index_stats()
public function index_stats()
{
global $user;
if (empty($this->stats))
{
$this->get_stats();
}
return array(
$user->lang['FULLTEXT_POSTGRES_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0,
$this->user->lang['FULLTEXT_POSTGRES_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0,
);
}
/**
* Computes the stats and store them in the $this->stats associative array
*
* @access private
*/
function get_stats()
protected function get_stats()
{
global $db, $config;
if ($db->sql_layer != 'postgres')
if ($this->db->sql_layer != 'postgres')
{
$this->stats = array();
return;
@ -776,74 +728,70 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
AND pg_catalog.pg_table_is_visible(c1.oid)
AND c1.oid = i.indrelid
AND i.indexrelid = c2.oid";
$result = $db->sql_query($sql);
$result = $this->db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
// deal with older PostgreSQL versions which didn't use Index_type
if (strpos($row['indexdef'], 'to_tsvector') !== false)
{
if ($row['relname'] == POSTS_TABLE . '_' . $config['fulltext_postgres_ts_name'] . '_post_text' || $row['relname'] == POSTS_TABLE . '_post_text')
if ($row['relname'] == POSTS_TABLE . '_' . $this->config['fulltext_postgres_ts_name'] . '_post_text' || $row['relname'] == POSTS_TABLE . '_post_text')
{
$this->stats['post_text'] = $row;
}
else if ($row['relname'] == POSTS_TABLE . '_' . $config['fulltext_postgres_ts_name'] . '_post_subject' || $row['relname'] == POSTS_TABLE . '_post_subject')
else if ($row['relname'] == POSTS_TABLE . '_' . $this->config['fulltext_postgres_ts_name'] . '_post_subject' || $row['relname'] == POSTS_TABLE . '_post_subject')
{
$this->stats['post_subject'] = $row;
}
}
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
$this->stats['total_posts'] = $config['num_posts'];
$this->stats['total_posts'] = $this->config['num_posts'];
}
/**
* Display various options that can be configured for the backend from the acp
*
* @return associative array containing template and config variables
*
* @access public
*/
function acp()
public function acp()
{
global $user, $config, $db;
$tpl = '
<dl>
<dt><label>' . $user->lang['FULLTEXT_POSTGRES_VERSION_CHECK'] . '</label><br /><span>' . $user->lang['FULLTEXT_POSTGRES_VERSION_CHECK_EXPLAIN'] . '</span></dt>
<dd>' . (($this->tsearch_usable) ? $user->lang['YES'] : $user->lang['NO']) . ' (PostgreSQL ' . $this->version . ')</dd>
<dt><label>' . $this->user->lang['FULLTEXT_POSTGRES_VERSION_CHECK'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_POSTGRES_VERSION_CHECK_EXPLAIN'] . '</span></dt>
<dd>' . (($this->tsearch_usable) ? $this->user->lang['YES'] : $this->user->lang['NO']) . ' (PostgreSQL ' . $this->version . ')</dd>
</dl>
<dl>
<dt><label>' . $user->lang['FULLTEXT_POSTGRES_TS_NAME'] . '</label><br /><span>' . $user->lang['FULLTEXT_POSTGRES_TS_NAME_EXPLAIN'] . '</span></dt>
<dt><label>' . $this->user->lang['FULLTEXT_POSTGRES_TS_NAME'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_POSTGRES_TS_NAME_EXPLAIN'] . '</span></dt>
<dd><select name="config[fulltext_postgres_ts_name]">';
if ($db->sql_layer == 'postgres' && $this->tsearch_usable)
if ($this->db->sql_layer == 'postgres' && $this->tsearch_usable)
{
$sql = 'SELECT cfgname AS ts_name
FROM pg_ts_config';
$result = $db->sql_query($sql);
$result = $this->db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
while ($row = $this->db->sql_fetchrow($result))
{
$tpl .= '<option value="' . $row['ts_name'] . '"' . ($row['ts_name'] === $config['fulltext_postgres_ts_name'] ? ' selected="selected"' : '') . '>' . $row['ts_name'] . '</option>';
$tpl .= '<option value="' . $row['ts_name'] . '"' . ($row['ts_name'] === $this->config['fulltext_postgres_ts_name'] ? ' selected="selected"' : '') . '>' . $row['ts_name'] . '</option>';
}
$db->sql_freeresult($result);
$this->db->sql_freeresult($result);
}
else
{
$tpl .= '<option value="' . $config['fulltext_postgres_ts_name'] . '" selected="selected">' . $config['fulltext_postgres_ts_name'] . '</option>';
$tpl .= '<option value="' . $this->config['fulltext_postgres_ts_name'] . '" selected="selected">' . $this->config['fulltext_postgres_ts_name'] . '</option>';
}
$tpl .= '</select></dd>
</dl>
<dl>
<dt><label for="fulltext_postgres_min_word_len">' . $user->lang['FULLTEXT_POSTGRES_MIN_WORD_LEN'] . ':</label><br /><span>' . $user->lang['FULLTEXT_POSTGRES_MIN_WORD_LEN_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_postgres_min_word_len" type="text" size="3" maxlength="3" name="config[fulltext_postgres_min_word_len]" value="' . (int) $config['fulltext_postgres_min_word_len'] . '" /></dd>
<dt><label for="fulltext_postgres_min_word_len">' . $this->user->lang['FULLTEXT_POSTGRES_MIN_WORD_LEN'] . ':</label><br /><span>' . $this->user->lang['FULLTEXT_POSTGRES_MIN_WORD_LEN_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_postgres_min_word_len" type="text" size="3" maxlength="3" name="config[fulltext_postgres_min_word_len]" value="' . (int) $this->config['fulltext_postgres_min_word_len'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_postgres_max_word_len">' . $user->lang['FULLTEXT_POSTGRES_MAX_WORD_LEN'] . ':</label><br /><span>' . $user->lang['FULLTEXT_POSTGRES_MAX_WORD_LEN_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_postgres_max_word_len" type="text" size="3" maxlength="3" name="config[fulltext_postgres_max_word_len]" value="' . (int) $config['fulltext_postgres_max_word_len'] . '" /></dd>
<dt><label for="fulltext_postgres_max_word_len">' . $this->user->lang['FULLTEXT_POSTGRES_MAX_WORD_LEN'] . ':</label><br /><span>' . $this->user->lang['FULLTEXT_POSTGRES_MAX_WORD_LEN_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_postgres_max_word_len" type="text" size="3" maxlength="3" name="config[fulltext_postgres_max_word_len]" value="' . (int) $this->config['fulltext_postgres_max_word_len'] . '" /></dd>
</dl>
';

View file

@ -0,0 +1,787 @@
<?php
/**
*
* @package search
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* @ignore
*/
define('SPHINX_MAX_MATCHES', 20000);
define('SPHINX_CONNECT_RETRIES', 3);
define('SPHINX_CONNECT_WAIT_TIME', 300);
/**
* fulltext_sphinx
* Fulltext search based on the sphinx search deamon
* @package search
*/
class phpbb_search_fulltext_sphinx
{
protected $stats = array();
protected $split_words = array();
protected $id;
protected $indexes;
protected $sphinx;
protected $phpbb_root_path;
protected $php_ext;
protected $auth;
protected $config;
protected $db;
protected $db_tools;
protected $dbtype;
protected $user;
protected $config_file_data = '';
public $search_query;
public $common_words = array();
/**
* Constructor
* Creates a new phpbb_search_fulltext_postgres, which is used as a search backend.
*
* @param string|bool $error Any error that occurs is passed on through this reference variable otherwise false
*/
public function __construct(&$error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $phpEx;
$this->config = $config;
$this->user = $user;
$this->db = $db;
$this->auth = $auth;
if (!class_exists('phpbb_db_tools'))
{
require($this->phpbb_root_path . 'includes/db/db_tools.' . $this->php_ext);
}
// Initialize phpbb_db_tools object
$this->db_tools = new phpbb_db_tools($this->db);
if(!$this->config['fulltext_sphinx_id'])
{
set_config('fulltext_sphinx_id', unique_id());
}
$this->id = $this->config['fulltext_sphinx_id'];
$this->indexes = 'index_phpbb_' . $this->id . '_delta;index_phpbb_' . $this->id . '_main';
if (!class_exists('SphinxClient'))
{
require($this->phpbb_root_path . 'includes/sphinxapi.' . $this->php_ext);
}
// Initialize sphinx client
$this->sphinx = new SphinxClient();
$this->sphinx->SetServer(($this->config['fulltext_sphinx_host'] ? $this->config['fulltext_sphinx_host'] : 'localhost'), ($this->config['fulltext_sphinx_port'] ? (int) $this->config['fulltext_sphinx_port'] : 9312));
$error = false;
}
/**
* Returns the name of this search backend to be displayed to administrators
*
* @return string Name
*/
public function get_name()
{
return 'Sphinx Fulltext';
}
/**
* Checks permissions and paths, if everything is correct it generates the config file
*
* @return string|bool Language key of the error/incompatiblity encountered, or false if successful
*/
public function init()
{
if ($this->db->sql_layer != 'mysql' && $this->db->sql_layer != 'mysql4' && $this->db->sql_layer != 'mysqli' && $this->db->sql_layer != 'postgres')
{
return $this->user->lang['FULLTEXT_SPHINX_WRONG_DATABASE'];
}
// Move delta to main index each hour
set_config('search_gc', 3600);
return false;
}
/**
* Generates content of sphinx.conf
*
* @return bool True if sphinx.conf content is correctly generated, false otherwise
*/
protected function config_generate()
{
// Check if Database is supported by Sphinx
if ($this->db->sql_layer =='mysql' || $this->db->sql_layer == 'mysql4' || $this->db->sql_layer == 'mysqli')
{
$this->dbtype = 'mysql';
}
else if ($this->db->sql_layer == 'postgres')
{
$this->dbtype = 'pgsql';
}
else
{
$this->config_file_data = $this->user->lang('FULLTEXT_SPHINX_WRONG_DATABASE');
return false;
}
// Check if directory paths have been filled
if (!$this->config['fulltext_sphinx_data_path'])
{
$this->config_file_data = $this->user->lang('FULLTEXT_SPHINX_NO_CONFIG_DATA');
return false;
}
include($this->phpbb_root_path . 'config.' . $this->php_ext);
/* Now that we're sure everything was entered correctly,
generate a config for the index. We use a config value
fulltext_sphinx_id for this, as it should be unique. */
$config_object = new phpbb_search_sphinx_config($this->config_file_data);
$config_data = array(
'source source_phpbb_' . $this->id . '_main' => array(
array('type', $this->dbtype),
// This config value sql_host needs to be changed incase sphinx and sql are on different servers
array('sql_host', $dbhost),
array('sql_user', $dbuser),
array('sql_pass', $dbpasswd),
array('sql_db', $dbname),
array('sql_port', $dbport),
array('sql_query_pre', 'SET NAMES \'utf8\''),
array('sql_query_pre', 'UPDATE ' . SPHINX_TABLE . ' SET max_doc_id = (SELECT MAX(post_id) FROM ' . POSTS_TABLE . ') WHERE counter_id = 1'),
array('sql_query_range', 'SELECT MIN(post_id), MAX(post_id) FROM ' . POSTS_TABLE . ''),
array('sql_range_step', '5000'),
array('sql_query', 'SELECT
p.post_id AS id,
p.forum_id,
p.topic_id,
p.poster_id,
CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post,
p.post_time,
p.post_subject,
p.post_subject as title,
p.post_text as data,
t.topic_last_post_time,
0 as deleted
FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t
WHERE
p.topic_id = t.topic_id
AND p.post_id >= $start AND p.post_id <= $end'),
array('sql_query_post', ''),
array('sql_query_post_index', 'UPDATE ' . SPHINX_TABLE . ' SET max_doc_id = $maxid WHERE counter_id = 1'),
array('sql_query_info', 'SELECT * FROM ' . POSTS_TABLE . ' WHERE post_id = $id'),
array('sql_attr_uint', 'forum_id'),
array('sql_attr_uint', 'topic_id'),
array('sql_attr_uint', 'poster_id'),
array('sql_attr_bool', 'topic_first_post'),
array('sql_attr_bool', 'deleted'),
array('sql_attr_timestamp' , 'post_time'),
array('sql_attr_timestamp' , 'topic_last_post_time'),
array('sql_attr_str2ordinal', 'post_subject'),
),
'source source_phpbb_' . $this->id . '_delta : source_phpbb_' . $this->id . '_main' => array(
array('sql_query_pre', ''),
array('sql_query_range', ''),
array('sql_range_step', ''),
array('sql_query', 'SELECT
p.post_id AS id,
p.forum_id,
p.topic_id,
p.poster_id,
CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post,
p.post_time,
p.post_subject,
p.post_subject as title,
p.post_text as data,
t.topic_last_post_time,
0 as deleted
FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t
WHERE
p.topic_id = t.topic_id
AND p.post_id >= ( SELECT max_doc_id FROM ' . SPHINX_TABLE . ' WHERE counter_id=1 )'),
),
'index index_phpbb_' . $this->id . '_main' => array(
array('path', $this->config['fulltext_sphinx_data_path'] . 'index_phpbb_' . $this->id . '_main'),
array('source', 'source_phpbb_' . $this->id . '_main'),
array('docinfo', 'extern'),
array('morphology', 'none'),
array('stopwords', ''),
array('min_word_len', '2'),
array('charset_type', 'utf-8'),
array('charset_table', 'U+FF10..U+FF19->0..9, 0..9, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z, A..Z->a..z, a..z, U+0149, U+017F, U+0138, U+00DF, U+00FF, U+00C0..U+00D6->U+00E0..U+00F6, U+00E0..U+00F6, U+00D8..U+00DE->U+00F8..U+00FE, U+00F8..U+00FE, U+0100->U+0101, U+0101, U+0102->U+0103, U+0103, U+0104->U+0105, U+0105, U+0106->U+0107, U+0107, U+0108->U+0109, U+0109, U+010A->U+010B, U+010B, U+010C->U+010D, U+010D, U+010E->U+010F, U+010F, U+0110->U+0111, U+0111, U+0112->U+0113, U+0113, U+0114->U+0115, U+0115, U+0116->U+0117, U+0117, U+0118->U+0119, U+0119, U+011A->U+011B, U+011B, U+011C->U+011D, U+011D, U+011E->U+011F, U+011F, U+0130->U+0131, U+0131, U+0132->U+0133, U+0133, U+0134->U+0135, U+0135, U+0136->U+0137, U+0137, U+0139->U+013A, U+013A, U+013B->U+013C, U+013C, U+013D->U+013E, U+013E, U+013F->U+0140, U+0140, U+0141->U+0142, U+0142, U+0143->U+0144, U+0144, U+0145->U+0146, U+0146, U+0147->U+0148, U+0148, U+014A->U+014B, U+014B, U+014C->U+014D, U+014D, U+014E->U+014F, U+014F, U+0150->U+0151, U+0151, U+0152->U+0153, U+0153, U+0154->U+0155, U+0155, U+0156->U+0157, U+0157, U+0158->U+0159, U+0159, U+015A->U+015B, U+015B, U+015C->U+015D, U+015D, U+015E->U+015F, U+015F, U+0160->U+0161, U+0161, U+0162->U+0163, U+0163, U+0164->U+0165, U+0165, U+0166->U+0167, U+0167, U+0168->U+0169, U+0169, U+016A->U+016B, U+016B, U+016C->U+016D, U+016D, U+016E->U+016F, U+016F, U+0170->U+0171, U+0171, U+0172->U+0173, U+0173, U+0174->U+0175, U+0175, U+0176->U+0177, U+0177, U+0178->U+00FF, U+00FF, U+0179->U+017A, U+017A, U+017B->U+017C, U+017C, U+017D->U+017E, U+017E, U+0410..U+042F->U+0430..U+044F, U+0430..U+044F, U+4E00..U+9FFF'),
array('min_prefix_len', '0'),
array('min_infix_len', '0'),
),
'index index_phpbb_' . $this->id . '_delta : index_phpbb_' . $this->id . '_main' => array(
array('path', $this->config['fulltext_sphinx_data_path'] . 'index_phpbb_' . $this->id . '_delta'),
array('source', 'source_phpbb_' . $this->id . '_delta'),
),
'indexer' => array(
array('mem_limit', $this->config['fulltext_sphinx_indexer_mem_limit'] . 'M'),
),
'searchd' => array(
array('compat_sphinxql_magics' , '0'),
array('listen' , ($this->config['fulltext_sphinx_host'] ? $this->config['fulltext_sphinx_host'] : 'localhost') . ':' . ($this->config['fulltext_sphinx_port'] ? $this->config['fulltext_sphinx_port'] : '9312')),
array('log', $this->config['fulltext_sphinx_data_path'] . 'log/searchd.log'),
array('query_log', $this->config['fulltext_sphinx_data_path'] . 'log/sphinx-query.log'),
array('read_timeout', '5'),
array('max_children', '30'),
array('pid_file', $this->config['fulltext_sphinx_data_path'] . 'searchd.pid'),
array('max_matches', (string) SPHINX_MAX_MATCHES),
array('binlog_path', $this->config['fulltext_sphinx_data_path']),
),
);
$non_unique = array('sql_query_pre' => true, 'sql_attr_uint' => true, 'sql_attr_timestamp' => true, 'sql_attr_str2ordinal' => true, 'sql_attr_bool' => true);
$delete = array('sql_group_column' => true, 'sql_date_column' => true, 'sql_str2ordinal_column' => true);
foreach ($config_data as $section_name => $section_data)
{
$section = $config_object->get_section_by_name($section_name);
if (!$section)
{
$section = $config_object->add_section($section_name);
}
foreach ($delete as $key => $void)
{
$section->delete_variables_by_name($key);
}
foreach ($non_unique as $key => $void)
{
$section->delete_variables_by_name($key);
}
foreach ($section_data as $entry)
{
$key = $entry[0];
$value = $entry[1];
if (!isset($non_unique[$key]))
{
$variable = $section->get_variable_by_name($key);
if (!$variable)
{
$variable = $section->create_variable($key, $value);
}
else
{
$variable->set_value($value);
}
}
else
{
$variable = $section->create_variable($key, $value);
}
}
}
$this->config_file_data = $config_object->get_data();
return true;
}
/**
* Splits keywords entered by a user into an array of words stored in $this->split_words
* Stores the tidied search query in $this->search_query
*
* @param string $keywords Contains the keyword as entered by the user
* @param string $terms is either 'all' or 'any'
* @return false if no valid keywords were found and otherwise true
*/
public function split_keywords(&$keywords, $terms)
{
if ($terms == 'all')
{
$match = array('#\sand\s#i', '#\sor\s#i', '#\snot\s#i', '#\+#', '#-#', '#\|#', '#@#');
$replace = array(' & ', ' | ', ' - ', ' +', ' -', ' |', '');
$replacements = 0;
$keywords = preg_replace($match, $replace, $keywords);
$this->sphinx->SetMatchMode(SPH_MATCH_EXTENDED);
}
else
{
$this->sphinx->SetMatchMode(SPH_MATCH_ANY);
}
// Keep quotes and new lines
$keywords = str_replace(array('&quot;', "\n"), array('"', ' '), trim($keywords));
if (strlen($keywords) > 0)
{
$this->search_query = str_replace('"', '&quot;', $keywords);
return true;
}
return false;
}
/**
* Performs a search on keywords depending on display specific params. You have to run split_keywords() first.
*
* @param string $type contains either posts or topics depending on what should be searched for
* @param string $fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched)
* @param string $terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words)
* @param array $sort_by_sql contains SQL code for the ORDER BY part of a query
* @param string $sort_key is the key of $sort_by_sql for the selected sorting
* @param string $sort_dir is either a or d representing ASC and DESC
* @param string $sort_days specifies the maximum amount of days a post may be old
* @param array $ex_fid_ary specifies an array of forum ids which should not be searched
* @param array $m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
* @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
* @param array $author_ary an array of author ids if the author should be ignored during the search the array is empty
* @param string $author_name specifies the author match, when ANONYMOUS is also a search-match
* @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
* @return boolean|int total number of results
*/
public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
// No keywords? No posts.
if (!strlen($this->search_query) && !sizeof($author_ary))
{
return false;
}
$id_ary = array();
$join_topic = ($type != 'posts');
// Sorting
if ($type == 'topics')
{
switch ($sort_key)
{
case 'a':
$this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'poster_id ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'));
break;
case 'f':
$this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'forum_id ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'));
break;
case 'i':
case 's':
$this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'post_subject ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'));
break;
case 't':
default:
$this->sphinx->SetGroupBy('topic_id', SPH_GROUPBY_ATTR, 'topic_last_post_time ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'));
break;
}
}
else
{
switch ($sort_key)
{
case 'a':
$this->sphinx->SetSortMode(($sort_dir == 'a') ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'poster_id');
break;
case 'f':
$this->sphinx->SetSortMode(($sort_dir == 'a') ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'forum_id');
break;
case 'i':
case 's':
$this->sphinx->SetSortMode(($sort_dir == 'a') ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'post_subject');
break;
case 't':
default:
$this->sphinx->SetSortMode(($sort_dir == 'a') ? SPH_SORT_ATTR_ASC : SPH_SORT_ATTR_DESC, 'post_time');
break;
}
}
// Most narrow filters first
if ($topic_id)
{
$this->sphinx->SetFilter('topic_id', array($topic_id));
}
$search_query_prefix = '';
switch ($fields)
{
case 'titleonly':
// Only search the title
if ($terms == 'all')
{
$search_query_prefix = '@title ';
}
// Weight for the title
$this->sphinx->SetFieldWeights(array("title" => 5, "data" => 1));
// 1 is first_post, 0 is not first post
$this->sphinx->SetFilter('topic_first_post', array(1));
break;
case 'msgonly':
// Only search the body
if ($terms == 'all')
{
$search_query_prefix = '@data ';
}
// Weight for the body
$this->sphinx->SetFieldWeights(array("title" => 1, "data" => 5));
break;
case 'firstpost':
// More relative weight for the title, also search the body
$this->sphinx->SetFieldWeights(array("title" => 5, "data" => 1));
// 1 is first_post, 0 is not first post
$this->sphinx->SetFilter('topic_first_post', array(1));
break;
default:
// More relative weight for the title, also search the body
$this->sphinx->SetFieldWeights(array("title" => 5, "data" => 1));
break;
}
if (sizeof($author_ary))
{
$this->sphinx->SetFilter('poster_id', $author_ary);
}
if (sizeof($ex_fid_ary))
{
// All forums that a user is allowed to access
$fid_ary = array_unique(array_intersect(array_keys($this->auth->acl_getf('f_read', true)), array_keys($this->auth->acl_getf('f_search', true))));
// All forums that the user wants to and can search in
$search_forums = array_diff($fid_ary, $ex_fid_ary);
if (sizeof($search_forums))
{
$this->sphinx->SetFilter('forum_id', $search_forums);
}
}
$this->sphinx->SetFilter('deleted', array(0));
$this->sphinx->SetLimits($start, (int) $per_page, SPHINX_MAX_MATCHES);
$result = $this->sphinx->Query($search_query_prefix . str_replace('&quot;', '"', $this->search_query), $this->indexes);
// Could be connection to localhost:9312 failed (errno=111,
// msg=Connection refused) during rotate, retry if so
$retries = SPHINX_CONNECT_RETRIES;
while (!$result && (strpos($this->sphinx->GetLastError(), "errno=111,") !== false) && $retries--)
{
usleep(SPHINX_CONNECT_WAIT_TIME);
$result = $this->sphinx->Query($search_query_prefix . str_replace('&quot;', '"', $this->search_query), $this->indexes);
}
if ($this->sphinx->GetLastError())
{
add_log('critical', 'LOG_SPHINX_ERROR', $this->sphinx->GetLastError());
if ($this->auth->acl_get('a_'))
{
trigger_error($this->user->lang('SPHINX_SEARCH_FAILED', $this->sphinx->GetLastError()));
}
else
{
trigger_error($this->user->lang('SPHINX_SEARCH_FAILED_LOG'));
}
}
$id_ary = array();
if (isset($result['matches']))
{
if ($type == 'posts')
{
$id_ary = array_keys($result['matches']);
}
else
{
foreach ($result['matches'] as $key => $value)
{
$id_ary[] = $value['attrs']['topic_id'];
}
}
}
else
{
return false;
}
$result_count = $result['total_found'];
$id_ary = array_slice($id_ary, 0, (int) $per_page);
return $result_count;
}
/**
* Performs a search on an author's posts without caring about message contents. Depends on display specific params
*
* @param string $type contains either posts or topics depending on what should be searched for
* @param boolean $firstpost_only if true, only topic starting posts will be considered
* @param array $sort_by_sql contains SQL code for the ORDER BY part of a query
* @param string $sort_key is the key of $sort_by_sql for the selected sorting
* @param string $sort_dir is either a or d representing ASC and DESC
* @param string $sort_days specifies the maximum amount of days a post may be old
* @param array $ex_fid_ary specifies an array of forum ids which should not be searched
* @param array $m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
* @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
* @param array $author_ary an array of author ids
* @param string $author_name specifies the author match, when ANONYMOUS is also a search-match
* @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
* @return boolean|int total number of results
*/
public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
$this->search_query = '';
$this->sphinx->SetMatchMode(SPH_MATCH_FULLSCAN);
$fields = ($firstpost_only) ? 'firstpost' : 'all';
$terms = 'all';
return $this->keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, $id_ary, $start, $per_page);
}
/**
* Updates wordlist and wordmatch tables when a message is posted or changed
*
* @param string $mode Contains the post mode: edit, post, reply, quote
* @param int $post_id The id of the post which is modified/created
* @param string &$message New or updated post content
* @param string &$subject New or updated post subject
* @param int $poster_id Post author's user id
* @param int $forum_id The id of the forum in which the post is located
*/
public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
{
if ($mode == 'edit')
{
$this->sphinx->UpdateAttributes($this->indexes, array('forum_id', 'poster_id'), array((int)$post_id => array((int)$forum_id, (int)$poster_id)));
}
else if ($mode != 'post' && $post_id)
{
// Update topic_last_post_time for full topic
$sql_array = array(
'SELECT' => 'p1.post_id',
'FROM' => array(
POSTS_TABLE => 'p1',
),
'LEFT_JOIN' => array(array(
'FROM' => array(
POSTS_TABLE => 'p2'
),
'ON' => 'p1.topic_id = p2.topic_id',
)),
);
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query($sql);
$post_updates = array();
$post_time = time();
while ($row = $this->db->sql_fetchrow($result))
{
$post_updates[(int)$row['post_id']] = array($post_time);
}
$this->db->sql_freeresult($result);
if (sizeof($post_updates))
{
$this->sphinx->UpdateAttributes($this->indexes, array('topic_last_post_time'), $post_updates);
}
}
}
/**
* Delete a post from the index after it was deleted
*/
public function index_remove($post_ids, $author_ids, $forum_ids)
{
$values = array();
foreach ($post_ids as $post_id)
{
$values[$post_id] = array(1);
}
$this->sphinx->UpdateAttributes($this->indexes, array('deleted'), $values);
}
/**
* Nothing needs to be destroyed
*/
public function tidy($create = false)
{
set_config('search_last_gc', time(), true);
}
/**
* Create sphinx table
*
* @return string|bool error string is returned incase of errors otherwise false
*/
public function create_index($acp_module, $u_action)
{
if (!$this->index_created())
{
$table_data = array(
'COLUMNS' => array(
'counter_id' => array('UINT', 0),
'max_doc_id' => array('UINT', 0),
),
'PRIMARY_KEY' => 'counter_id',
);
$this->db_tools->sql_create_table(SPHINX_TABLE, $table_data);
$sql = 'TRUNCATE TABLE ' . SPHINX_TABLE;
$this->db->sql_query($sql);
$data = array(
'counter_id' => '1',
'max_doc_id' => '0',
);
$sql = 'INSERT INTO ' . SPHINX_TABLE . ' ' . $this->db->sql_build_array('INSERT', $data);
$this->db->sql_query($sql);
}
return false;
}
/**
* Drop sphinx table
*
* @return string|bool error string is returned incase of errors otherwise false
*/
public function delete_index($acp_module, $u_action)
{
if (!$this->index_created())
{
return false;
}
$this->db_tools->sql_table_drop(SPHINX_TABLE);
return false;
}
/**
* Returns true if the sphinx table was created
*
* @return bool true if sphinx table was created
*/
public function index_created($allow_new_files = true)
{
$created = false;
if ($this->db_tools->sql_table_exists(SPHINX_TABLE))
{
$created = true;
}
return $created;
}
/**
* Returns an associative array containing information about the indexes
*
* @return string|bool Language string of error false otherwise
*/
public function index_stats()
{
if (empty($this->stats))
{
$this->get_stats();
}
return array(
$this->user->lang['FULLTEXT_SPHINX_MAIN_POSTS'] => ($this->index_created()) ? $this->stats['main_posts'] : 0,
$this->user->lang['FULLTEXT_SPHINX_DELTA_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] - $this->stats['main_posts'] : 0,
$this->user->lang['FULLTEXT_MYSQL_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0,
);
}
/**
* Collects stats that can be displayed on the index maintenance page
*/
protected function get_stats()
{
if ($this->index_created())
{
$sql = 'SELECT COUNT(post_id) as total_posts
FROM ' . POSTS_TABLE;
$result = $this->db->sql_query($sql);
$this->stats['total_posts'] = (int) $this->db->sql_fetchfield('total_posts');
$this->db->sql_freeresult($result);
$sql = 'SELECT COUNT(p.post_id) as main_posts
FROM ' . POSTS_TABLE . ' p, ' . SPHINX_TABLE . ' m
WHERE p.post_id <= m.max_doc_id
AND m.counter_id = 1';
$result = $this->db->sql_query($sql);
$this->stats['main_posts'] = (int) $this->db->sql_fetchfield('main_posts');
$this->db->sql_freeresult($result);
}
}
/**
* Returns a list of options for the ACP to display
*
* @return associative array containing template and config variables
*/
public function acp()
{
$config_vars = array(
'fulltext_sphinx_data_path' => 'string',
'fulltext_sphinx_host' => 'string',
'fulltext_sphinx_port' => 'string',
'fulltext_sphinx_indexer_mem_limit' => 'int',
);
$tpl = '
<span class="error">' . $this->user->lang['FULLTEXT_SPHINX_CONFIGURE']. '</span>
<dl>
<dt><label for="fulltext_sphinx_data_path">' . $this->user->lang['FULLTEXT_SPHINX_DATA_PATH'] . ':</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_DATA_PATH_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_sphinx_data_path" type="text" size="40" maxlength="255" name="config[fulltext_sphinx_data_path]" value="' . $this->config['fulltext_sphinx_data_path'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_sphinx_host">' . $this->user->lang['FULLTEXT_SPHINX_HOST'] . ':</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_HOST_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_sphinx_host" type="text" size="40" maxlength="255" name="config[fulltext_sphinx_host]" value="' . $this->config['fulltext_sphinx_host'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_sphinx_port">' . $this->user->lang['FULLTEXT_SPHINX_PORT'] . ':</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_PORT_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_sphinx_port" type="text" size="4" maxlength="10" name="config[fulltext_sphinx_port]" value="' . $this->config['fulltext_sphinx_port'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_sphinx_indexer_mem_limit">' . $this->user->lang['FULLTEXT_SPHINX_INDEXER_MEM_LIMIT'] . ':</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_INDEXER_MEM_LIMIT_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_sphinx_indexer_mem_limit" type="text" size="4" maxlength="10" name="config[fulltext_sphinx_indexer_mem_limit]" value="' . $this->config['fulltext_sphinx_indexer_mem_limit'] . '" />' . $this->user->lang['MIB'] . '</dd>
</dl>
<dl>
<dt><label for="fulltext_sphinx_config_file">' . $this->user->lang['FULLTEXT_SPHINX_CONFIG_FILE'] . ':</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_CONFIG_FILE_EXPLAIN'] . '</dt>
<dd>' . (($this->config_generate()) ? '<textarea readonly="readonly" rows="6">' . $this->config_file_data . '</textarea>' : $this->config_file_data) . '</dd>
<dl>
';
// These are fields required in the config table
return array(
'tpl' => $tpl,
'config' => $config_vars
);
}
}

View file

@ -0,0 +1,288 @@
<?php
/**
*
* @package search
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* phpbb_search_sphinx_config
* An object representing the sphinx configuration
* Can read it from file and write it back out after modification
* @package search
*/
class phpbb_search_sphinx_config
{
private $sections = array();
/**
* Constructor which optionally loads data from a variable
*
* @param string $config_data Variable containing the sphinx configuration data
*
* @access public
*/
function __construct($config_data)
{
if ($config_data != '')
{
$this->read($config_data);
}
}
/**
* Get a section object by its name
*
* @param string $name The name of the section that shall be returned
* @return phpbb_search_sphinx_config_section The section object or null if none was found
*
* @access public
*/
function get_section_by_name($name)
{
for ($i = 0, $size = sizeof($this->sections); $i < $size; $i++)
{
// Make sure this is really a section object and not a comment
if (($this->sections[$i] instanceof phpbb_search_sphinx_config_section) && $this->sections[$i]->get_name() == $name)
{
return $this->sections[$i];
}
}
}
/**
* Appends a new empty section to the end of the config
*
* @param string $name The name for the new section
* @return phpbb_search_sphinx_config_section The newly created section object
*
* @access public
*/
function add_section($name)
{
$this->sections[] = new phpbb_search_sphinx_config_section($name, '');
return $this->sections[sizeof($this->sections) - 1];
}
/**
* Reads the config file data
*
* @param string $config_data The config file data
*
* @access private
*/
function read($config_data)
{
$this->sections = array();
$section = null;
$found_opening_bracket = false;
$in_value = false;
foreach ($config_data as $i => $line)
{
// If the value of a variable continues to the next line because the line
// break was escaped then we don't trim leading space but treat it as a part of the value
if ($in_value)
{
$line = rtrim($line);
}
else
{
$line = trim($line);
}
// If we're not inside a section look for one
if (!$section)
{
// Add empty lines and comments as comment objects to the section list
// that way they're not deleted when reassembling the file from the sections
if (!$line || $line[0] == '#')
{
$this->sections[] = new phpbb_search_sphinx_config_comment($config_file[$i]);
continue;
}
else
{
// Otherwise we scan the line reading the section name until we find
// an opening curly bracket or a comment
$section_name = '';
$section_name_comment = '';
$found_opening_bracket = false;
for ($j = 0, $length = strlen($line); $j < $length; $j++)
{
if ($line[$j] == '#')
{
$section_name_comment = substr($line, $j);
break;
}
if ($found_opening_bracket)
{
continue;
}
if ($line[$j] == '{')
{
$found_opening_bracket = true;
continue;
}
$section_name .= $line[$j];
}
// And then we create the new section object
$section_name = trim($section_name);
$section = new phpbb_search_sphinx_config_section($section_name, $section_name_comment);
}
}
else
{
// If we're looking for variables inside a section
$skip_first = false;
// If we're not in a value continuing over the line feed
if (!$in_value)
{
// Then add empty lines and comments as comment objects to the variable list
// of this section so they're not deleted on reassembly
if (!$line || $line[0] == '#')
{
$section->add_variable(new phpbb_search_sphinx_config_comment($config_file[$i]));
continue;
}
// As long as we haven't yet actually found an opening bracket for this section
// we treat everything as comments so it's not deleted either
if (!$found_opening_bracket)
{
if ($line[0] == '{')
{
$skip_first = true;
$line = substr($line, 1);
$found_opening_bracket = true;
}
else
{
$section->add_variable(new phpbb_search_sphinx_config_comment($config_file[$i]));
continue;
}
}
}
// If we did not find a comment in this line or still add to the previous
// line's value ...
if ($line || $in_value)
{
if (!$in_value)
{
$name = '';
$value = '';
$comment = '';
$found_assignment = false;
}
$in_value = false;
$end_section = false;
/* ... then we should prase this line char by char:
- first there's the variable name
- then an equal sign
- the variable value
- possibly a backslash before the linefeed in this case we need to continue
parsing the value in the next line
- a # indicating that the rest of the line is a comment
- a closing curly bracket indicating the end of this section*/
for ($j = 0, $length = strlen($line); $j < $length; $j++)
{
if ($line[$j] == '#')
{
$comment = substr($line, $j);
break;
}
else if ($line[$j] == '}')
{
$comment = substr($line, $j + 1);
$end_section = true;
break;
}
else if (!$found_assignment)
{
if ($line[$j] == '=')
{
$found_assignment = true;
}
else
{
$name .= $line[$j];
}
}
else
{
if ($line[$j] == '\\' && $j == $length - 1)
{
$value .= "\n";
$in_value = true;
// Go to the next line and keep processing the value in there
continue 2;
}
$value .= $line[$j];
}
}
// If a name and an equal sign were found then we have append a
// new variable object to the section
if ($name && $found_assignment)
{
$section->add_variable(new phpbb_search_sphinx_config_variable(trim($name), trim($value), ($end_section) ? '' : $comment));
continue;
}
/* If we found a closing curly bracket this section has been completed
and we can append it to the section list and continue with looking for
the next section */
if ($end_section)
{
$section->set_end_comment($comment);
$this->sections[] = $section;
$section = null;
continue;
}
}
// If we did not find anything meaningful up to here, then just treat it
// as a comment
$comment = ($skip_first) ? "\t" . substr(ltrim($config_file[$i]), 1) : $config_file[$i];
$section->add_variable(new phpbb_search_sphinx_config_comment($comment));
}
}
}
/**
* Returns the config data
*
* @return string $data The config data that is generated
*
* @access public
*/
function get_data()
{
$data = "";
foreach ($this->sections as $section)
{
$data .= $section->to_string();
}
return $data;
}
}

View file

@ -0,0 +1,49 @@
<?php
/**
*
* @package search
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* phpbb_search_sphinx_config_comment
* Represents a comment inside the sphinx configuration
*/
class phpbb_search_sphinx_config_comment
{
private $exact_string;
/**
* Create a new comment
*
* @param string $exact_string The content of the comment including newlines, leading whitespace, etc.
*
* @access public
*/
function __construct($exact_string)
{
$this->exact_string = $exact_string;
}
/**
* Simply returns the comment as it was created
*
* @return string The exact string that was specified in the constructor
*
* @access public
*/
function to_string()
{
return $this->exact_string;
}
}

View file

@ -0,0 +1,162 @@
<?php
/**
*
* @package search
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* phpbb_search_sphinx_config_section
* Represents a single section inside the sphinx configuration
*/
class phpbb_search_sphinx_config_section
{
private $name;
private $comment;
private $end_comment;
private $variables = array();
/**
* Construct a new section
*
* @param string $name Name of the section
* @param string $comment Comment that should be appended after the name in the
* textual format.
*
* @access public
*/
function __construct($name, $comment)
{
$this->name = $name;
$this->comment = $comment;
$this->end_comment = '';
}
/**
* Add a variable object to the list of variables in this section
*
* @param phpbb_search_sphinx_config_variable $variable The variable object
*
* @access public
*/
function add_variable($variable)
{
$this->variables[] = $variable;
}
/**
* Adds a comment after the closing bracket in the textual representation
*
* @param string $end_comment
*
* @access public
*/
function set_end_comment($end_comment)
{
$this->end_comment = $end_comment;
}
/**
* Getter for the name of this section
*
* @return string Section's name
*
* @access public
*/
function get_name()
{
return $this->name;
}
/**
* Get a variable object by its name
*
* @param string $name The name of the variable that shall be returned
* @return phpbb_search_sphinx_config_section The first variable object from this section with the
* given name or null if none was found
*
* @access public
*/
function get_variable_by_name($name)
{
for ($i = 0, $size = sizeof($this->variables); $i < $size; $i++)
{
// Make sure this is a variable object and not a comment
if (($this->variables[$i] instanceof phpbb_search_sphinx_config_variable) && $this->variables[$i]->get_name() == $name)
{
return $this->variables[$i];
}
}
}
/**
* Deletes all variables with the given name
*
* @param string $name The name of the variable objects that are supposed to be removed
*
* @access public
*/
function delete_variables_by_name($name)
{
for ($i = 0, $size = sizeof($this->variables); $i < $size; $i++)
{
// Make sure this is a variable object and not a comment
if (($this->variables[$i] instanceof phpbb_search_sphinx_config_variable) && $this->variables[$i]->get_name() == $name)
{
array_splice($this->variables, $i, 1);
$i--;
}
}
}
/**
* Create a new variable object and append it to the variable list of this section
*
* @param string $name The name for the new variable
* @param string $value The value for the new variable
* @return phpbb_search_sphinx_config_variable Variable object that was created
*
* @access public
*/
function create_variable($name, $value)
{
$this->variables[] = new phpbb_search_sphinx_config_variable($name, $value, '');
return $this->variables[sizeof($this->variables) - 1];
}
/**
* Turns this object into a string which can be written to a config file
*
* @return string Config data in textual form, parsable for sphinx
*
* @access public
*/
function to_string()
{
$content = $this->name . ' ' . $this->comment . "\n{\n";
// Make sure we don't get too many newlines after the opening bracket
while (trim($this->variables[0]->to_string()) == '')
{
array_shift($this->variables);
}
foreach ($this->variables as $variable)
{
$content .= $variable->to_string();
}
$content .= '}' . $this->end_comment . "\n";
return $content;
}
}

View file

@ -0,0 +1,80 @@
<?php
/**
*
* @package search
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* phpbb_search_sphinx_config_variable
* Represents a single variable inside the sphinx configuration
*/
class phpbb_search_sphinx_config_variable
{
private $name;
private $value;
private $comment;
/**
* Constructs a new variable object
*
* @param string $name Name of the variable
* @param string $value Value of the variable
* @param string $comment Optional comment after the variable in the
* config file
*
* @access public
*/
function __construct($name, $value, $comment)
{
$this->name = $name;
$this->value = $value;
$this->comment = $comment;
}
/**
* Getter for the variable's name
*
* @return string The variable object's name
*
* @access public
*/
function get_name()
{
return $this->name;
}
/**
* Allows changing the variable's value
*
* @param string $value New value for this variable
*
* @access public
*/
function set_value($value)
{
$this->value = $value;
}
/**
* Turns this object into a string readable by sphinx
*
* @return string Config data in textual form
*
* @access public
*/
function to_string()
{
return "\t" . $this->name . ' = ' . str_replace("\n", "\\\n", $this->value) . ' ' . $this->comment . "\n";
}
}

1712
phpBB/includes/sphinxapi.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -139,7 +139,7 @@ class phpbb_template
*/
public function display($handle)
{
$result = $this->call_hook($handle);
$result = $this->call_hook($handle, __FUNCTION__);
if ($result !== false)
{
return $result[0];
@ -174,16 +174,17 @@ class phpbb_template
* Calls hook if any is defined.
*
* @param string $handle Template handle being displayed.
* @param string $method Method name of the caller.
*/
private function call_hook($handle)
private function call_hook($handle, $method)
{
global $phpbb_hook;
if (!empty($phpbb_hook) && $phpbb_hook->call_hook(array(__CLASS__, __FUNCTION__), $handle, $this))
if (!empty($phpbb_hook) && $phpbb_hook->call_hook(array(__CLASS__, $method), $handle, $this))
{
if ($phpbb_hook->hook_return(array(__CLASS__, __FUNCTION__)))
if ($phpbb_hook->hook_return(array(__CLASS__, $method)))
{
$result = $phpbb_hook->hook_return_result(array(__CLASS__, __FUNCTION__));
$result = $phpbb_hook->hook_return_result(array(__CLASS__, $method));
return array($result);
}
}

View file

@ -69,17 +69,16 @@ class ucp_main
// Get cleaned up list... return only those forums having the f_read permission
$forum_ary = $auth->acl_getf('f_read', true);
$forum_ary = array_unique(array_keys($forum_ary));
$sql = "SELECT t.* $sql_select
FROM $sql_from
WHERE t.topic_type = " . POST_GLOBAL . '
AND ' . $db->sql_in_set('t.forum_id', $forum_ary) . '
ORDER BY t.topic_last_post_time DESC';
$topic_list = $rowset = array();
// If the user can't see any forums, he can't read any posts because fid of 0 is invalid
if (!empty($forum_ary))
{
$sql = "SELECT t.* $sql_select
FROM $sql_from
WHERE t.topic_type = " . POST_GLOBAL . '
AND ' . $db->sql_in_set('t.forum_id', $forum_ary) . '
ORDER BY t.topic_last_post_time DESC';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
@ -671,7 +670,7 @@ class ucp_main
if ($topics_count)
{
phpbb_generate_template_pagination($template, $this->u_action, 'pagination', 'start', $topics_count, $config['topics_per_page'], $start);
$template->assign_vars(array(
'PAGE_NUMBER' => phpbb_on_page($template, $user, $this->u_action, $topics_count, $config['topics_per_page'], $start),
'TOTAL_TOPICS' => $user->lang('VIEW_FORUM_TOPICS', (int) $topics_count),
@ -837,7 +836,7 @@ class ucp_main
'U_VIEW_TOPIC' => $view_topic_url,
'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id),
));
phpbb_generate_template_pagination($template, append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . "&amp;t=$topic_id"), 'topicrow.pagination', 'start', $replies + 1, $config['posts_per_page'], 1, true, true);
}
}

View file

@ -21,7 +21,7 @@ if (!defined('IN_PHPBB'))
function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
{
global $user, $template, $auth, $db, $cache;
global $phpbb_root_path, $request, $phpEx, $config;
global $phpbb_root_path, $request, $phpEx, $config, $phpbb_dispatcher;
$user->add_lang(array('viewtopic', 'memberlist'));
@ -204,7 +204,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
}
}
$template->assign_vars(array(
$msg_data = array(
'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']),
'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']),
'MESSAGE_AUTHOR' => get_username_string('username', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']),
@ -265,9 +265,28 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
'S_CUSTOM_FIELDS' => (!empty($cp_row['row'])) ? true : false,
'U_PRINT_PM' => ($config['print_pm'] && $auth->acl_get('u_pm_printpm')) ? "$url&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] . "&amp;view=print" : '',
'U_FORWARD_PM' => ($config['forward_pm'] && $auth->acl_get('u_sendpm') && $auth->acl_get('u_pm_forward')) ? "$url&amp;mode=compose&amp;action=forward&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '')
'U_FORWARD_PM' => ($config['forward_pm'] && $auth->acl_get('u_sendpm') && $auth->acl_get('u_pm_forward')) ? "$url&amp;mode=compose&amp;action=forward&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
);
/**
* Modify pm and sender data before it is assigned to the template
*
* @event core.ucp_pm_view_messsage
* @var mixed id Active module category (can be int or string)
* @var string mode Active module
* @var int folder_id ID of the folder the message is in
* @var int msg_id ID of the private message
* var array folder Array with data of user's message folders
* @var array message_row Array with message data
* @var array cp_row Array with senders custom profile field data
* @var array msg_data Template array with message data
* @since 3.1-A1
*/
$vars = array('id', 'mode', 'folder_id', 'msg_id', 'folder', 'message_row', 'cp_row', 'msg_data');
extract($phpbb_dispatcher->trigger_event('core.ucp_pm_view_messsage', compact($vars)));
$template->assign_vars($msg_data);
// Display the custom profile fields
if (!empty($cp_row['row']))
{

View file

@ -25,7 +25,7 @@ class ucp_zebra
function main($id, $mode)
{
global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx, $request;
global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx, $request, $phpbb_dispatcher;
$submit = (isset($_POST['submit']) || isset($_GET['add']) || isset($_GET['remove'])) ? true : false;
$s_hidden_fields = '';
@ -54,9 +54,22 @@ class ucp_zebra
// Remove users
if (!empty($data['usernames']))
{
$user_ids = $data['usernames'];
/**
* Remove users from friends/foes
*
* @event core.ucp_remove_zebra
* @var string mode Zebra type: friends|foes
* @var array user_ids User ids we remove
* @since 3.1-A1
*/
$vars = array('user_ids');
extract($phpbb_dispatcher->trigger_event('core.ucp_remove_zebra', compact($vars)));
$sql = 'DELETE FROM ' . ZEBRA_TABLE . '
WHERE user_id = ' . $user->data['user_id'] . '
AND ' . $db->sql_in_set('zebra_id', $data['usernames']);
AND ' . $db->sql_in_set('zebra_id', $user_ids);
$db->sql_query($sql);
$updated = true;
@ -186,6 +199,19 @@ class ucp_zebra
);
}
/**
* Add users to friends/foes
*
* @event core.ucp_add_zebra
* @var string mode Zebra type:
* friends|foes
* @var array sql_ary Array of
* entries we add
* @since 3.1-A1
*/
$vars = array('mode', 'sql_ary');
extract($phpbb_dispatcher->trigger_event('core.ucp_add_zebra', compact($vars)));
$db->sql_multi_insert(ZEBRA_TABLE, $sql_ary);
$updated = true;

View file

@ -76,18 +76,18 @@ class phpbb_user extends phpbb_session
function setup($lang_set = false, $style_id = false)
{
global $db, $phpbb_style, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache;
global $phpbb_dispatcher;
if ($this->data['user_id'] != ANONYMOUS)
{
$this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
$this->date_format = $this->data['user_dateformat'];
$user_lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
$user_date_format = $this->data['user_dateformat'];
$user_timezone = $this->data['user_timezone'];
}
else
{
$this->lang_name = basename($config['default_lang']);
$this->date_format = $config['default_dateformat'];
$user_lang_name = basename($config['default_lang']);
$user_date_format = $config['default_dateformat'];
$user_timezone = $config['board_timezone'];
/**
@ -107,7 +107,7 @@ class phpbb_user extends phpbb_session
if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx"))
{
$this->lang_name = $config['default_lang'] = $accept_lang;
$user_lang_name = $config['default_lang'] = $accept_lang;
break;
}
else
@ -118,7 +118,7 @@ class phpbb_user extends phpbb_session
if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx"))
{
$this->lang_name = $config['default_lang'] = $accept_lang;
$user_lang_name = $config['default_lang'] = $accept_lang;
break;
}
}
@ -127,6 +127,28 @@ class phpbb_user extends phpbb_session
*/
}
$user_data = $this->data;
/**
* Event to load language files and modify user data on every page
*
* @event core.user_setup
* @var array user_data Array with user's data row
* @var string user_lang_name Basename of the user's langauge
* @var string user_date_format User's date/time format
* @var string user_timezone User's timezone, should be one of
* http://www.php.net/manual/en/timezones.php
* @var mixed lang_set String or array of language files
* @var mixed style_id Style we are going to display
* @since 3.1-A1
*/
$vars = array('user_data', 'user_lang_name', 'user_date_format', 'user_timezone', 'lang_set', 'style_id');
extract($phpbb_dispatcher->trigger_event('core.user_setup', compact($vars)));
$this->data = $user_data;
$this->lang_name = $user_lang_name;
$this->date_format = $user_date_format;
try
{
$this->timezone = new DateTimeZone($user_timezone);

View file

@ -171,8 +171,20 @@ $template->assign_vars(array(
'U_MCP' => ($auth->acl_get('m_') || $auth->acl_getf_global('m_')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=front', true, $user->session_id) : '')
);
$page_title = $user->lang['INDEX'];
/**
* You can use this event to modify the page title and load data for the index
*
* @event core.index_modify_page_title
* @var string page_title Title of the index page
* @since 3.1-A1
*/
$vars = array('page_title');
extract($phpbb_dispatcher->trigger_event('core.index_modify_page_title', compact($vars)));
// Output page
page_header($user->lang['INDEX']);
page_header($page_title);
$template->set_filenames(array(
'body' => 'index_body.html')

View file

@ -1079,6 +1079,8 @@ function database_update_info()
),
),
),
// No changes from 3.0.11-RC2 to 3.0.11
'3.0.11-RC2' => array(),
/** @todo DROP LOGIN_ATTEMPT_TABLE.attempt_id in 3.0.12-RC1 */
@ -2222,6 +2224,10 @@ function change_database_data(&$no_updates, $version)
case '3.0.11-RC1':
break;
// No changes from 3.0.11-RC2 to 3.0.11
case '3.0.11-RC2':
break;
// Changes from 3.1.0-dev to 3.1.0-A1
case '3.1.0-dev':
@ -2277,6 +2283,16 @@ function change_database_data(&$no_updates, $version)
set_config('fulltext_postgres_max_word_len', 254);
}
if (!isset($config['fulltext_sphinx_stopwords']))
{
set_config('fulltext_sphinx_stopwords', 0);
}
if (!isset($config['fulltext_sphinx_indexer_mem_limit']))
{
set_config('fulltext_sphinx_indexer_mem_limit', 512);
}
if (!isset($config['load_jquery_cdn']))
{
set_config('load_jquery_cdn', 0);

View file

@ -569,7 +569,7 @@ class install_convert extends module
*/
function convert_data($sub)
{
global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache;
global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache, $auth;
global $convert, $convert_row, $message_parser, $skip_rows, $language;
global $request;
@ -750,7 +750,7 @@ class install_convert extends module
}
$error = false;
$convert->fulltext_search = new $search_type($error);
$convert->fulltext_search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
if ($error)
{

View file

@ -1427,7 +1427,7 @@ class install_install extends module
*/
function build_search_index($mode, $sub)
{
global $db, $lang, $phpbb_root_path, $phpEx, $config;
global $db, $lang, $phpbb_root_path, $phpEx, $config, $auth, $user;
// Obtain any submitted data
$data = $this->get_submitted_data();
@ -1463,7 +1463,7 @@ class install_install extends module
set_config_count(null, null, null, $config);
$error = false;
$search = new phpbb_search_fulltext_native($error);
$search = new phpbb_search_fulltext_native($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
$sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id
FROM ' . POSTS_TABLE;

View file

@ -349,7 +349,7 @@ class install_update extends module
// We are directly within an update. To make sure our update list is correct we check its status.
$update_list = ($request->variable('check_again', false, false, phpbb_request_interface::POST)) ? false : $cache->get('_update_list');
$modified = ($update_list !== false) ? @filemtime($cache->cache_dir . 'data_update_list.' . $phpEx) : 0;
$modified = ($update_list !== false) ? @filemtime($cache->get_driver()->cache_dir . 'data_update_list.' . $phpEx) : 0;
// Make sure the list is up-to-date
if ($update_list !== false)

View file

@ -127,6 +127,8 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_mi
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_max_word_len', '254');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_min_word_len', '4');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_ts_name', 'simple');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_indexer_mem_limit', '512');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_stopwords', '0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('gzip_compress', '0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('hot_threshold', '25');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('icons_path', 'images/icons');

View file

@ -690,6 +690,7 @@ $lang = array_merge($lang, array(
'LOG_SEARCH_INDEX_CREATED' => '<strong>Created search index for</strong><br />» %s',
'LOG_SEARCH_INDEX_REMOVED' => '<strong>Removed search index for</strong><br />» %s',
'LOG_SPHINX_ERROR' => '<strong>Sphinx Error</strong><br />» %s',
'LOG_STYLE_ADD' => '<strong>Added new style</strong><br />» %s',
'LOG_STYLE_DELETE' => '<strong>Deleted style</strong><br />» %s',
'LOG_STYLE_EDIT_DETAILS' => '<strong>Edited style</strong><br />» %s',

View file

@ -69,6 +69,22 @@ $lang = array_merge($lang, array(
'FULLTEXT_POSTGRES_MIN_WORD_LEN_EXPLAIN' => 'Words with at least this many characters will be included in the query to the database.',
'FULLTEXT_POSTGRES_MAX_WORD_LEN_EXPLAIN' => 'Words with no more than this many characters will be included in the query to the database.',
'FULLTEXT_SPHINX_CONFIGURE' => 'Configure the following settings to generate sphinx config file',
'FULLTEXT_SPHINX_DATA_PATH' => 'Path to data directory',
'FULLTEXT_SPHINX_DATA_PATH_EXPLAIN' => 'It will be used to store the indexes and log files. You should create this directory outside the web accessible directories. (should have a trailing slash)',
'FULLTEXT_SPHINX_DELTA_POSTS' => 'Number of posts in frequently updated delta index',
'FULLTEXT_SPHINX_HOST' => 'Sphinx search daemon host',
'FULLTEXT_SPHINX_HOST_EXPLAIN' => 'Host on which the sphinx search daemon (searchd) listens. Leave empty to use the default localhost',
'FULLTEXT_SPHINX_INDEXER_MEM_LIMIT' => 'Indexer memory limit',
'FULLTEXT_SPHINX_INDEXER_MEM_LIMIT_EXPLAIN' => 'This number should at all times be lower than the RAM available on your machine. If you experience periodic performance problems this might be due to the indexer consuming too many resources. It might help to lower the amount of memory available to the indexer.',
'FULLTEXT_SPHINX_MAIN_POSTS' => 'Number of posts in main index',
'FULLTEXT_SPHINX_PORT' => 'Sphinx search daemon port',
'FULLTEXT_SPHINX_PORT_EXPLAIN' => 'Port on which the sphinx search daemon (searchd) listens. Leave empty to use the default Sphinx API port 9312',
'FULLTEXT_SPHINX_WRONG_DATABASE' => 'The sphinx search for phpBB supports MySQL and PostgreSQL only.',
'FULLTEXT_SPHINX_CONFIG_FILE' => 'Sphinx config file',
'FULLTEXT_SPHINX_CONFIG_FILE_EXPLAIN' => 'The generated content of the sphinx config file. This data needs to be pasted into the sphinx.conf which is used by sphinx search daemon.',
'FULLTEXT_SPHINX_NO_CONFIG_DATA' => 'The sphinx data and config directory paths are not defined. Please define them to generate the config file.',
'GENERAL_SEARCH_SETTINGS' => 'General search settings',
'GO_TO_SEARCH_INDEX' => 'Go to search index page',

View file

@ -105,6 +105,8 @@ $lang = array_merge($lang, array(
'SORT_FORUM' => 'Forum',
'SORT_POST_SUBJECT' => 'Post subject',
'SORT_TIME' => 'Post time',
'SPHINX_SEARCH_FAILED' => 'Search failed: %s',
'SPHINX_SEARCH_FAILED_LOG' => 'Sorry, search could not be performed. More information about this failure has been logged in the error log.',
'TOO_FEW_AUTHOR_CHARS' => array(
1 => 'You must specify at least %d character of the authors name.',

View file

@ -575,6 +575,26 @@ switch ($mode)
unset($module);
}
/**
* Modify user data before we display the profile
*
* @event core.memberlist_view_profile
* @var array member Title of the index page
* @var bool user_notes_enabled Is the mcp user notes module
* enabled?
* @var bool warn_user_enabled Is the mcp warnings module
* enabled?
* @var bool zebra_enabled Is the ucp zebra module
* enabled?
* @var bool friends_enabled Is the ucp friends module
* enabled?
* @var bool foes_enabled Is the ucp foes module
* enabled?
* @since 3.1-A1
*/
$vars = array('member', 'user_notes_enabled', 'warn_user_enabled', 'zebra_enabled', 'friends_enabled', 'foes_enabled');
extract($phpbb_dispatcher->trigger_event('core.memberlist_view_profile', compact($vars)));
$template->assign_vars(show_profile($member, $user_notes_enabled, $warn_user_enabled));
// Custom Profile Fields
@ -1631,7 +1651,7 @@ page_footer();
*/
function show_profile($data, $user_notes_enabled = false, $warn_user_enabled = false)
{
global $config, $auth, $template, $user, $phpEx, $phpbb_root_path;
global $config, $auth, $template, $user, $phpEx, $phpbb_root_path, $phpbb_dispatcher;
$username = $data['username'];
$user_id = $data['user_id'];
@ -1693,7 +1713,7 @@ function show_profile($data, $user_notes_enabled = false, $warn_user_enabled = f
}
// Dump it out to the template
return array(
$template_data = array(
'AGE' => $age,
'RANK_TITLE' => $rank_title,
'JOINED' => $user->format_date($data['user_regdate']),
@ -1741,6 +1761,19 @@ function show_profile($data, $user_notes_enabled = false, $warn_user_enabled = f
'L_VIEWING_PROFILE' => sprintf($user->lang['VIEWING_PROFILE'], $username),
);
/**
* Preparing a user's data before displaying it in profile and memberlist
*
* @event core.memberlist_prepare_profile_data
* @var array data Array with user's data
* @var array template_data Template array with user's data
* @since 3.1-A1
*/
$vars = array('data', 'template_data');
extract($phpbb_dispatcher->trigger_event('core.memberlist_prepare_profile_data', compact($vars)));
return $template_data;
}
function _sort_last_active($first, $second)

View file

@ -280,7 +280,7 @@ if ($keywords || $author || $author_id || $search_id || $submit)
}
// We do some additional checks in the module to ensure it can actually be utilised
$error = false;
$search = new $search_type($error);
$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
if ($error)
{

View file

@ -6,7 +6,7 @@
<option value="">{L_SELECT_CURRENT_TIME}</option>
{S_TZ_DATE_OPTIONS}
</select>
<input id="tz_select_date_suggest" class="inputbox button2" style="display: none; width: 150px !important;" data-is-registration="<!-- IF S_REGISTRATION -->true<!-- ELSE -->false<!-- ENDIF -->" data-l-suggestion="{L_TIMEZONE_DATE_SUGGESTION}" value="fuu" />
<input type="button" id="tz_select_date_suggest" class="button2" style="display: none;" data-is-registration="<!-- IF S_REGISTRATION -->true<!-- ELSE -->false<!-- ENDIF -->" data-l-suggestion="{L_TIMEZONE_DATE_SUGGESTION}" value="{L_TIMEZONE_DATE_SUGGESTION}" />
</dd>
<!-- ENDIF -->
<dd>

View file

@ -103,7 +103,7 @@
<ul class="linklist">
<!-- IF TOTAL_MESSAGES or S_VIEW_MESSAGE -->
<li class="rightside pagination">
<!-- IF TOTAL_MESSAGES -->{TOTAL_MESSAGES &bull; <!-- ENDIF -->
<!-- IF TOTAL_MESSAGES -->{TOTAL_MESSAGES} &bull; <!-- ENDIF -->
<!-- IF .pagination -->
<!-- INCLUDE pagination.html -->
<!-- ELSE -->

View file

@ -260,8 +260,9 @@ ul.cplist {
/* Friends list */
.cp-mini {
padding: 0 5px;
margin: 10px 15px 10px 5px;
padding: 5px 10px;
border-radius: 7px;
}
dl.mini dt {

View file

@ -7,7 +7,7 @@
<option value="">{L_SELECT_CURRENT_TIME}</option>
{S_TZ_DATE_OPTIONS}
</select><br />
<input id="tz_select_date_suggest" class="btnlite" style="display: none;" data-is-registration="<!-- IF S_REGISTRATION -->true<!-- ELSE -->false<!-- ENDIF -->" data-l-suggestion="{L_TIMEZONE_DATE_SUGGESTION}" value="{L_TIMEZONE_DATE_SUGGESTION}" />
<input type="button" id="tz_select_date_suggest" class="btnlite" style="display: none;" data-is-registration="<!-- IF S_REGISTRATION -->true<!-- ELSE -->false<!-- ENDIF -->" data-l-suggestion="{L_TIMEZONE_DATE_SUGGESTION}" value="{L_TIMEZONE_DATE_SUGGESTION}" />
</div>
<!-- ENDIF -->
<select name="tz" id="timezone" class="autowidth tz_select">

View file

@ -328,6 +328,18 @@ if (!$auth->acl_get('u_sig'))
$module->set_display('profile', 'signature', false);
}
/**
* Use this event to enable and disable additional UCP modules
*
* @event core.ucp_display_module_before
* @var p_master module Object holding all modules and their status
* @var mixed id Active module category (can be the int or string)
* @var string mode Active module
* @since 3.1-A1
*/
$vars = array('module', 'id', 'mode');
extract($phpbb_dispatcher->trigger_event('core.ucp_display_module_before', compact($vars)));
// Select the active module
$module->set_active($id, $mode);

View file

@ -694,7 +694,7 @@ if (sizeof($topic_list))
$u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . "&amp;t=$topic_id", true, $user->session_id) : '';
// Send vars to template
$template->assign_block_vars('topicrow', array(
$topic_row = array(
'FORUM_ID' => $row['forum_id'],
'TOPIC_ID' => $topic_id,
'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
@ -746,11 +746,24 @@ if (sizeof($topic_list))
'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=reports&amp;f=' . $row['forum_id'] . '&amp;t=' . $topic_id, true, $user->session_id),
'U_MCP_QUEUE' => $u_mcp_queue,
'S_TOPIC_TYPE_SWITCH' => ($s_type_switch == $s_type_switch_test) ? -1 : $s_type_switch_test)
'S_TOPIC_TYPE_SWITCH' => ($s_type_switch == $s_type_switch_test) ? -1 : $s_type_switch_test,
);
/**
* Modify the topic data before it is assigned to the template
*
* @event core.viewforum_modify_topicrow
* @var array row Array with topic data
* @var array topic_row Template array with topic data
* @since 3.1-A1
*/
$vars = array('row', 'topic_row');
extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_topicrow', compact($vars)));
$template->assign_block_vars('topicrow', $topic_row);
phpbb_generate_template_pagination($template, $view_topic_url, 'topicrow.pagination', 'start', $replies + 1, $config['posts_per_page'], 1, true, true);
$s_type_switch = ($row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL) ? 1 : 0;
if ($unread_topic)

View file

@ -121,13 +121,30 @@ if (!$show_guests)
}
// Get user list
$sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_type, u.user_colour, s.session_id, s.session_time, s.session_page, s.session_ip, s.session_browser, s.session_viewonline, s.session_forum_id
FROM ' . USERS_TABLE . ' u, ' . SESSIONS_TABLE . ' s
WHERE u.user_id = s.session_user_id
$sql_ary = array(
'SELECT' => 'u.user_id, u.username, u.username_clean, u.user_type, u.user_colour, s.session_id, s.session_time, s.session_page, s.session_ip, s.session_browser, s.session_viewonline, s.session_forum_id',
'FROM' => array(
USERS_TABLE => 'u',
SESSIONS_TABLE => 's',
),
'WHERE' => 'u.user_id = s.session_user_id
AND s.session_time >= ' . (time() - ($config['load_online_time'] * 60)) .
((!$show_guests) ? ' AND s.session_user_id <> ' . ANONYMOUS : '') . '
ORDER BY ' . $order_by;
$result = $db->sql_query($sql);
((!$show_guests) ? ' AND s.session_user_id <> ' . ANONYMOUS : ''),
'ORDER_BY' => $order_by,
);
/**
* Modify the SQL query for getting the user data to display viewonline list
*
* @event core.viewonline_modify_sql
* @var array sql_ary The SQL array
* @var bool show_guests Do we display guests in the list
* @since 3.1-A1
*/
$vars = array('sql_ary', 'show_guests');
extract($phpbb_dispatcher->trigger_event('core.viewonline_modify_sql', compact($vars)));
$result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary));
$prev_id = $prev_ip = $user_list = array();
$logged_visible_online = $logged_hidden_online = $counter = 0;
@ -320,6 +337,19 @@ while ($row = $db->sql_fetchrow($result))
break;
}
/**
* Overwrite the location's name and URL, which are displayed in the list
*
* @event core.viewonline_overwrite_location
* @var array on_page File name and query string
* @var array row Array with the users sql row
* @var string location Page name to displayed in the list
* @var string location_url Page url to displayed in the list
* @since 3.1-A1
*/
$vars = array('on_page', 'row', 'location', 'location_url');
extract($phpbb_dispatcher->trigger_event('core.viewonline_overwrite_location', compact($vars)));
$template->assign_block_vars('user_row', array(
'USERNAME' => $row['username'],
'USERNAME_COLOUR' => $row['user_colour'],

View file

@ -987,6 +987,16 @@ $sql_ary = array(
AND u.user_id = p.poster_id',
);
/**
* Event to modify the SQL query before the post and poster data is retrieved
*
* @event core.viewtopic_get_post_data
* @var array sql_ary The SQL array to get the data of posts and posters
* @since 3.1-A1
*/
$vars = array('sql_ary');
extract($phpbb_dispatcher->trigger_event('core.viewtopic_get_post_data', compact($vars)));
$sql = $db->sql_build_query('SELECT', $sql_ary);
$result = $db->sql_query($sql);
@ -1063,7 +1073,7 @@ while ($row = $db->sql_fetchrow($result))
{
if ($poster_id == ANONYMOUS)
{
$user_cache[$poster_id] = array(
$user_cache_data = array(
'joined' => '',
'posts' => '',
'from' => '',
@ -1098,6 +1108,20 @@ while ($row = $db->sql_fetchrow($result))
'allow_pm' => 0,
);
/**
* Modify the guest user's data displayed with the posts
*
* @event core.viewtopic_cache_guest_data
* @var array user_cache_data Array with the user's data
* @var int poster_id Poster's user id
* @var array row Array with original user and post data
* @since 3.1-A1
*/
$vars = array('user_cache_data', 'poster_id', 'row');
extract($phpbb_dispatcher->trigger_event('core.viewtopic_cache_guest_data', compact($vars)));
$user_cache[$poster_id] = $user_cache_data;
get_user_rank($row['user_rank'], false, $user_cache[$poster_id]['rank_title'], $user_cache[$poster_id]['rank_image'], $user_cache[$poster_id]['rank_image_src']);
}
else
@ -1112,7 +1136,7 @@ while ($row = $db->sql_fetchrow($result))
$id_cache[] = $poster_id;
$user_cache[$poster_id] = array(
$user_cache_data = array(
'joined' => $user->format_date($row['user_regdate']),
'posts' => $row['user_posts'],
'warnings' => (isset($row['user_warnings'])) ? $row['user_warnings'] : 0,
@ -1150,6 +1174,20 @@ while ($row = $db->sql_fetchrow($result))
'author_profile' => get_username_string('profile', $poster_id, $row['username'], $row['user_colour']),
);
/**
* Modify the users' data displayed with their posts
*
* @event core.viewtopic_cache_user_data
* @var array user_cache_data Array with the user's data
* @var int poster_id Poster's user id
* @var array row Array with original user and post data
* @since 3.1-A1
*/
$vars = array('user_cache_data', 'poster_id', 'row');
extract($phpbb_dispatcher->trigger_event('core.viewtopic_cache_user_data', compact($vars)));
$user_cache[$poster_id] = $user_cache_data;
get_user_rank($row['user_rank'], $row['user_posts'], $user_cache[$poster_id]['rank_title'], $user_cache[$poster_id]['rank_image'], $user_cache[$poster_id]['rank_image_src']);
if ((!empty($row['user_allow_viewemail']) && $auth->acl_get('u_sendemail')) || $auth->acl_get('a_email'))
@ -1493,7 +1531,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
)));
//
$postrow = array(
$post_row = array(
'POST_AUTHOR_FULL' => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_full'] : get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
'POST_AUTHOR_COLOUR' => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_colour'] : get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
'POST_AUTHOR' => ($poster_id != ANONYMOUS) ? $user_cache[$poster_id]['author_username'] : get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']),
@ -1569,13 +1607,28 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
'L_IGNORE_POST' => ($row['hide_post']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), '<a href="' . $viewtopic_url . "&amp;p={$row['post_id']}&amp;view=show#p{$row['post_id']}" . '">', '</a>') : '',
);
$user_poster_data = $user_cache[$poster_id];
/**
* Modify the posts template block
*
* @event core.viewtopic_modify_post_row
* @var array row Array with original post and user data
* @var array cp_row Custom profile field data of the poster
* @var array user_poster_data Poster's data from user cache
* @var array post_row Template block array of the post
* @since 3.1-A1
*/
$vars = array('row', 'cp_row', 'user_poster_data', 'post_row');
extract($phpbb_dispatcher->trigger_event('core.viewtopic_modify_post_row', compact($vars)));
if (isset($cp_row['row']) && sizeof($cp_row['row']))
{
$postrow = array_merge($postrow, $cp_row['row']);
$post_row = array_merge($post_row, $cp_row['row']);
}
// Dump vars into template
$template->assign_block_vars('postrow', $postrow);
$template->assign_block_vars('postrow', $post_row);
if (!empty($cp_row['blockrow']))
{
@ -1729,8 +1782,23 @@ if (!request_var('t', 0) && !empty($topic_id))
$request->overwrite('t', $topic_id);
}
$page_title = $topic_data['topic_title'] . ($start ? ' - ' . sprintf($user->lang['PAGE_TITLE_NUMBER'], floor($start / $config['posts_per_page']) + 1) : '');
/**
* You can use this event to modify the page title of the viewtopic page
*
* @event core.viewtopic_modify_page_title
* @var string page_title Title of the index page
* @var array topic_data Array with topic data
* @var int forum_id Forum ID of the topic
* @var int start Start offset used to calculate the page
* @since 3.1-A1
*/
$vars = array('page_title', 'topic_data', 'forum_id', 'start');
extract($phpbb_dispatcher->trigger_event('core.viewtopic_modify_page_title', compact($vars)));
// Output the page
page_header($topic_data['topic_title'] . ($start ? ' - ' . sprintf($user->lang['PAGE_TITLE_NUMBER'], floor($start / $config['posts_per_page']) + 1) : ''), true, $forum_id);
page_header($page_title, true, $forum_id);
$template->set_filenames(array(
'body' => ($view == 'print') ? 'viewtopic_print.html' : 'viewtopic_body.html')

View file

@ -9,7 +9,7 @@
require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_cache_test extends phpbb_test_case
class phpbb_cache_test extends phpbb_database_test_case
{
private $cache_dir;
@ -18,8 +18,15 @@ class phpbb_cache_test extends phpbb_test_case
$this->cache_dir = dirname(__FILE__) . '/../tmp/cache/';
}
public function getDataSet()
{
return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config.xml');
}
protected function setUp()
{
parent::setUp();
if (file_exists($this->cache_dir))
{
// cache directory possibly left after aborted
@ -35,6 +42,8 @@ class phpbb_cache_test extends phpbb_test_case
{
$this->remove_cache_dir();
}
parent::tearDown();
}
private function create_cache_dir()
@ -67,4 +76,34 @@ class phpbb_cache_test extends phpbb_test_case
'File ACM put and get'
);
}
public function test_cache_sql()
{
$driver = new phpbb_cache_driver_file($this->cache_dir);
global $db, $cache;
$db = $this->new_dbal();
$cache = new phpbb_cache_service($driver);
$sql = "SELECT * FROM phpbb_config
WHERE config_name = 'foo'";
$result = $db->sql_query($sql, 300);
$first_result = $db->sql_fetchrow($result);
$this->assertFileExists($this->cache_dir . 'sql_' . md5(preg_replace('/[\n\r\s\t]+/', ' ', $sql)) . '.php');
$sql = "SELECT * FROM phpbb_config
WHERE config_name = 'foo'";
$result = $db->sql_query($sql, 300);
$this->assertEquals($first_result, $db->sql_fetchrow($result));
$sql = "SELECT * FROM phpbb_config
WHERE config_name = 'bar'";
$result = $db->sql_query($sql, 300);
$this->assertNotEquals($first_result, $db->sql_fetchrow($result));
$db->sql_close();
}
}

18
tests/cache/fixtures/config.xml vendored Normal file
View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<dataset>
<table name="phpbb_config">
<column>config_name</column>
<column>config_value</column>
<column>is_dynamic</column>
<row>
<value>foo</value>
<value>23</value>
<value>0</value>
</row>
<row>
<value>bar</value>
<value>42</value>
<value>1</value>
</row>
</table>
</dataset>

View file

@ -46,8 +46,9 @@ class phpbb_functions_acp_build_cfg_template_test extends phpbb_test_case
*/
public function test_build_cfg_template_text($tpl_type, $key, $new, $config_key, $vars, $expected)
{
global $user;
global $user, $phpbb_dispatcher;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$user->lang = new phpbb_mock_lang();
$this->assertEquals($expected, build_cfg_template($tpl_type, $key, $new, $config_key, $vars));
@ -80,8 +81,9 @@ class phpbb_functions_acp_build_cfg_template_test extends phpbb_test_case
*/
public function test_build_cfg_template_dimension($tpl_type, $key, $new, $config_key, $vars, $expected)
{
global $user;
global $user, $phpbb_dispatcher;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$user->lang = new phpbb_mock_lang();
$this->assertEquals($expected, build_cfg_template($tpl_type, $key, $new, $config_key, $vars));
@ -106,8 +108,9 @@ class phpbb_functions_acp_build_cfg_template_test extends phpbb_test_case
*/
public function test_build_cfg_template_textarea($tpl_type, $key, $new, $config_key, $vars, $expected)
{
global $user;
global $user, $phpbb_dispatcher;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$user->lang = new phpbb_mock_lang();
$this->assertEquals($expected, build_cfg_template($tpl_type, $key, $new, $config_key, $vars));
@ -156,8 +159,9 @@ class phpbb_functions_acp_build_cfg_template_test extends phpbb_test_case
*/
public function test_build_cfg_template_radio($tpl_type, $key, $new, $config_key, $vars, $expected)
{
global $user;
global $user, $phpbb_dispatcher;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$user->lang = new phpbb_mock_lang();
$this->assertEquals($expected, build_cfg_template($tpl_type, $key, $new, $config_key, $vars));
@ -182,8 +186,9 @@ class phpbb_functions_acp_build_cfg_template_test extends phpbb_test_case
*/
public function test_build_cfg_template_append($tpl_type, $key, $new, $config_key, $vars, $expected)
{
global $user;
global $user, $phpbb_dispatcher;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
$user->lang = new phpbb_mock_lang();
$this->assertEquals($expected, build_cfg_template($tpl_type, $key, $new, $config_key, $vars));

View file

@ -121,7 +121,7 @@ class phpbb_mock_cache implements phpbb_cache_driver_interface
public function sql_load($query)
{
}
public function sql_save($query, &$query_result, $ttl)
public function sql_save($query, $query_result, $ttl)
{
}
public function sql_exists($query_id)

View file

@ -0,0 +1,16 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_mock_event_dispatcher
{
public function trigger_event($eventName, $data)
{
return array();
}
}

View file

@ -197,13 +197,11 @@ class phpbb_functional_test_case extends phpbb_test_case
$this->do_request('create_table', $data);
$this->do_request('config_file', $data);
file_put_contents($phpbb_root_path . "config.$phpEx", phpbb_create_config_file_data($data, self::$config['dbms'], array(), true));
$this->do_request('config_file', $data);
copy($phpbb_root_path . "config.$phpEx", $phpbb_root_path . "config_test.$phpEx");
$this->do_request('final', $data);
copy($phpbb_root_path . "config.$phpEx", $phpbb_root_path . "config_test.$phpEx");
}
private function do_request($sub, $post_data = null)