Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
search.php
0001 <?php
0002 /**
0003 *
0004 * This file is part of the phpBB Forum Software package.
0005 *
0006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007 * @license GNU General Public License, version 2 (GPL-2.0)
0008 *
0009 * For full copyright and license information, please see
0010 * the docs/CREDITS.txt file.
0011 *
0012 */
0013
0014 /**
0015 * @ignore
0016 */
0017 define('IN_PHPBB', true);
0018 $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
0019 $phpEx = substr(strrchr(__FILE__, '.'), 1);
0020 include($phpbb_root_path . 'common.' . $phpEx);
0021
0022 // Start session management
0023 $user->session_begin();
0024 $auth->acl($user->data);
0025 $user->setup('search');
0026
0027 // Define initial vars
0028 $mode = $request->variable('mode', '');
0029 $search_id = $request->variable('search_id', '');
0030 $start = max($request->variable('start', 0), 0);
0031 $post_id = $request->variable('p', 0);
0032 $topic_id = $request->variable('t', 0);
0033 $view = $request->variable('view', '');
0034
0035 $submit = $request->variable('submit', false);
0036 $keywords = $request->variable('keywords', '', true);
0037 $add_keywords = $request->variable('add_keywords', '', true);
0038 $author = $request->variable('author', '', true);
0039 $author_id = $request->variable('author_id', 0);
0040 $show_results = ($topic_id) ? 'posts' : $request->variable('sr', 'posts');
0041 $show_results = ($show_results == 'posts') ? 'posts' : 'topics';
0042 $search_terms = $request->variable('terms', 'all');
0043 $search_fields = $request->variable('sf', 'all');
0044 $search_child = $request->variable('sc', true);
0045
0046 $sort_days = $request->variable('st', 0);
0047 $sort_key = $request->variable('sk', 't');
0048 $sort_dir = $request->variable('sd', 'd');
0049
0050 $return_chars = $request->variable('ch', ($topic_id) ? -1 : 300);
0051 $search_forum = $request->variable('fid', array(0));
0052
0053 // We put login boxes for the case if search_id is newposts, egosearch or unreadposts
0054 // because a guest should be able to log in even if guests search is not permitted
0055
0056 switch ($search_id)
0057 {
0058 // Egosearch is an author search
0059 case 'egosearch':
0060 $author_id = $user->data['user_id'];
0061 if ($user->data['user_id'] == ANONYMOUS)
0062 {
0063 login_box('', $user->lang['LOGIN_EXPLAIN_EGOSEARCH']);
0064 }
0065 break;
0066
0067 // Search for unread posts needs to be allowed and user to be logged in if topics tracking for guests is disabled
0068 case 'unreadposts':
0069 if (!$config['load_unreads_search'])
0070 {
0071 $template->assign_var('S_NO_SEARCH', true);
0072 trigger_error('NO_SEARCH_UNREADS');
0073 }
0074 else if (!$config['load_anon_lastread'] && !$user->data['is_registered'])
0075 {
0076 login_box('', $user->lang['LOGIN_EXPLAIN_UNREADSEARCH']);
0077 }
0078 break;
0079
0080 // The "new posts" search uses user_lastvisit which is user based, so it should require user to log in.
0081 case 'newposts':
0082 if ($user->data['user_id'] == ANONYMOUS)
0083 {
0084 login_box('', $user->lang['LOGIN_EXPLAIN_NEWPOSTS']);
0085 }
0086 break;
0087
0088 default:
0089 // There's nothing to do here for now ;)
0090 break;
0091 }
0092
0093 // Is user able to search? Has search been disabled?
0094 if (!$auth->acl_get('u_search') || !$auth->acl_getf_global('f_search') || !$config['load_search'])
0095 {
0096 $template->assign_var('S_NO_SEARCH', true);
0097 trigger_error('NO_SEARCH');
0098 }
0099
0100 // Check search load limit
0101 if ($user->load && $config['limit_search_load'] && ($user->load > doubleval($config['limit_search_load'])))
0102 {
0103 $template->assign_var('S_NO_SEARCH', true);
0104 trigger_error('NO_SEARCH_LOAD');
0105 }
0106
0107 // It is applicable if the configuration setting is non-zero, and the user cannot
0108 // ignore the flood setting, and the search is a keyword search.
0109 $interval = ($user->data['user_id'] == ANONYMOUS) ? $config['search_anonymous_interval'] : $config['search_interval'];
0110 if ($interval && !in_array($search_id, array('unreadposts', 'unanswered', 'active_topics', 'egosearch')) && !$auth->acl_get('u_ignoreflood'))
0111 {
0112 if ($user->data['user_last_search'] > time() - $interval)
0113 {
0114 $template->assign_var('S_NO_SEARCH', true);
0115 trigger_error($user->lang('NO_SEARCH_TIME', (int) ($user->data['user_last_search'] + $interval - time())));
0116 }
0117 }
0118
0119 // Define some vars
0120 $limit_days = array(0 => $user->lang['ALL_RESULTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
0121 $sort_by_text = array('a' => $user->lang['SORT_AUTHOR'], 't' => $user->lang['SORT_TIME'], 'f' => $user->lang['SORT_FORUM'], 'i' => $user->lang['SORT_TOPIC_TITLE'], 's' => $user->lang['SORT_POST_SUBJECT']);
0122
0123 $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
0124 gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
0125
0126 /* @var $phpbb_content_visibility \phpbb\content_visibility */
0127 $phpbb_content_visibility = $phpbb_container->get('content.visibility');
0128
0129 /* @var $pagination \phpbb\pagination */
0130 $pagination = $phpbb_container->get('pagination');
0131
0132 /**
0133 * This event allows you to alter the above parameters, such as keywords and submit
0134 *
0135 * @event core.search_modify_submit_parameters
0136 * @var string keywords The search keywords
0137 * @var string author Specifies the author match, when ANONYMOUS is also a search-match
0138 * @var int author_id ID of the author to search by
0139 * @var string search_id Predefined search type name
0140 * @var bool submit Whether or not the form has been submitted
0141 * @since 3.1.10-RC1
0142 */
0143 $vars = array(
0144 'keywords',
0145 'author',
0146 'author_id',
0147 'search_id',
0148 'submit',
0149 );
0150 extract($phpbb_dispatcher->trigger_event('core.search_modify_submit_parameters', compact($vars)));
0151
0152 if ($keywords || $author || $author_id || $search_id || $submit)
0153 {
0154 // clear arrays
0155 $id_ary = array();
0156
0157 // If we are looking for authors get their ids
0158 $author_id_ary = array();
0159 $sql_author_match = '';
0160 if ($author_id)
0161 {
0162 $author_id_ary[] = $author_id;
0163 }
0164 else if ($author)
0165 {
0166 if ((strpos($author, '*') !== false) && (utf8_strlen(str_replace(array('*', '%'), '', $author)) < $config['min_search_author_chars']))
0167 {
0168 trigger_error($user->lang('TOO_FEW_AUTHOR_CHARS', (int) $config['min_search_author_chars']));
0169 }
0170
0171 $sql_where = (strpos($author, '*') !== false) ? ' username_clean ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($author))) : " username_clean = '" . $db->sql_escape(utf8_clean_string($author)) . "'";
0172
0173 $sql = 'SELECT user_id
0174 FROM ' . USERS_TABLE . "
0175 WHERE $sql_where
0176 AND user_type <> " . USER_IGNORE;
0177 $result = $db->sql_query_limit($sql, 100);
0178
0179 while ($row = $db->sql_fetchrow($result))
0180 {
0181 $author_id_ary[] = (int) $row['user_id'];
0182 }
0183 $db->sql_freeresult($result);
0184
0185 $sql_where = (strpos($author, '*') !== false) ? ' post_username ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($author))) : " post_username = '" . $db->sql_escape(utf8_clean_string($author)) . "'";
0186
0187 $sql = 'SELECT 1 as guest_post
0188 FROM ' . POSTS_TABLE . "
0189 WHERE $sql_where
0190 AND poster_id = " . ANONYMOUS;
0191 $result = $db->sql_query_limit($sql, 1);
0192 $found_guest_post = $db->sql_fetchfield('guest_post');
0193 $db->sql_freeresult($result);
0194
0195 if ($found_guest_post)
0196 {
0197 $author_id_ary[] = ANONYMOUS;
0198 $sql_author_match = (strpos($author, '*') !== false) ? ' ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($author))) : " = '" . $db->sql_escape(utf8_clean_string($author)) . "'";
0199 }
0200
0201 if (!sizeof($author_id_ary))
0202 {
0203 trigger_error('NO_SEARCH_RESULTS');
0204 }
0205 }
0206
0207 // if we search in an existing search result just add the additional keywords. But we need to use "all search terms"-mode
0208 // so we can keep the old keywords in their old mode, but add the new ones as required words
0209 if ($add_keywords)
0210 {
0211 if ($search_terms == 'all')
0212 {
0213 $keywords .= ' ' . $add_keywords;
0214 }
0215 else
0216 {
0217 $search_terms = 'all';
0218 $keywords = implode(' |', explode(' ', preg_replace('#\s+#u', ' ', $keywords))) . ' ' .$add_keywords;
0219 }
0220 }
0221
0222 // Which forums should not be searched? Author searches are also carried out in unindexed forums
0223 if (empty($keywords) && sizeof($author_id_ary))
0224 {
0225 $ex_fid_ary = array_keys($auth->acl_getf('!f_read', true));
0226 }
0227 else
0228 {
0229 $ex_fid_ary = array_unique(array_merge(array_keys($auth->acl_getf('!f_read', true)), array_keys($auth->acl_getf('!f_search', true))));
0230 }
0231
0232 $not_in_fid = (sizeof($ex_fid_ary)) ? 'WHERE ' . $db->sql_in_set('f.forum_id', $ex_fid_ary, true) . " OR (f.forum_password <> '' AND fa.user_id <> " . (int) $user->data['user_id'] . ')' : "";
0233
0234 $sql = 'SELECT f.forum_id, f.forum_name, f.parent_id, f.forum_type, f.right_id, f.forum_password, f.forum_flags, fa.user_id
0235 FROM ' . FORUMS_TABLE . ' f
0236 LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa ON (fa.forum_id = f.forum_id
0237 AND fa.session_id = '" . $db->sql_escape($user->session_id) . "')
0238 $not_in_fid
0239 ORDER BY f.left_id";
0240 $result = $db->sql_query($sql);
0241
0242 $right_id = 0;
0243 $reset_search_forum = true;
0244 while ($row = $db->sql_fetchrow($result))
0245 {
0246 if ($row['forum_password'] && $row['user_id'] != $user->data['user_id'])
0247 {
0248 $ex_fid_ary[] = (int) $row['forum_id'];
0249 continue;
0250 }
0251
0252 // Exclude forums from active topics
0253 if (!($row['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) && ($search_id == 'active_topics'))
0254 {
0255 $ex_fid_ary[] = (int) $row['forum_id'];
0256 continue;
0257 }
0258
0259 if (sizeof($search_forum))
0260 {
0261 if ($search_child)
0262 {
0263 if (in_array($row['forum_id'], $search_forum) && $row['right_id'] > $right_id)
0264 {
0265 $right_id = (int) $row['right_id'];
0266 }
0267 else if ($row['right_id'] < $right_id)
0268 {
0269 continue;
0270 }
0271 }
0272
0273 if (!in_array($row['forum_id'], $search_forum))
0274 {
0275 $ex_fid_ary[] = (int) $row['forum_id'];
0276 $reset_search_forum = false;
0277 }
0278 }
0279 }
0280 $db->sql_freeresult($result);
0281
0282 // find out in which forums the user is allowed to view posts
0283 $m_approve_posts_fid_sql = $phpbb_content_visibility->get_global_visibility_sql('post', $ex_fid_ary, 'p.');
0284 $m_approve_topics_fid_sql = $phpbb_content_visibility->get_global_visibility_sql('topic', $ex_fid_ary, 't.');
0285
0286 if ($reset_search_forum)
0287 {
0288 $search_forum = array();
0289 }
0290
0291 // Select which method we'll use to obtain the post_id or topic_id information
0292 $search_type = $config['search_type'];
0293
0294 if (!class_exists($search_type))
0295 {
0296 trigger_error('NO_SUCH_SEARCH_MODULE');
0297 }
0298 // We do some additional checks in the module to ensure it can actually be utilised
0299 $error = false;
0300 $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
0301
0302 if ($error)
0303 {
0304 trigger_error($error);
0305 }
0306
0307 // let the search module split up the keywords
0308 if ($keywords)
0309 {
0310 $correct_query = $search->split_keywords($keywords, $search_terms);
0311 $common_words = $search->get_common_words();
0312 if (!$correct_query || (!$search->get_search_query() && !sizeof($author_id_ary) && !$search_id))
0313 {
0314 $ignored = (sizeof($common_words)) ? sprintf($user->lang['IGNORED_TERMS_EXPLAIN'], implode(' ', $common_words)) . '<br />' : '';
0315 $word_length = $search->get_word_length();
0316 if ($word_length)
0317 {
0318 trigger_error($ignored . $user->lang('NO_KEYWORDS', $user->lang('CHARACTERS', (int) $word_length['min']), $user->lang('CHARACTERS', (int) $word_length['max'])));
0319 }
0320 else
0321 {
0322 trigger_error($ignored);
0323 }
0324 }
0325 }
0326
0327 if (!$keywords && sizeof($author_id_ary))
0328 {
0329 // if it is an author search we want to show topics by default
0330 $show_results = ($topic_id) ? 'posts' : $request->variable('sr', ($search_id == 'egosearch') ? 'topics' : 'posts');
0331 $show_results = ($show_results == 'posts') ? 'posts' : 'topics';
0332 }
0333
0334 // define some variables needed for retrieving post_id/topic_id information
0335 $sort_by_sql = array('a' => 'u.username_clean', 't' => (($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time'), 'f' => 'f.forum_id', 'i' => 't.topic_title', 's' => (($show_results == 'posts') ? 'p.post_subject' : 't.topic_title'));
0336
0337 /**
0338 * Event to modify the SQL parameters before pre-made searches
0339 *
0340 * @event core.search_modify_param_before
0341 * @var string keywords String of the specified keywords
0342 * @var array sort_by_sql Array of SQL sorting instructions
0343 * @var array ex_fid_ary Array of excluded forum ids
0344 * @var array author_id_ary Array of exclusive author ids
0345 * @var string search_id The id of the search request
0346 * @var array id_ary Array of post or topic ids for search result
0347 * @var string show_results 'posts' or 'topics' type of ids
0348 * @since 3.1.3-RC1
0349 * @changed 3.1.10-RC1 Added id_ary, show_results
0350 */
0351 $vars = array(
0352 'keywords',
0353 'sort_by_sql',
0354 'ex_fid_ary',
0355 'author_id_ary',
0356 'search_id',
0357 'id_ary',
0358 'show_results',
0359 );
0360 extract($phpbb_dispatcher->trigger_event('core.search_modify_param_before', compact($vars)));
0361
0362 // pre-made searches
0363 $sql = $field = $l_search_title = '';
0364 if ($search_id)
0365 {
0366 switch ($search_id)
0367 {
0368 // Oh holy Bob, bring us some activity...
0369 case 'active_topics':
0370 $l_search_title = $user->lang['SEARCH_ACTIVE_TOPICS'];
0371 $show_results = 'topics';
0372 $sort_key = 't';
0373 $sort_dir = 'd';
0374 $sort_days = $request->variable('st', 7);
0375 $sort_by_sql['t'] = 't.topic_last_post_time';
0376
0377 gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
0378 $s_sort_key = $s_sort_dir = '';
0379
0380 $last_post_time_sql = ($sort_days) ? ' AND t.topic_last_post_time > ' . (time() - ($sort_days * 24 * 3600)) : '';
0381
0382 $sql = 'SELECT t.topic_last_post_time, t.topic_id
0383 FROM ' . TOPICS_TABLE . " t
0384 WHERE t.topic_moved_id = 0
0385 $last_post_time_sql
0386 AND " . $m_approve_topics_fid_sql . '
0387 ' . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . '
0388 ORDER BY t.topic_last_post_time DESC';
0389 $field = 'topic_id';
0390 break;
0391
0392 case 'unanswered':
0393 $l_search_title = $user->lang['SEARCH_UNANSWERED'];
0394 $show_results = $request->variable('sr', 'topics');
0395 $show_results = ($show_results == 'posts') ? 'posts' : 'topics';
0396 $sort_by_sql['t'] = ($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time';
0397 $sort_by_sql['s'] = ($show_results == 'posts') ? 'p.post_subject' : 't.topic_title';
0398 $sql_sort = 'ORDER BY ' . $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
0399
0400 $sort_join = ($sort_key == 'f') ? FORUMS_TABLE . ' f, ' : '';
0401 $sql_sort = ($sort_key == 'f') ? ' AND f.forum_id = p.forum_id ' . $sql_sort : $sql_sort;
0402
0403 if ($sort_days)
0404 {
0405 $last_post_time = 'AND p.post_time > ' . (time() - ($sort_days * 24 * 3600));
0406 }
0407 else
0408 {
0409 $last_post_time = '';
0410 }
0411
0412 if ($sort_key == 'a')
0413 {
0414 $sort_join = USERS_TABLE . ' u, ';
0415 $sql_sort = ' AND u.user_id = p.poster_id ' . $sql_sort;
0416 }
0417 if ($show_results == 'posts')
0418 {
0419 $sql = "SELECT p.post_id
0420 FROM $sort_join" . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t
0421 WHERE t.topic_posts_approved = 1
0422 AND p.topic_id = t.topic_id
0423 $last_post_time
0424 AND $m_approve_posts_fid_sql
0425 " . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . "
0426 $sql_sort";
0427 $field = 'post_id';
0428 }
0429 else
0430 {
0431 $sql = 'SELECT DISTINCT ' . $sort_by_sql[$sort_key] . ", p.topic_id
0432 FROM $sort_join" . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t
0433 WHERE t.topic_posts_approved = 1
0434 AND t.topic_moved_id = 0
0435 AND p.topic_id = t.topic_id
0436 $last_post_time
0437 AND $m_approve_topics_fid_sql
0438 " . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . "
0439 $sql_sort";
0440 $field = 'topic_id';
0441 }
0442 break;
0443
0444 case 'unreadposts':
0445 $l_search_title = $user->lang['SEARCH_UNREAD'];
0446 // force sorting
0447 $show_results = 'topics';
0448 $sort_key = 't';
0449 $sort_by_sql['t'] = 't.topic_last_post_time';
0450 $sql_sort = 'ORDER BY ' . $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
0451
0452 $sql_where = 'AND t.topic_moved_id = 0
0453 AND ' . $m_approve_topics_fid_sql . '
0454 ' . ((sizeof($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '');
0455
0456 gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
0457 $s_sort_key = $s_sort_dir = $u_sort_param = $s_limit_days = '';
0458
0459 $template->assign_var('U_MARK_ALL_READ', ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}index.$phpEx", 'hash=' . generate_link_hash('global') . '&mark=forums&mark_time=' . time()) : '');
0460 break;
0461
0462 case 'newposts':
0463 $l_search_title = $user->lang['SEARCH_NEW'];
0464 // force sorting
0465 $show_results = ($request->variable('sr', 'topics') == 'posts') ? 'posts' : 'topics';
0466 $sort_key = 't';
0467 $sort_dir = 'd';
0468 $sort_by_sql['t'] = ($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time';
0469 $sql_sort = 'ORDER BY ' . $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
0470
0471 gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
0472 $s_sort_key = $s_sort_dir = $u_sort_param = $s_limit_days = '';
0473
0474 if ($show_results == 'posts')
0475 {
0476 $sql = 'SELECT p.post_id
0477 FROM ' . POSTS_TABLE . ' p
0478 WHERE p.post_time > ' . $user->data['user_lastvisit'] . '
0479 AND ' . $m_approve_posts_fid_sql . '
0480 ' . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . "
0481 $sql_sort";
0482 $field = 'post_id';
0483 }
0484 else
0485 {
0486 $sql = 'SELECT t.topic_id
0487 FROM ' . TOPICS_TABLE . ' t
0488 WHERE t.topic_last_post_time > ' . $user->data['user_lastvisit'] . '
0489 AND t.topic_moved_id = 0
0490 AND ' . $m_approve_topics_fid_sql . '
0491 ' . ((sizeof($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . "
0492 $sql_sort";
0493 /*
0494 [Fix] queued replies missing from "view new posts" (Bug #42705 - Patch by Paul)
0495 - Creates temporary table, query is far from optimized
0496
0497 $sql = 'SELECT t.topic_id
0498 FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
0499 WHERE p.post_time > ' . $user->data['user_lastvisit'] . '
0500 AND t.topic_id = p.topic_id
0501 AND t.topic_moved_id = 0
0502 AND ' . $m_approve_topics_fid_sql . "
0503 GROUP BY t.topic_id
0504 $sql_sort";
0505 */
0506 $field = 'topic_id';
0507 }
0508 break;
0509
0510 case 'egosearch':
0511 $l_search_title = $user->lang['SEARCH_SELF'];
0512 break;
0513 }
0514 }
0515
0516 /**
0517 * Event to modify data after pre-made searches
0518 *
0519 * @event core.search_modify_param_after
0520 * @var string l_search_title The title of the search page
0521 * @var string search_id Predefined search type name
0522 * @var string show_results Display topics or posts
0523 * @var string sql SQL query corresponding to the pre-made search id
0524 * @since 3.1.7-RC1
0525 */
0526 $vars = array(
0527 'l_search_title',
0528 'search_id',
0529 'show_results',
0530 'sql',
0531 );
0532 extract($phpbb_dispatcher->trigger_event('core.search_modify_param_after', compact($vars)));
0533
0534 // show_results should not change after this
0535 $per_page = ($show_results == 'posts') ? $config['posts_per_page'] : $config['topics_per_page'];
0536 $total_match_count = 0;
0537
0538 // Set limit for the $total_match_count to reduce server load
0539 $total_matches_limit = 1000;
0540 $found_more_search_matches = false;
0541
0542 if ($search_id)
0543 {
0544 if ($sql)
0545 {
0546 // Only return up to $total_matches_limit+1 ids (the last one will be removed later)
0547 $result = $db->sql_query_limit($sql, $total_matches_limit + 1);
0548
0549 while ($row = $db->sql_fetchrow($result))
0550 {
0551 $id_ary[] = (int) $row[$field];
0552 }
0553 $db->sql_freeresult($result);
0554 }
0555 else if ($search_id == 'unreadposts')
0556 {
0557 // Only return up to $total_matches_limit+1 ids (the last one will be removed later)
0558 $id_ary = array_keys(get_unread_topics($user->data['user_id'], $sql_where, $sql_sort, $total_matches_limit + 1));
0559 }
0560 else
0561 {
0562 $search_id = '';
0563 }
0564
0565 $total_match_count = sizeof($id_ary);
0566 if ($total_match_count)
0567 {
0568 // Limit the number to $total_matches_limit for pre-made searches
0569 if ($total_match_count > $total_matches_limit)
0570 {
0571 $found_more_search_matches = true;
0572 $total_match_count = $total_matches_limit;
0573 }
0574
0575 // Make sure $start is set to the last page if it exceeds the amount
0576 $start = $pagination->validate_start($start, $per_page, $total_match_count);
0577
0578 $id_ary = array_slice($id_ary, $start, $per_page);
0579 }
0580 else
0581 {
0582 // Set $start to 0 if no matches were found
0583 $start = 0;
0584 }
0585 }
0586
0587 // make sure that some arrays are always in the same order
0588 sort($ex_fid_ary);
0589 sort($author_id_ary);
0590
0591 if ($search->get_search_query())
0592 {
0593 $total_match_count = $search->keyword_search($show_results, $search_fields, $search_terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_posts_fid_sql, $topic_id, $author_id_ary, $sql_author_match, $id_ary, $start, $per_page);
0594 }
0595 else if (sizeof($author_id_ary))
0596 {
0597 $firstpost_only = ($search_fields === 'firstpost' || $search_fields == 'titleonly') ? true : false;
0598 $total_match_count = $search->author_search($show_results, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_posts_fid_sql, $topic_id, $author_id_ary, $sql_author_match, $id_ary, $start, $per_page);
0599 }
0600
0601 /**
0602 * Event to search otherwise than by keywords or author
0603 *
0604 * @event core.search_backend_search_after
0605 * @var string show_results 'posts' or 'topics' type of ids
0606 * @var string search_fields The data fields to search in
0607 * @var string search_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)
0608 * @var array sort_by_sql Array of SQL sorting instructions
0609 * @var string sort_key The sort key
0610 * @var string sort_dir The sort direction
0611 * @var int sort_days Limit the age of results
0612 * @var array ex_fid_ary Array of excluded forum ids
0613 * @var string m_approve_posts_fid_sql Specifies which types of posts the user can view in which forums
0614 * @var 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
0615 * @var array author_id_ary Array of exclusive author ids
0616 * @var string sql_author_match Specifies the author match, when ANONYMOUS is also a search-match
0617 * @var array id_ary Array of post or topic ids for search result
0618 * @var int start The starting id of the results
0619 * @var int per_page Number of ids each page is supposed to contain
0620 * @var int total_match_count The total number of search matches
0621 * @since 3.1.10-RC1
0622 */
0623 $vars = array(
0624 'show_results',
0625 'search_fields',
0626 'search_terms',
0627 'sort_by_sql',
0628 'sort_key',
0629 'sort_dir',
0630 'sort_days',
0631 'ex_fid_ary',
0632 'm_approve_posts_fid_sql',
0633 'topic_id',
0634 'author_id_ary',
0635 'sql_author_match',
0636 'id_ary',
0637 'start',
0638 'per_page',
0639 'total_match_count',
0640 );
0641 extract($phpbb_dispatcher->trigger_event('core.search_backend_search_after', compact($vars)));
0642
0643 $sql_where = '';
0644
0645 if (sizeof($id_ary))
0646 {
0647 $sql_where .= $db->sql_in_set(($show_results == 'posts') ? 'p.post_id' : 't.topic_id', $id_ary);
0648 $sql_where .= (sizeof($ex_fid_ary)) ? ' AND (' . $db->sql_in_set('f.forum_id', $ex_fid_ary, true) . ' OR f.forum_id IS NULL)' : '';
0649 $sql_where .= ' AND ' . (($show_results == 'posts') ? $m_approve_posts_fid_sql : $m_approve_topics_fid_sql);
0650 }
0651
0652 if ($show_results == 'posts')
0653 {
0654 include($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
0655 }
0656 else
0657 {
0658 include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
0659 }
0660
0661 $user->add_lang('viewtopic');
0662
0663 // Grab icons
0664 $icons = $cache->obtain_icons();
0665
0666 // define some vars for urls
0667 // A single wildcard will make the search results look ugly
0668 $hilit = phpbb_clean_search_string(str_replace(array('+', '-', '|', '(', ')', '"'), ' ', $keywords));
0669 $hilit = str_replace(' ', '|', $hilit);
0670
0671 $u_hilit = urlencode(htmlspecialchars_decode(str_replace('|', ' ', $hilit)));
0672 $u_show_results = '&sr=' . $show_results;
0673 $u_search_forum = implode('&fid%5B%5D=', $search_forum);
0674
0675 $u_search = append_sid("{$phpbb_root_path}search.$phpEx", $u_sort_param . $u_show_results);
0676 $u_search .= ($search_id) ? '&search_id=' . $search_id : '';
0677 $u_search .= ($u_hilit) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
0678 $u_search .= ($search_terms != 'all') ? '&terms=' . $search_terms : '';
0679 $u_search .= ($topic_id) ? '&t=' . $topic_id : '';
0680 $u_search .= ($author) ? '&author=' . urlencode(htmlspecialchars_decode($author)) : '';
0681 $u_search .= ($author_id) ? '&author_id=' . $author_id : '';
0682 $u_search .= ($u_search_forum) ? '&fid%5B%5D=' . $u_search_forum : '';
0683 $u_search .= (!$search_child) ? '&sc=0' : '';
0684 $u_search .= ($search_fields != 'all') ? '&sf=' . $search_fields : '';
0685 $u_search .= ($return_chars != 300) ? '&ch=' . $return_chars : '';
0686
0687 /**
0688 * Event to add or modify search URL parameters
0689 *
0690 * @event core.search_modify_url_parameters
0691 * @var string u_search Search URL parameters string
0692 * @var string search_id Predefined search type name
0693 * @var string show_results String indicating the show results mode
0694 * @var string sql_where The SQL WHERE string used by search to get topic data
0695 * @var int total_match_count The total number of search matches
0696 * @var array ex_fid_ary Array of excluded forum ids
0697 * @since 3.1.7-RC1
0698 * @changed 3.1.10-RC1 Added show_results, sql_where, total_match_count
0699 * @changed 3.1.11-RC1 Added ex_fid_ary
0700 */
0701 $vars = array(
0702 'u_search',
0703 'search_id',
0704 'show_results',
0705 'sql_where',
0706 'total_match_count',
0707 'ex_fid_ary',
0708 );
0709 extract($phpbb_dispatcher->trigger_event('core.search_modify_url_parameters', compact($vars)));
0710
0711 if ($sql_where)
0712 {
0713 if ($show_results == 'posts')
0714 {
0715 // @todo Joining this query to the one below?
0716 $sql = 'SELECT zebra_id, friend, foe
0717 FROM ' . ZEBRA_TABLE . '
0718 WHERE user_id = ' . $user->data['user_id'];
0719 $result = $db->sql_query($sql);
0720
0721 $zebra = array();
0722 while ($row = $db->sql_fetchrow($result))
0723 {
0724 $zebra[($row['friend']) ? 'friend' : 'foe'][] = $row['zebra_id'];
0725 }
0726 $db->sql_freeresult($result);
0727
0728 $sql_array = array(
0729 'SELECT' => 'p.*, f.forum_id, f.forum_name, t.*, u.username, u.username_clean, u.user_sig, u.user_sig_bbcode_uid, u.user_colour',
0730 'FROM' => array(
0731 POSTS_TABLE => 'p',
0732 ),
0733 'LEFT_JOIN' => array(
0734 array(
0735 'FROM' => array(TOPICS_TABLE => 't'),
0736 'ON' => 'p.topic_id = t.topic_id',
0737 ),
0738 array(
0739 'FROM' => array(FORUMS_TABLE => 'f'),
0740 'ON' => 'p.forum_id = f.forum_id',
0741 ),
0742 array(
0743 'FROM' => array(USERS_TABLE => 'u'),
0744 'ON' => 'p.poster_id = u.user_id',
0745 ),
0746 ),
0747 'WHERE' => $sql_where,
0748 'ORDER_BY' => $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'),
0749 );
0750
0751 /**
0752 * Event to modify the SQL query before the posts data is retrieved
0753 *
0754 * @event core.search_get_posts_data
0755 * @var array sql_array The SQL array
0756 * @var array zebra Array of zebra data for the current user
0757 * @var int total_match_count The total number of search matches
0758 * @var string keywords String of the specified keywords
0759 * @var array sort_by_sql Array of SQL sorting instructions
0760 * @var string s_sort_dir The sort direction
0761 * @var string s_sort_key The sort key
0762 * @var string s_limit_days Limit the age of results
0763 * @var array ex_fid_ary Array of excluded forum ids
0764 * @var array author_id_ary Array of exclusive author ids
0765 * @var string search_fields The data fields to search in
0766 * @var int search_id The id of the search request
0767 * @var int start The starting id of the results
0768 * @since 3.1.0-b3
0769 */
0770 $vars = array(
0771 'sql_array',
0772 'zebra',
0773 'total_match_count',
0774 'keywords',
0775 'sort_by_sql',
0776 's_sort_dir',
0777 's_sort_key',
0778 's_limit_days',
0779 'ex_fid_ary',
0780 'author_id_ary',
0781 'search_fields',
0782 'search_id',
0783 'start',
0784 );
0785 extract($phpbb_dispatcher->trigger_event('core.search_get_posts_data', compact($vars)));
0786
0787 $sql = $db->sql_build_query('SELECT', $sql_array);
0788 }
0789 else
0790 {
0791 $sql_from = TOPICS_TABLE . ' t
0792 LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = t.forum_id)
0793 ' . (($sort_key == 'a') ? ' LEFT JOIN ' . USERS_TABLE . ' u ON (u.user_id = t.topic_poster) ' : '');
0794 $sql_select = 't.*, f.forum_id, f.forum_name';
0795
0796 if ($user->data['is_registered'])
0797 {
0798 if ($config['load_db_track'] && $author_id !== $user->data['user_id'])
0799 {
0800 $sql_from .= ' LEFT JOIN ' . TOPICS_POSTED_TABLE . ' tp ON (tp.user_id = ' . $user->data['user_id'] . '
0801 AND t.topic_id = tp.topic_id)';
0802 $sql_select .= ', tp.topic_posted';
0803 }
0804
0805 if ($config['load_db_lastread'])
0806 {
0807 $sql_from .= ' LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.user_id = ' . $user->data['user_id'] . '
0808 AND t.topic_id = tt.topic_id)
0809 LEFT JOIN ' . FORUMS_TRACK_TABLE . ' ft ON (ft.user_id = ' . $user->data['user_id'] . '
0810 AND ft.forum_id = f.forum_id)';
0811 $sql_select .= ', tt.mark_time, ft.mark_time as f_mark_time';
0812 }
0813 }
0814
0815 if ($config['load_anon_lastread'] || ($user->data['is_registered'] && !$config['load_db_lastread']))
0816 {
0817 $tracking_topics = $request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE);
0818 $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array();
0819 }
0820
0821 $sql_order_by = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
0822
0823 /**
0824 * Event to modify the SQL query before the topic data is retrieved
0825 *
0826 * @event core.search_get_topic_data
0827 * @var string sql_select The SQL SELECT string used by search to get topic data
0828 * @var string sql_from The SQL FROM string used by search to get topic data
0829 * @var string sql_where The SQL WHERE string used by search to get topic data
0830 * @var int total_match_count The total number of search matches
0831 * @var array sort_by_sql Array of SQL sorting instructions
0832 * @var string sort_dir The sorting direction
0833 * @var string sort_key The sorting key
0834 * @var string sql_order_by The SQL ORDER BY string used by search to get topic data
0835 * @since 3.1.0-a1
0836 * @changed 3.1.0-RC5 Added total_match_count
0837 * @changed 3.1.7-RC1 Added sort_by_sql, sort_dir, sort_key, sql_order_by
0838 */
0839 $vars = array(
0840 'sql_select',
0841 'sql_from',
0842 'sql_where',
0843 'total_match_count',
0844 'sort_by_sql',
0845 'sort_dir',
0846 'sort_key',
0847 'sql_order_by',
0848 );
0849 extract($phpbb_dispatcher->trigger_event('core.search_get_topic_data', compact($vars)));
0850
0851 $sql = "SELECT $sql_select
0852 FROM $sql_from
0853 WHERE $sql_where
0854 ORDER BY $sql_order_by";
0855 }
0856 $result = $db->sql_query($sql);
0857 $result_topic_id = 0;
0858
0859 $rowset = $attachments = $topic_tracking_info = array();
0860
0861 if ($show_results == 'topics')
0862 {
0863 $forums = $rowset = $shadow_topic_list = array();
0864 while ($row = $db->sql_fetchrow($result))
0865 {
0866 $row['forum_id'] = (int) $row['forum_id'];
0867 $row['topic_id'] = (int) $row['topic_id'];
0868
0869 if ($row['topic_status'] == ITEM_MOVED)
0870 {
0871 $shadow_topic_list[$row['topic_moved_id']] = $row['topic_id'];
0872 }
0873
0874 $rowset[$row['topic_id']] = $row;
0875
0876 if (!isset($forums[$row['forum_id']]) && $user->data['is_registered'] && $config['load_db_lastread'])
0877 {
0878 $forums[$row['forum_id']]['mark_time'] = $row['f_mark_time'];
0879 }
0880 $forums[$row['forum_id']]['topic_list'][] = $row['topic_id'];
0881 $forums[$row['forum_id']]['rowset'][$row['topic_id']] = &$rowset[$row['topic_id']];
0882 }
0883 $db->sql_freeresult($result);
0884
0885 // If we have some shadow topics, update the rowset to reflect their topic information
0886 if (sizeof($shadow_topic_list))
0887 {
0888 $sql = 'SELECT *
0889 FROM ' . TOPICS_TABLE . '
0890 WHERE ' . $db->sql_in_set('topic_id', array_keys($shadow_topic_list));
0891 $result = $db->sql_query($sql);
0892
0893 while ($row = $db->sql_fetchrow($result))
0894 {
0895 $orig_topic_id = $shadow_topic_list[$row['topic_id']];
0896
0897 // We want to retain some values
0898 $row = array_merge($row, array(
0899 'topic_moved_id' => $rowset[$orig_topic_id]['topic_moved_id'],
0900 'topic_status' => $rowset[$orig_topic_id]['topic_status'],
0901 'forum_name' => $rowset[$orig_topic_id]['forum_name'])
0902 );
0903
0904 $rowset[$orig_topic_id] = $row;
0905 }
0906 $db->sql_freeresult($result);
0907 }
0908 unset($shadow_topic_list);
0909
0910 foreach ($forums as $forum_id => $forum)
0911 {
0912 if ($user->data['is_registered'] && $config['load_db_lastread'])
0913 {
0914 $topic_tracking_info[$forum_id] = get_topic_tracking($forum_id, $forum['topic_list'], $forum['rowset'], array($forum_id => $forum['mark_time']));
0915 }
0916 else if ($config['load_anon_lastread'] || $user->data['is_registered'])
0917 {
0918 $topic_tracking_info[$forum_id] = get_complete_topic_tracking($forum_id, $forum['topic_list']);
0919
0920 if (!$user->data['is_registered'])
0921 {
0922 $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate']) : 0;
0923 }
0924 }
0925 }
0926 unset($forums);
0927 }
0928 else
0929 {
0930 $text_only_message = '';
0931 $attach_list = array();
0932
0933 while ($row = $db->sql_fetchrow($result))
0934 {
0935 // We pre-process some variables here for later usage
0936 $row['post_text'] = censor_text($row['post_text']);
0937
0938 $text_only_message = $row['post_text'];
0939 // make list items visible as such
0940 if ($row['bbcode_uid'])
0941 {
0942 $text_only_message = str_replace('[*:' . $row['bbcode_uid'] . ']', '⋅ ', $text_only_message);
0943 // no BBCode in text only message
0944 strip_bbcode($text_only_message, $row['bbcode_uid']);
0945 }
0946
0947 if ($return_chars == -1 || utf8_strlen($text_only_message) < ($return_chars + 3))
0948 {
0949 $row['display_text_only'] = false;
0950
0951 // Does this post have an attachment? If so, add it to the list
0952 if ($row['post_attachment'] && $config['allow_attachments'])
0953 {
0954 $attach_list[$row['forum_id']][] = $row['post_id'];
0955 }
0956 }
0957 else
0958 {
0959 $row['post_text'] = $text_only_message;
0960 $row['display_text_only'] = true;
0961 }
0962
0963 $rowset[] = $row;
0964 }
0965 $db->sql_freeresult($result);
0966
0967 unset($text_only_message);
0968
0969 // Pull attachment data
0970 if (sizeof($attach_list))
0971 {
0972 $use_attach_list = $attach_list;
0973 $attach_list = array();
0974
0975 foreach ($use_attach_list as $forum_id => $_list)
0976 {
0977 if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id))
0978 {
0979 $attach_list = array_merge($attach_list, $_list);
0980 }
0981 }
0982 }
0983
0984 if (sizeof($attach_list))
0985 {
0986 $sql = 'SELECT *
0987 FROM ' . ATTACHMENTS_TABLE . '
0988 WHERE ' . $db->sql_in_set('post_msg_id', $attach_list) . '
0989 AND in_message = 0
0990 ORDER BY filetime DESC, post_msg_id ASC';
0991 $result = $db->sql_query($sql);
0992
0993 while ($row = $db->sql_fetchrow($result))
0994 {
0995 $attachments[$row['post_msg_id']][] = $row;
0996 }
0997 $db->sql_freeresult($result);
0998 }
0999 }
1000
1001 if ($hilit)
1002 {
1003 // Remove bad highlights
1004 $hilit_array = array_filter(explode('|', $hilit), 'strlen');
1005 foreach ($hilit_array as $key => $value)
1006 {
1007 $hilit_array[$key] = phpbb_clean_search_string($value);
1008 $hilit_array[$key] = str_replace('\*', '\w*?', preg_quote($hilit_array[$key], '#'));
1009 $hilit_array[$key] = preg_replace('#(^|\s)\\\\w\*\?(\s|$)#', '$1\w+?$2', $hilit_array[$key]);
1010 }
1011 $hilit = implode('|', $hilit_array);
1012 }
1013
1014 /**
1015 * Modify the rowset data
1016 *
1017 * @event core.search_modify_rowset
1018 * @var array attachments Array with posts attachments data
1019 * @var string hilit String to highlight
1020 * @var array rowset Array with the search results data
1021 * @var string show_results String indicating the show results mode
1022 * @var array topic_tracking_info Array with the topics tracking data
1023 * @var string u_hilit Highlight string to be injected into URL
1024 * @var string view Search results view mode
1025 * @var array zebra Array with zebra data for the current user
1026 * @since 3.1.0-b4
1027 * @changed 3.1.0-b5 Added var show_results
1028 */
1029 $vars = array(
1030 'attachments',
1031 'hilit',
1032 'rowset',
1033 'show_results',
1034 'topic_tracking_info',
1035 'u_hilit',
1036 'view',
1037 'zebra',
1038 );
1039 extract($phpbb_dispatcher->trigger_event('core.search_modify_rowset', compact($vars)));
1040
1041 foreach ($rowset as $row)
1042 {
1043 $forum_id = $row['forum_id'];
1044 $result_topic_id = $row['topic_id'];
1045 $topic_title = censor_text($row['topic_title']);
1046 $replies = $phpbb_content_visibility->get_count('topic_posts', $row, $forum_id) - 1;
1047
1048 $view_topic_url_params = "f=$forum_id&t=$result_topic_id" . (($u_hilit) ? "&hilit=$u_hilit" : '');
1049 $view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params);
1050
1051 if ($show_results == 'topics')
1052 {
1053 if ($config['load_db_track'] && $author_id === $user->data['user_id'])
1054 {
1055 $row['topic_posted'] = 1;
1056 }
1057
1058 $folder_img = $folder_alt = $topic_type = '';
1059 topic_status($row, $replies, (isset($topic_tracking_info[$forum_id][$row['topic_id']]) && $row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']]) ? true : false, $folder_img, $folder_alt, $topic_type);
1060
1061 $unread_topic = (isset($topic_tracking_info[$forum_id][$row['topic_id']]) && $row['topic_last_post_time'] > $topic_tracking_info[$forum_id][$row['topic_id']]) ? true : false;
1062
1063 $topic_unapproved = (($row['topic_visibility'] == ITEM_UNAPPROVED || $row['topic_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $forum_id)) ? true : false;
1064 $posts_unapproved = ($row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $auth->acl_get('m_approve', $forum_id)) ? true : false;
1065 $topic_deleted = $row['topic_visibility'] == ITEM_DELETED;
1066 $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . "&t=$result_topic_id", true, $user->session_id) : '';
1067 $u_mcp_queue = (!$u_mcp_queue && $topic_deleted) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&mode=deleted_topics&t=$result_topic_id", true, $user->session_id) : $u_mcp_queue;
1068
1069 $row['topic_title'] = preg_replace('#(?!<.*)(?<!\w)(' . $hilit . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#isu', '<span class="posthilit">$1</span>', $row['topic_title']);
1070
1071 $tpl_ary = array(
1072 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
1073 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
1074 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
1075 'FIRST_POST_TIME' => $user->format_date($row['topic_time']),
1076 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'],
1077 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']),
1078 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']),
1079 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
1080 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
1081 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
1082
1083 'TOPIC_TYPE' => $topic_type,
1084
1085 'TOPIC_IMG_STYLE' => $folder_img,
1086 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt),
1087 'TOPIC_FOLDER_IMG_ALT' => $user->lang[$folder_alt],
1088
1089 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '',
1090 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '',
1091 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '',
1092 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
1093 'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '',
1094
1095 'S_TOPIC_TYPE' => $row['topic_type'],
1096 'S_USER_POSTED' => (!empty($row['topic_posted'])) ? true : false,
1097 'S_UNREAD_TOPIC' => $unread_topic,
1098
1099 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && $auth->acl_get('m_report', $forum_id)) ? true : false,
1100 'S_TOPIC_UNAPPROVED' => $topic_unapproved,
1101 'S_POSTS_UNAPPROVED' => $posts_unapproved,
1102 'S_TOPIC_DELETED' => $topic_deleted,
1103 'S_HAS_POLL' => ($row['poll_start']) ? true : false,
1104
1105 'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'],
1106 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
1107 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
1108 'U_NEWEST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&view=unread') . '#unread',
1109 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=reports&t=' . $result_topic_id, true, $user->session_id),
1110 'U_MCP_QUEUE' => $u_mcp_queue,
1111 );
1112 }
1113 else
1114 {
1115 if ((isset($zebra['foe']) && in_array($row['poster_id'], $zebra['foe'])) && (!$view || $view != 'show' || $post_id != $row['post_id']))
1116 {
1117 $template->assign_block_vars('searchresults', array(
1118 'S_IGNORE_POST' => true,
1119
1120 'L_IGNORE_POST' => sprintf($user->lang['POST_BY_FOE'], $row['username'], "<a href=\"$u_search&start=$start&p=" . $row['post_id'] . '&view=show#p' . $row['post_id'] . '">', '</a>'))
1121 );
1122
1123 continue;
1124 }
1125
1126 // Replace naughty words such as farty pants
1127 $row['post_subject'] = censor_text($row['post_subject']);
1128
1129 if ($row['display_text_only'])
1130 {
1131 // now find context for the searched words
1132 $row['post_text'] = get_context($row['post_text'], array_filter(explode('|', $hilit), 'strlen'), $return_chars);
1133 $row['post_text'] = bbcode_nl2br($row['post_text']);
1134 }
1135 else
1136 {
1137 $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES;
1138 $row['post_text'] = generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, false);
1139
1140 if (!empty($attachments[$row['post_id']]))
1141 {
1142 parse_attachments($forum_id, $row['post_text'], $attachments[$row['post_id']], $update_count);
1143
1144 // we only display inline attachments
1145 unset($attachments[$row['post_id']]);
1146 }
1147 }
1148
1149 if ($hilit)
1150 {
1151 // post highlighting
1152 $row['post_text'] = preg_replace('#(?!<.*)(?<!\w)(' . $hilit . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#isu', '<span class="posthilit">$1</span>', $row['post_text']);
1153 $row['post_subject'] = preg_replace('#(?!<.*)(?<!\w)(' . $hilit . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#isu', '<span class="posthilit">$1</span>', $row['post_subject']);
1154 }
1155
1156 $tpl_ary = array(
1157 'POST_AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']),
1158 'POST_AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']),
1159 'POST_AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']),
1160 'U_POST_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']),
1161
1162 'POST_SUBJECT' => $row['post_subject'],
1163 'POST_DATE' => (!empty($row['post_time'])) ? $user->format_date($row['post_time']) : '',
1164 'MESSAGE' => $row['post_text']
1165 );
1166 }
1167
1168 $tpl_ary = array_merge($tpl_ary, array(
1169 'FORUM_ID' => $forum_id,
1170 'TOPIC_ID' => $result_topic_id,
1171 'POST_ID' => ($show_results == 'posts') ? $row['post_id'] : false,
1172
1173 'FORUM_TITLE' => $row['forum_name'],
1174 'TOPIC_TITLE' => $topic_title,
1175 'TOPIC_REPLIES' => $replies,
1176 'TOPIC_VIEWS' => $row['topic_views'],
1177
1178 'U_VIEW_TOPIC' => $view_topic_url,
1179 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id),
1180 'U_VIEW_POST' => (!empty($row['post_id'])) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=" . $row['topic_id'] . '&p=' . $row['post_id'] . (($u_hilit) ? '&hilit=' . $u_hilit : '')) . '#p' . $row['post_id'] : '',
1181 ));
1182
1183 /**
1184 * Modify the topic data before it is assigned to the template
1185 *
1186 * @event core.search_modify_tpl_ary
1187 * @var array row Array with topic data
1188 * @var array tpl_ary Template block array with topic data
1189 * @var string show_results Display topics or posts
1190 * @var string topic_title Cleaned topic title
1191 * @var int replies The number of topic replies
1192 * @var string view_topic_url The URL to the topic
1193 * @var string folder_img The folder image of the topic
1194 * @var string folder_alt The alt attribute of the topic folder img
1195 * @var int topic_type The topic type
1196 * @var bool unread_topic Whether the topic has unread posts
1197 * @var bool topic_unapproved Whether the topic is unapproved
1198 * @var int posts_unapproved The number of unapproved posts
1199 * @var bool topic_deleted Whether the topic has been deleted
1200 * @var string u_mcp_queue The URL to the corresponding MCP queue page
1201 * @var array zebra The zebra data of the current user
1202 * @var array attachments All the attachments of the search results
1203 * @since 3.1.0-a1
1204 * @changed 3.1.0-b3 Added vars show_results, topic_title, replies,
1205 * view_topic_url, folder_img, folder_alt, topic_type, unread_topic,
1206 * topic_unapproved, posts_unapproved, topic_deleted, u_mcp_queue,
1207 * zebra, attachments
1208 */
1209 $vars = array(
1210 'row',
1211 'tpl_ary',
1212 'show_results',
1213 'topic_title',
1214 'replies',
1215 'view_topic_url',
1216 'folder_img',
1217 'folder_alt',
1218 'topic_type',
1219 'unread_topic',
1220 'topic_unapproved',
1221 'posts_unapproved',
1222 'topic_deleted',
1223 'u_mcp_queue',
1224 'zebra',
1225 'attachments',
1226 );
1227 extract($phpbb_dispatcher->trigger_event('core.search_modify_tpl_ary', compact($vars)));
1228
1229 $template->assign_block_vars('searchresults', $tpl_ary);
1230
1231 if ($show_results == 'topics')
1232 {
1233 $pagination->generate_template_pagination($view_topic_url, 'searchresults.pagination', 'start', $replies + 1, $config['posts_per_page'], 1, true, true);
1234 }
1235 }
1236
1237 if ($topic_id && ($topic_id == $result_topic_id))
1238 {
1239 $template->assign_vars(array(
1240 'SEARCH_TOPIC' => $topic_title,
1241 'L_RETURN_TO_TOPIC' => $user->lang('RETURN_TO', $topic_title),
1242 'U_SEARCH_TOPIC' => $view_topic_url
1243 ));
1244 }
1245 }
1246 unset($rowset);
1247
1248 // Output header
1249 if ($found_more_search_matches)
1250 {
1251 $l_search_matches = $user->lang('FOUND_MORE_SEARCH_MATCHES', (int) $total_match_count);
1252 }
1253 else
1254 {
1255 $l_search_matches = $user->lang('FOUND_SEARCH_MATCHES', (int) $total_match_count);
1256 }
1257
1258 // Check if search backend supports phrase search or not
1259 $phrase_search_disabled = '';
1260 if (strpos(html_entity_decode($keywords), '"') !== false && method_exists($search, 'supports_phrase_search'))
1261 {
1262 $phrase_search_disabled = $search->supports_phrase_search() ? false : true;
1263 }
1264
1265 $pagination->generate_template_pagination($u_search, 'pagination', 'start', $total_match_count, $per_page, $start);
1266
1267 $template->assign_vars(array(
1268 'SEARCH_TITLE' => $l_search_title,
1269 'SEARCH_MATCHES' => $l_search_matches,
1270 'SEARCH_WORDS' => $keywords,
1271 'SEARCHED_QUERY' => $search->get_search_query(),
1272 'IGNORED_WORDS' => (!empty($common_words)) ? implode(' ', $common_words) : '',
1273
1274 'PHRASE_SEARCH_DISABLED' => $phrase_search_disabled,
1275
1276 'TOTAL_MATCHES' => $total_match_count,
1277 'SEARCH_IN_RESULTS' => ($search_id) ? false : true,
1278
1279 'S_SELECT_SORT_DIR' => $s_sort_dir,
1280 'S_SELECT_SORT_KEY' => $s_sort_key,
1281 'S_SELECT_SORT_DAYS' => $s_limit_days,
1282 'S_SEARCH_ACTION' => $u_search,
1283 'S_SHOW_TOPICS' => ($show_results == 'posts') ? false : true,
1284
1285 'GOTO_PAGE_IMG' => $user->img('icon_post_target', 'GOTO_PAGE'),
1286 'NEWEST_POST_IMG' => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'),
1287 'REPORTED_IMG' => $user->img('icon_topic_reported', 'TOPIC_REPORTED'),
1288 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'TOPIC_UNAPPROVED'),
1289 'DELETED_IMG' => $user->img('icon_topic_deleted', 'TOPIC_DELETED'),
1290 'POLL_IMG' => $user->img('icon_topic_poll', 'TOPIC_POLL'),
1291 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'),
1292
1293 'U_SEARCH_WORDS' => $u_search,
1294 ));
1295
1296 /**
1297 * Modify the title and/or load data for the search results page
1298 *
1299 * @event core.search_results_modify_search_title
1300 * @var int author_id ID of the author to search by
1301 * @var string l_search_title The title of the search page
1302 * @var string search_id Predefined search type name
1303 * @var string show_results Search results output mode - topics or posts
1304 * @var int start The starting id of the results
1305 * @var int total_match_count The count of search results
1306 * @var string keywords The search keywords
1307 * @since 3.1.0-RC4
1308 * @changed 3.1.6-RC1 Added total_match_count and keywords
1309 */
1310 $vars = array(
1311 'author_id',
1312 'l_search_title',
1313 'search_id',
1314 'show_results',
1315 'start',
1316 'total_match_count',
1317 'keywords',
1318 );
1319 extract($phpbb_dispatcher->trigger_event('core.search_results_modify_search_title', compact($vars)));
1320
1321 page_header(($l_search_title) ? $l_search_title : $user->lang['SEARCH']);
1322
1323 $template->set_filenames(array(
1324 'body' => 'search_results.html')
1325 );
1326 make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"));
1327
1328 page_footer();
1329 }
1330
1331 // Search forum
1332 $rowset = array();
1333 $s_forums = '';
1334 $sql = 'SELECT f.forum_id, f.forum_name, f.parent_id, f.forum_type, f.left_id, f.right_id, f.forum_password, f.enable_indexing, fa.user_id
1335 FROM ' . FORUMS_TABLE . ' f
1336 LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa ON (fa.forum_id = f.forum_id
1337 AND fa.session_id = '" . $db->sql_escape($user->session_id) . "')
1338 ORDER BY f.left_id ASC";
1339 $result = $db->sql_query($sql);
1340
1341 while ($row = $db->sql_fetchrow($result))
1342 {
1343 $rowset[(int) $row['forum_id']] = $row;
1344 }
1345 $db->sql_freeresult($result);
1346
1347 $right = $cat_right = $padding_inc = 0;
1348 $padding = $forum_list = $holding = '';
1349 $pad_store = array('0' => '');
1350
1351 /**
1352 * Modify the forum select list for advanced search page
1353 *
1354 * @event core.search_modify_forum_select_list
1355 * @var array rowset Array with the forums list data
1356 * @since 3.1.10-RC1
1357 */
1358 $vars = array('rowset');
1359 extract($phpbb_dispatcher->trigger_event('core.search_modify_forum_select_list', compact($vars)));
1360
1361 foreach ($rowset as $row)
1362 {
1363 if ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id']))
1364 {
1365 // Non-postable forum with no subforums, don't display
1366 continue;
1367 }
1368
1369 if ($row['forum_type'] == FORUM_POST && ($row['left_id'] + 1 == $row['right_id']) && !$row['enable_indexing'])
1370 {
1371 // Postable forum with no subforums and indexing disabled, don't display
1372 continue;
1373 }
1374
1375 if ($row['forum_type'] == FORUM_LINK || ($row['forum_password'] && !$row['user_id']))
1376 {
1377 // if this forum is a link or password protected (user has not entered the password yet) then skip to the next branch
1378 continue;
1379 }
1380
1381 if ($row['left_id'] < $right)
1382 {
1383 $padding .= ' ';
1384 $pad_store[$row['parent_id']] = $padding;
1385 }
1386 else if ($row['left_id'] > $right + 1)
1387 {
1388 if (isset($pad_store[$row['parent_id']]))
1389 {
1390 $padding = $pad_store[$row['parent_id']];
1391 }
1392 else
1393 {
1394 continue;
1395 }
1396 }
1397
1398 $right = $row['right_id'];
1399
1400 if ($auth->acl_gets('!f_search', '!f_list', $row['forum_id']))
1401 {
1402 // if the user does not have permissions to search or see this forum skip only this forum/category
1403 continue;
1404 }
1405
1406 $selected = (in_array($row['forum_id'], $search_forum)) ? ' selected="selected"' : '';
1407
1408 if ($row['left_id'] > $cat_right)
1409 {
1410 // make sure we don't forget anything
1411 $s_forums .= $holding;
1412 $holding = '';
1413 }
1414
1415 if ($row['right_id'] - $row['left_id'] > 1)
1416 {
1417 $cat_right = max($cat_right, $row['right_id']);
1418
1419 $holding .= '<option value="' . $row['forum_id'] . '"' . $selected . '>' . $padding . $row['forum_name'] . '</option>';
1420 }
1421 else
1422 {
1423 $s_forums .= $holding . '<option value="' . $row['forum_id'] . '"' . $selected . '>' . $padding . $row['forum_name'] . '</option>';
1424 $holding = '';
1425 }
1426 }
1427
1428 if ($holding)
1429 {
1430 $s_forums .= $holding;
1431 }
1432
1433 unset($pad_store);
1434 unset($rowset);
1435
1436 if (!$s_forums)
1437 {
1438 trigger_error('NO_SEARCH');
1439 }
1440
1441 // Number of chars returned
1442 $s_characters = '<option value="-1">' . $user->lang['ALL_AVAILABLE'] . '</option>';
1443 $s_characters .= '<option value="0">0</option>';
1444 $s_characters .= '<option value="25">25</option>';
1445 $s_characters .= '<option value="50">50</option>';
1446
1447 for ($i = 100; $i <= 1000; $i += 100)
1448 {
1449 $selected = ($i == 300) ? ' selected="selected"' : '';
1450 $s_characters .= '<option value="' . $i . '"' . $selected . '>' . $i . '</option>';
1451 }
1452
1453 $s_hidden_fields = array('t' => $topic_id);
1454
1455 if ($_SID)
1456 {
1457 $s_hidden_fields['sid'] = $_SID;
1458 }
1459
1460 if (!empty($_EXTRA_URL))
1461 {
1462 foreach ($_EXTRA_URL as $url_param)
1463 {
1464 $url_param = explode('=', $url_param, 2);
1465 $s_hidden_fields[$url_param[0]] = $url_param[1];
1466 }
1467 }
1468
1469 $template->assign_vars(array(
1470 'S_SEARCH_ACTION' => append_sid("{$phpbb_root_path}search.$phpEx", false, true, 0), // We force no ?sid= appending by using 0
1471 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields),
1472 'S_CHARACTER_OPTIONS' => $s_characters,
1473 'S_FORUM_OPTIONS' => $s_forums,
1474 'S_SELECT_SORT_DIR' => $s_sort_dir,
1475 'S_SELECT_SORT_KEY' => $s_sort_key,
1476 'S_SELECT_SORT_DAYS' => $s_limit_days,
1477 'S_IN_SEARCH' => true,
1478 ));
1479
1480 // only show recent searches to search administrators
1481 if ($auth->acl_get('a_search'))
1482 {
1483 // Handle large objects differently for Oracle and MSSQL
1484 switch ($db->get_sql_layer())
1485 {
1486 case 'oracle':
1487 $sql = 'SELECT search_time, search_keywords
1488 FROM ' . SEARCH_RESULTS_TABLE . '
1489 WHERE dbms_lob.getlength(search_keywords) > 0
1490 ORDER BY search_time DESC';
1491 break;
1492
1493 case 'mssql_odbc':
1494 case 'mssqlnative':
1495 $sql = 'SELECT search_time, search_keywords
1496 FROM ' . SEARCH_RESULTS_TABLE . '
1497 WHERE DATALENGTH(search_keywords) > 0
1498 ORDER BY search_time DESC';
1499 break;
1500
1501 default:
1502 $sql = 'SELECT search_time, search_keywords
1503 FROM ' . SEARCH_RESULTS_TABLE . '
1504 WHERE search_keywords <> \'\'
1505 ORDER BY search_time DESC';
1506 break;
1507 }
1508 $result = $db->sql_query_limit($sql, 5);
1509
1510 while ($row = $db->sql_fetchrow($result))
1511 {
1512 $keywords = $row['search_keywords'];
1513
1514 $template->assign_block_vars('recentsearch', array(
1515 'KEYWORDS' => $keywords,
1516 'TIME' => $user->format_date($row['search_time']),
1517
1518 'U_KEYWORDS' => append_sid("{$phpbb_root_path}search.$phpEx", 'keywords=' . urlencode(htmlspecialchars_decode($keywords)))
1519 ));
1520 }
1521 $db->sql_freeresult($result);
1522 }
1523
1524 // Output the basic page
1525 page_header($user->lang['SEARCH']);
1526
1527 $template->set_filenames(array(
1528 'body' => 'search_body.html')
1529 );
1530 make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"));
1531
1532 page_footer();
1533