[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * This file is part of the phpBB Forum Software package. 5 * 6 * @copyright (c) phpBB Limited <https://www.phpbb.com> 7 * @license GNU General Public License, version 2 (GPL-2.0) 8 * 9 * For full copyright and license information, please see 10 * the docs/CREDITS.txt file. 11 * 12 */ 13 14 /** 15 * @ignore 16 */ 17 define('IN_PHPBB', true); 18 $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './'; 19 $phpEx = substr(strrchr(__FILE__, '.'), 1); 20 include($phpbb_root_path . 'common.' . $phpEx); 21 22 // Start session management 23 $user->session_begin(); 24 $auth->acl($user->data); 25 $user->setup('search'); 26 27 // Define initial vars 28 $mode = $request->variable('mode', ''); 29 $search_id = $request->variable('search_id', ''); 30 $start = max($request->variable('start', 0), 0); 31 $post_id = $request->variable('p', 0); 32 $topic_id = $request->variable('t', 0); 33 $view = $request->variable('view', ''); 34 35 $submit = $request->variable('submit', false); 36 $keywords = $request->variable('keywords', '', true); 37 $add_keywords = $request->variable('add_keywords', '', true); 38 $author = $request->variable('author', '', true); 39 $author_id = $request->variable('author_id', 0); 40 $show_results = ($topic_id) ? 'posts' : $request->variable('sr', 'posts'); 41 $show_results = ($show_results == 'posts') ? 'posts' : 'topics'; 42 $search_terms = $request->variable('terms', 'all'); 43 $search_fields = $request->variable('sf', 'all'); 44 $search_child = $request->variable('sc', true); 45 46 $sort_days = $request->variable('st', 0); 47 $sort_key = $request->variable('sk', 't'); 48 $sort_dir = $request->variable('sd', 'd'); 49 50 $return_chars = $request->variable('ch', $topic_id ? 0 : (int) $config['default_search_return_chars']); 51 $search_forum = $request->variable('fid', array(0)); 52 53 // We put login boxes for the case if search_id is newposts, egosearch or unreadposts 54 // because a guest should be able to log in even if guests search is not permitted 55 56 switch ($search_id) 57 { 58 // Egosearch is an author search 59 case 'egosearch': 60 $author_id = $user->data['user_id']; 61 if ($user->data['user_id'] == ANONYMOUS) 62 { 63 login_box('', $user->lang['LOGIN_EXPLAIN_EGOSEARCH']); 64 } 65 break; 66 67 // Search for unread posts needs to be allowed and user to be logged in if topics tracking for guests is disabled 68 case 'unreadposts': 69 if (!$config['load_unreads_search']) 70 { 71 $template->assign_var('S_NO_SEARCH', true); 72 trigger_error('NO_SEARCH_UNREADS'); 73 } 74 else if (!$config['load_anon_lastread'] && !$user->data['is_registered']) 75 { 76 login_box('', $user->lang['LOGIN_EXPLAIN_UNREADSEARCH']); 77 } 78 break; 79 80 // The "new posts" search uses user_lastvisit which is user based, so it should require user to log in. 81 case 'newposts': 82 if ($user->data['user_id'] == ANONYMOUS) 83 { 84 login_box('', $user->lang['LOGIN_EXPLAIN_NEWPOSTS']); 85 } 86 break; 87 88 default: 89 // There's nothing to do here for now ;) 90 break; 91 } 92 93 $search_auth_check_override = false; 94 /** 95 * This event allows you to override search auth checks 96 * 97 * @event core.search_auth_check_override 98 * @var bool search_auth_check_override Whether or not the search auth check overridden 99 * @since 3.3.14-RC1 100 */ 101 $vars = [ 102 'search_auth_check_override', 103 ]; 104 extract($phpbb_dispatcher->trigger_event('core.search_auth_check_override', compact($vars))); 105 106 // Is user able to search? Has search been disabled? 107 if (!$search_auth_check_override && (!$auth->acl_get('u_search') || !$auth->acl_getf_global('f_search') || !$config['load_search'])) 108 { 109 $template->assign_var('S_NO_SEARCH', true); 110 trigger_error('NO_SEARCH'); 111 } 112 113 // Check search load limit 114 if ($user->load && $config['limit_search_load'] && ($user->load > doubleval($config['limit_search_load']))) 115 { 116 $template->assign_var('S_NO_SEARCH', true); 117 trigger_error('NO_SEARCH_LOAD'); 118 } 119 120 // It is applicable if the configuration setting is non-zero, and the user cannot 121 // ignore the flood setting, and the search is a keyword search. 122 $interval = ($user->data['user_id'] == ANONYMOUS) ? $config['search_anonymous_interval'] : $config['search_interval']; 123 if ($interval && !in_array($search_id, array('unreadposts', 'unanswered', 'active_topics', 'egosearch')) && !$auth->acl_get('u_ignoreflood')) 124 { 125 if ($user->data['user_last_search'] > time() - $interval) 126 { 127 $template->assign_var('S_NO_SEARCH', true); 128 trigger_error($user->lang('NO_SEARCH_TIME', (int) ($user->data['user_last_search'] + $interval - time()))); 129 } 130 } 131 132 // Define some vars 133 $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']); 134 $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']); 135 136 $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; 137 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); 138 139 /* @var $phpbb_content_visibility \phpbb\content_visibility */ 140 $phpbb_content_visibility = $phpbb_container->get('content.visibility'); 141 142 /* @var $pagination \phpbb\pagination */ 143 $pagination = $phpbb_container->get('pagination'); 144 145 $template->assign_block_vars('navlinks', array( 146 'BREADCRUMB_NAME' => $user->lang('SEARCH'), 147 'U_BREADCRUMB' => append_sid("{$phpbb_root_path}search.$phpEx"), 148 )); 149 150 /** 151 * This event allows you to alter the above parameters, such as keywords and submit 152 * 153 * @event core.search_modify_submit_parameters 154 * @var string keywords The search keywords 155 * @var string author Specifies the author match, when ANONYMOUS is also a search-match 156 * @var int author_id ID of the author to search by 157 * @var string search_id Predefined search type name 158 * @var bool submit Whether or not the form has been submitted 159 * @since 3.1.10-RC1 160 */ 161 $vars = array( 162 'keywords', 163 'author', 164 'author_id', 165 'search_id', 166 'submit', 167 ); 168 extract($phpbb_dispatcher->trigger_event('core.search_modify_submit_parameters', compact($vars))); 169 170 if ($keywords || $author || $author_id || $search_id || $submit) 171 { 172 // clear arrays 173 $id_ary = array(); 174 175 // If we are looking for authors get their ids 176 $author_id_ary = array(); 177 $sql_author_match = ''; 178 if ($author_id) 179 { 180 $author_id_ary[] = $author_id; 181 } 182 else if ($author) 183 { 184 if ((strpos($author, '*') !== false) && (utf8_strlen(str_replace(array('*', '%'), '', $author)) < $config['min_search_author_chars'])) 185 { 186 trigger_error($user->lang('TOO_FEW_AUTHOR_CHARS', (int) $config['min_search_author_chars'])); 187 } 188 189 $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)) . "'"; 190 191 $sql = 'SELECT user_id 192 FROM ' . USERS_TABLE . " 193 WHERE $sql_where 194 AND user_type <> " . USER_IGNORE; 195 $result = $db->sql_query_limit($sql, 100); 196 197 while ($row = $db->sql_fetchrow($result)) 198 { 199 $author_id_ary[] = (int) $row['user_id']; 200 } 201 $db->sql_freeresult($result); 202 203 $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)) . "'"; 204 205 $sql = 'SELECT 1 as guest_post 206 FROM ' . POSTS_TABLE . " 207 WHERE $sql_where 208 AND poster_id = " . ANONYMOUS; 209 $result = $db->sql_query_limit($sql, 1); 210 $found_guest_post = $db->sql_fetchfield('guest_post'); 211 $db->sql_freeresult($result); 212 213 if ($found_guest_post) 214 { 215 $author_id_ary[] = ANONYMOUS; 216 $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)) . "'"; 217 } 218 219 if (!count($author_id_ary)) 220 { 221 trigger_error('NO_SEARCH_RESULTS'); 222 } 223 } 224 225 // if we search in an existing search result just add the additional keywords. But we need to use "all search terms"-mode 226 // so we can keep the old keywords in their old mode, but add the new ones as required words 227 if ($add_keywords) 228 { 229 if ($search_terms == 'all') 230 { 231 $keywords .= ' ' . $add_keywords; 232 } 233 else 234 { 235 $search_terms = 'all'; 236 $keywords = implode(' |', explode(' ', preg_replace('#\s+#u', ' ', $keywords))) . ' ' .$add_keywords; 237 } 238 } 239 240 // Which forums should not be searched? Author searches are also carried out in unindexed forums 241 if (empty($keywords) && count($author_id_ary)) 242 { 243 $ex_fid_ary = array_keys($auth->acl_getf('!f_read', true)); 244 } 245 else 246 { 247 $ex_fid_ary = array_unique(array_merge(array_keys($auth->acl_getf('!f_read', true)), array_keys($auth->acl_getf('!f_search', true)))); 248 } 249 250 $not_in_fid = (count($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'] . ')' : ""; 251 252 $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 253 FROM ' . FORUMS_TABLE . ' f 254 LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa ON (fa.forum_id = f.forum_id 255 AND fa.session_id = '" . $db->sql_escape($user->session_id) . "') 256 $not_in_fid 257 ORDER BY f.left_id"; 258 $result = $db->sql_query($sql); 259 260 $right_id = 0; 261 $reset_search_forum = true; 262 while ($row = $db->sql_fetchrow($result)) 263 { 264 if ($row['forum_password'] && $row['user_id'] != $user->data['user_id']) 265 { 266 $ex_fid_ary[] = (int) $row['forum_id']; 267 continue; 268 } 269 270 // Exclude forums from active topics 271 if (!($row['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) && ($search_id == 'active_topics')) 272 { 273 $ex_fid_ary[] = (int) $row['forum_id']; 274 continue; 275 } 276 277 if (count($search_forum)) 278 { 279 if ($search_child) 280 { 281 if (in_array($row['forum_id'], $search_forum) && $row['right_id'] > $right_id) 282 { 283 $right_id = (int) $row['right_id']; 284 } 285 else if ($row['right_id'] < $right_id) 286 { 287 continue; 288 } 289 } 290 291 if (!in_array($row['forum_id'], $search_forum)) 292 { 293 $ex_fid_ary[] = (int) $row['forum_id']; 294 $reset_search_forum = false; 295 } 296 } 297 } 298 $db->sql_freeresult($result); 299 300 // find out in which forums the user is allowed to view posts 301 $m_approve_posts_fid_sql = $phpbb_content_visibility->get_global_visibility_sql('post', $ex_fid_ary, 'p.'); 302 $m_approve_topics_fid_sql = $phpbb_content_visibility->get_global_visibility_sql('topic', $ex_fid_ary, 't.'); 303 304 if ($reset_search_forum) 305 { 306 $search_forum = array(); 307 } 308 309 // Select which method we'll use to obtain the post_id or topic_id information 310 $search_type = $config['search_type']; 311 312 if (!class_exists($search_type)) 313 { 314 trigger_error('NO_SUCH_SEARCH_MODULE'); 315 } 316 // We do some additional checks in the module to ensure it can actually be utilised 317 $error = false; 318 $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); 319 320 if ($error) 321 { 322 trigger_error($error); 323 } 324 325 // let the search module split up the keywords 326 if ($keywords) 327 { 328 $correct_query = $search->split_keywords($keywords, $search_terms); 329 $common_words = $search->get_common_words(); 330 if (!$correct_query || (!$search->get_search_query() && !count($author_id_ary) && !$search_id)) 331 { 332 $ignored = (count($common_words)) ? sprintf($user->lang['IGNORED_TERMS_EXPLAIN'], implode(' ', $common_words)) . '<br />' : ''; 333 $word_length = $search->get_word_length(); 334 if ($word_length) 335 { 336 trigger_error($ignored . $user->lang('NO_KEYWORDS', $user->lang('CHARACTERS', (int) $word_length['min']), $user->lang('CHARACTERS', (int) $word_length['max']))); 337 } 338 else 339 { 340 trigger_error($ignored); 341 } 342 } 343 } 344 345 if (!$keywords && count($author_id_ary)) 346 { 347 // if it is an author search we want to show topics by default 348 $show_results = ($topic_id) ? 'posts' : $request->variable('sr', ($search_id == 'egosearch') ? 'topics' : 'posts'); 349 $show_results = ($show_results == 'posts') ? 'posts' : 'topics'; 350 } 351 352 // define some variables needed for retrieving post_id/topic_id information 353 $sort_by_sql = [ 354 'a' => 'u.username_clean', 355 't' => (($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time'), 356 'f' => 'f.forum_id', 357 'i' => 't.topic_title', 358 's' => (($show_results == 'posts') ? 'p.post_subject' : 't.topic_title') 359 ]; 360 361 /** 362 * Event to modify the SQL parameters before pre-made searches 363 * 364 * @event core.search_modify_param_before 365 * @var string keywords String of the specified keywords 366 * @var array sort_by_sql Array of SQL sorting instructions 367 * @var array ex_fid_ary Array of excluded forum ids 368 * @var array author_id_ary Array of exclusive author ids 369 * @var string search_id The id of the search request 370 * @var array id_ary Array of post or topic ids for search result 371 * @var string show_results 'posts' or 'topics' type of ids 372 * @since 3.1.3-RC1 373 * @changed 3.1.10-RC1 Added id_ary, show_results 374 */ 375 $vars = array( 376 'keywords', 377 'sort_by_sql', 378 'ex_fid_ary', 379 'author_id_ary', 380 'search_id', 381 'id_ary', 382 'show_results', 383 ); 384 extract($phpbb_dispatcher->trigger_event('core.search_modify_param_before', compact($vars))); 385 386 // pre-made searches 387 $sql = $field = $l_search_title = ''; 388 if ($search_id) 389 { 390 switch ($search_id) 391 { 392 // Oh holy Bob, bring us some activity... 393 case 'active_topics': 394 $l_search_title = $user->lang['SEARCH_ACTIVE_TOPICS']; 395 $show_results = 'topics'; 396 $sort_key = 't'; 397 $sort_dir = 'd'; 398 $sort_days = $request->variable('st', 7); 399 $sort_by_sql['t'] = 't.topic_last_post_time'; 400 401 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); 402 $s_sort_key = $s_sort_dir = ''; 403 404 $last_post_time_sql = ($sort_days) ? ' AND t.topic_last_post_time > ' . (time() - ($sort_days * 24 * 3600)) : ''; 405 406 $sql = 'SELECT t.topic_last_post_time, t.topic_id 407 FROM ' . TOPICS_TABLE . " t 408 WHERE t.topic_moved_id = 0 409 $last_post_time_sql 410 AND " . $m_approve_topics_fid_sql . ' 411 ' . ((count($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . ' 412 ORDER BY t.topic_last_post_time DESC'; 413 $field = 'topic_id'; 414 break; 415 416 case 'unanswered': 417 $l_search_title = $user->lang['SEARCH_UNANSWERED']; 418 $show_results = $request->variable('sr', 'topics'); 419 $show_results = ($show_results == 'posts') ? 'posts' : 'topics'; 420 $sort_by_sql['t'] = ($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time'; 421 $sort_by_sql['s'] = ($show_results == 'posts') ? 'p.post_subject' : 't.topic_title'; 422 $sql_sort = 'ORDER BY ' . $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); 423 424 $sort_join = ($sort_key == 'f') ? FORUMS_TABLE . ' f, ' : ''; 425 $sql_sort = ($sort_key == 'f') ? ' AND f.forum_id = t.forum_id ' . $sql_sort : $sql_sort; 426 427 if ($sort_days) 428 { 429 $last_post_time = 'AND ' . ($show_results == 'posts' ? 'p.post_time' : 't.topic_last_post_time') . ' > ' . (time() - ($sort_days * 24 * 3600)); 430 } 431 else 432 { 433 $last_post_time = ''; 434 } 435 436 if ($sort_key == 'a') 437 { 438 $sort_join = USERS_TABLE . ' u, '; 439 $sql_sort = ' AND u.user_id = ' . ($show_results == 'posts' ? 'p.poster_id ' : 't.topic_last_poster_id ') . $sql_sort; 440 } 441 if ($show_results == 'posts') 442 { 443 $sql = "SELECT p.post_id 444 FROM $sort_join" . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t 445 WHERE t.topic_posts_approved = 1 446 AND p.topic_id = t.topic_id 447 $last_post_time 448 AND $m_approve_posts_fid_sql 449 " . ((count($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . " 450 $sql_sort"; 451 $field = 'post_id'; 452 } 453 else 454 { 455 $sql = 'SELECT DISTINCT ' . $sort_by_sql[$sort_key] . ", t.topic_id 456 FROM $sort_join" . TOPICS_TABLE . " t 457 WHERE t.topic_posts_approved = 1 458 AND t.topic_moved_id = 0 459 $last_post_time 460 AND $m_approve_topics_fid_sql 461 " . ((count($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . " 462 $sql_sort"; 463 $field = 'topic_id'; 464 } 465 break; 466 467 case 'unreadposts': 468 $l_search_title = $user->lang['SEARCH_UNREAD']; 469 // force sorting 470 $show_results = 'topics'; 471 $sort_key = 't'; 472 $sort_by_sql['t'] = 't.topic_last_post_time'; 473 $sql_sort = 'ORDER BY ' . $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); 474 475 $sql_where = 'AND t.topic_moved_id = 0 476 AND ' . $m_approve_topics_fid_sql . ' 477 ' . ((count($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : ''); 478 479 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); 480 $s_sort_key = $s_sort_dir = $u_sort_param = $s_limit_days = ''; 481 482 $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()) : ''); 483 break; 484 485 case 'newposts': 486 $l_search_title = $user->lang['SEARCH_NEW']; 487 // force sorting 488 $show_results = ($request->variable('sr', 'topics') == 'posts') ? 'posts' : 'topics'; 489 $sort_key = 't'; 490 $sort_dir = 'd'; 491 $sort_by_sql['t'] = ($show_results == 'posts') ? 'p.post_time' : 't.topic_last_post_time'; 492 $sql_sort = 'ORDER BY ' . $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); 493 494 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); 495 $s_sort_key = $s_sort_dir = $u_sort_param = $s_limit_days = ''; 496 497 if ($show_results == 'posts') 498 { 499 $sql = 'SELECT p.post_id 500 FROM ' . POSTS_TABLE . ' p 501 WHERE p.post_time > ' . $user->data['user_lastvisit'] . ' 502 AND ' . $m_approve_posts_fid_sql . ' 503 ' . ((count($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . " 504 $sql_sort"; 505 $field = 'post_id'; 506 } 507 else 508 { 509 $sql = 'SELECT t.topic_id 510 FROM ' . TOPICS_TABLE . ' t 511 WHERE t.topic_last_post_time > ' . $user->data['user_lastvisit'] . ' 512 AND t.topic_moved_id = 0 513 AND ' . $m_approve_topics_fid_sql . ' 514 ' . ((count($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . " 515 $sql_sort"; 516 /* 517 [Fix] queued replies missing from "view new posts" (Bug #42705 - Patch by Paul) 518 - Creates temporary table, query is far from optimized 519 520 $sql = 'SELECT t.topic_id 521 FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p 522 WHERE p.post_time > ' . $user->data['user_lastvisit'] . ' 523 AND t.topic_id = p.topic_id 524 AND t.topic_moved_id = 0 525 AND ' . $m_approve_topics_fid_sql . " 526 GROUP BY t.topic_id 527 $sql_sort"; 528 */ 529 $field = 'topic_id'; 530 } 531 break; 532 533 case 'egosearch': 534 $l_search_title = $user->lang['SEARCH_SELF']; 535 break; 536 } 537 538 $template->assign_block_vars('navlinks', array( 539 'BREADCRUMB_NAME' => $l_search_title, 540 'U_BREADCRUMB' => append_sid("{$phpbb_root_path}search.$phpEx", "search_id=$search_id"), 541 )); 542 } 543 544 /** 545 * Event to modify data after pre-made searches 546 * 547 * @event core.search_modify_param_after 548 * @var string l_search_title The title of the search page 549 * @var string search_id Predefined search type name 550 * @var string show_results Display topics or posts 551 * @var string sql SQL query corresponding to the pre-made search id 552 * @since 3.1.7-RC1 553 */ 554 $vars = array( 555 'l_search_title', 556 'search_id', 557 'show_results', 558 'sql', 559 ); 560 extract($phpbb_dispatcher->trigger_event('core.search_modify_param_after', compact($vars))); 561 562 // show_results should not change after this 563 $per_page = ($show_results == 'posts') ? $config['posts_per_page'] : $config['topics_per_page']; 564 $total_match_count = 0; 565 566 // Set limit for the $total_match_count to reduce server load 567 $total_matches_limit = 1000; 568 $found_more_search_matches = false; 569 570 if ($search_id) 571 { 572 if ($sql) 573 { 574 // Only return up to $total_matches_limit+1 ids (the last one will be removed later) 575 $result = $db->sql_query_limit($sql, $total_matches_limit + 1); 576 577 while ($row = $db->sql_fetchrow($result)) 578 { 579 $id_ary[] = (int) $row[$field]; 580 } 581 $db->sql_freeresult($result); 582 } 583 else if ($search_id == 'unreadposts') 584 { 585 // Only return up to $total_matches_limit+1 ids (the last one will be removed later) 586 $id_ary = array_keys(get_unread_topics($user->data['user_id'], $sql_where, $sql_sort, $total_matches_limit + 1)); 587 } 588 else 589 { 590 $search_id = ''; 591 } 592 593 $total_match_count = count($id_ary); 594 if ($total_match_count) 595 { 596 // Limit the number to $total_matches_limit for pre-made searches 597 if ($total_match_count > $total_matches_limit) 598 { 599 $found_more_search_matches = true; 600 $total_match_count = $total_matches_limit; 601 } 602 603 // Make sure $start is set to the last page if it exceeds the amount 604 $start = $pagination->validate_start($start, $per_page, $total_match_count); 605 606 $id_ary = array_slice($id_ary, $start, $per_page); 607 } 608 else 609 { 610 // Set $start to 0 if no matches were found 611 $start = 0; 612 } 613 } 614 615 // make sure that some arrays are always in the same order 616 sort($ex_fid_ary); 617 sort($author_id_ary); 618 619 if ($search->get_search_query()) 620 { 621 $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); 622 } 623 else if (count($author_id_ary)) 624 { 625 $firstpost_only = ($search_fields === 'firstpost' || $search_fields == 'titleonly') ? true : false; 626 $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); 627 } 628 629 /** 630 * Event to search otherwise than by keywords or author 631 * 632 * @event core.search_backend_search_after 633 * @var string show_results 'posts' or 'topics' type of ids 634 * @var string search_fields The data fields to search in 635 * @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) 636 * @var array sort_by_sql Array of SQL sorting instructions 637 * @var string sort_key The sort key 638 * @var string sort_dir The sort direction 639 * @var int sort_days Limit the age of results 640 * @var array ex_fid_ary Array of excluded forum ids 641 * @var string m_approve_posts_fid_sql Specifies which types of posts the user can view in which forums 642 * @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 643 * @var array author_id_ary Array of exclusive author ids 644 * @var string sql_author_match Specifies the author match, when ANONYMOUS is also a search-match 645 * @var array id_ary Array of post or topic ids for search result 646 * @var int start The starting id of the results 647 * @var int per_page Number of ids each page is supposed to contain 648 * @var int total_match_count The total number of search matches 649 * @since 3.1.10-RC1 650 */ 651 $vars = array( 652 'show_results', 653 'search_fields', 654 'search_terms', 655 'sort_by_sql', 656 'sort_key', 657 'sort_dir', 658 'sort_days', 659 'ex_fid_ary', 660 'm_approve_posts_fid_sql', 661 'topic_id', 662 'author_id_ary', 663 'sql_author_match', 664 'id_ary', 665 'start', 666 'per_page', 667 'total_match_count', 668 ); 669 extract($phpbb_dispatcher->trigger_event('core.search_backend_search_after', compact($vars))); 670 671 $sql_where = ''; 672 673 if (count($id_ary)) 674 { 675 $sql_where .= $db->sql_in_set(($show_results == 'posts') ? 'p.post_id' : 't.topic_id', $id_ary); 676 $sql_where .= (count($ex_fid_ary)) ? ' AND (' . $db->sql_in_set('f.forum_id', $ex_fid_ary, true) . ' OR f.forum_id IS NULL)' : ''; 677 $sql_where .= ' AND ' . (($show_results == 'posts') ? $m_approve_posts_fid_sql : $m_approve_topics_fid_sql); 678 } 679 680 if ($show_results == 'posts') 681 { 682 include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); 683 } 684 else 685 { 686 include($phpbb_root_path . 'includes/functions_display.' . $phpEx); 687 } 688 689 $user->add_lang('viewtopic'); 690 691 // Grab icons 692 $icons = $cache->obtain_icons(); 693 694 // define some vars for urls 695 // A single wildcard will make the search results look ugly 696 $hilit = phpbb_clean_search_string(str_replace(array('+', '-', '|', '(', ')', '"'), ' ', $keywords)); 697 $hilit = str_replace(' ', '|', $hilit); 698 699 $u_hilit = urlencode(html_entity_decode(str_replace('|', ' ', $hilit), ENT_COMPAT)); 700 $u_show_results = '&sr=' . $show_results; 701 $u_search_forum = implode('&fid%5B%5D=', $search_forum); 702 703 $u_search = append_sid("{$phpbb_root_path}search.$phpEx", $u_sort_param . $u_show_results); 704 $u_search .= ($search_id) ? '&search_id=' . $search_id : ''; 705 $u_search .= ($u_hilit) ? '&keywords=' . urlencode(html_entity_decode($keywords, ENT_COMPAT)) : ''; 706 $u_search .= ($search_terms != 'all') ? '&terms=' . $search_terms : ''; 707 $u_search .= ($topic_id) ? '&t=' . $topic_id : ''; 708 $u_search .= ($author) ? '&author=' . urlencode(html_entity_decode($author, ENT_COMPAT)) : ''; 709 $u_search .= ($author_id) ? '&author_id=' . $author_id : ''; 710 $u_search .= ($u_search_forum) ? '&fid%5B%5D=' . $u_search_forum : ''; 711 $u_search .= (!$search_child) ? '&sc=0' : ''; 712 $u_search .= ($search_fields != 'all') ? '&sf=' . $search_fields : ''; 713 $u_search .= $return_chars !== (int) $config['default_search_return_chars'] ? '&ch=' . $return_chars : ''; 714 715 /** 716 * Event to add or modify search URL parameters 717 * 718 * @event core.search_modify_url_parameters 719 * @var string u_search Search URL parameters string 720 * @var string search_id Predefined search type name 721 * @var string show_results String indicating the show results mode 722 * @var string sql_where The SQL WHERE string used by search to get topic data 723 * @var int total_match_count The total number of search matches 724 * @var array ex_fid_ary Array of excluded forum ids 725 * @since 3.1.7-RC1 726 * @changed 3.1.10-RC1 Added show_results, sql_where, total_match_count 727 * @changed 3.1.11-RC1 Added ex_fid_ary 728 */ 729 $vars = array( 730 'u_search', 731 'search_id', 732 'show_results', 733 'sql_where', 734 'total_match_count', 735 'ex_fid_ary', 736 ); 737 extract($phpbb_dispatcher->trigger_event('core.search_modify_url_parameters', compact($vars))); 738 739 if ($sql_where) 740 { 741 $zebra = []; 742 743 if ($show_results == 'posts') 744 { 745 // @todo Joining this query to the one below? 746 $sql = 'SELECT zebra_id, friend, foe 747 FROM ' . ZEBRA_TABLE . ' 748 WHERE user_id = ' . $user->data['user_id']; 749 $result = $db->sql_query($sql); 750 751 while ($row = $db->sql_fetchrow($result)) 752 { 753 $zebra[($row['friend']) ? 'friend' : 'foe'][] = $row['zebra_id']; 754 } 755 $db->sql_freeresult($result); 756 757 $sql_array = array( 758 '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', 759 'FROM' => array( 760 POSTS_TABLE => 'p', 761 ), 762 'LEFT_JOIN' => array( 763 array( 764 'FROM' => array(TOPICS_TABLE => 't'), 765 'ON' => 'p.topic_id = t.topic_id', 766 ), 767 array( 768 'FROM' => array(FORUMS_TABLE => 'f'), 769 'ON' => 'p.forum_id = f.forum_id', 770 ), 771 array( 772 'FROM' => array(USERS_TABLE => 'u'), 773 'ON' => 'p.poster_id = u.user_id', 774 ), 775 ), 776 'WHERE' => $sql_where, 777 'ORDER_BY' => $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'), 778 ); 779 780 /** 781 * Event to modify the SQL query before the posts data is retrieved 782 * 783 * @event core.search_get_posts_data 784 * @var array sql_array The SQL array 785 * @var array zebra Array of zebra data for the current user 786 * @var int total_match_count The total number of search matches 787 * @var string keywords String of the specified keywords 788 * @var array sort_by_sql Array of SQL sorting instructions 789 * @var string s_sort_dir The sort direction 790 * @var string s_sort_key The sort key 791 * @var string s_limit_days Limit the age of results 792 * @var array ex_fid_ary Array of excluded forum ids 793 * @var array author_id_ary Array of exclusive author ids 794 * @var string search_fields The data fields to search in 795 * @var int search_id The id of the search request 796 * @var int start The starting id of the results 797 * @since 3.1.0-b3 798 */ 799 $vars = array( 800 'sql_array', 801 'zebra', 802 'total_match_count', 803 'keywords', 804 'sort_by_sql', 805 's_sort_dir', 806 's_sort_key', 807 's_limit_days', 808 'ex_fid_ary', 809 'author_id_ary', 810 'search_fields', 811 'search_id', 812 'start', 813 ); 814 extract($phpbb_dispatcher->trigger_event('core.search_get_posts_data', compact($vars))); 815 816 $sql = $db->sql_build_query('SELECT', $sql_array); 817 } 818 else 819 { 820 $sql_from = TOPICS_TABLE . ' t 821 LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = t.forum_id) 822 ' . (($sort_key == 'a') ? ' LEFT JOIN ' . USERS_TABLE . ' u ON (u.user_id = t.topic_poster) ' : ''); 823 $sql_select = 't.*, f.forum_id, f.forum_name'; 824 825 if ($user->data['is_registered']) 826 { 827 if ($config['load_db_track'] && $author_id !== $user->data['user_id']) 828 { 829 $sql_from .= ' LEFT JOIN ' . TOPICS_POSTED_TABLE . ' tp ON (tp.user_id = ' . $user->data['user_id'] . ' 830 AND t.topic_id = tp.topic_id)'; 831 $sql_select .= ', tp.topic_posted'; 832 } 833 834 if ($config['load_db_lastread']) 835 { 836 $sql_from .= ' LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.user_id = ' . $user->data['user_id'] . ' 837 AND t.topic_id = tt.topic_id) 838 LEFT JOIN ' . FORUMS_TRACK_TABLE . ' ft ON (ft.user_id = ' . $user->data['user_id'] . ' 839 AND ft.forum_id = f.forum_id)'; 840 $sql_select .= ', tt.mark_time, ft.mark_time as f_mark_time'; 841 } 842 } 843 844 if ($config['load_anon_lastread'] || ($user->data['is_registered'] && !$config['load_db_lastread'])) 845 { 846 $tracking_topics = $request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE); 847 $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); 848 } 849 850 $sql_order_by = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); 851 852 /** 853 * Event to modify the SQL query before the topic data is retrieved 854 * 855 * @event core.search_get_topic_data 856 * @var string sql_select The SQL SELECT string used by search to get topic data 857 * @var string sql_from The SQL FROM string used by search to get topic data 858 * @var string sql_where The SQL WHERE string used by search to get topic data 859 * @var int total_match_count The total number of search matches 860 * @var array sort_by_sql Array of SQL sorting instructions 861 * @var string sort_dir The sorting direction 862 * @var string sort_key The sorting key 863 * @var string sql_order_by The SQL ORDER BY string used by search to get topic data 864 * @since 3.1.0-a1 865 * @changed 3.1.0-RC5 Added total_match_count 866 * @changed 3.1.7-RC1 Added sort_by_sql, sort_dir, sort_key, sql_order_by 867 */ 868 $vars = array( 869 'sql_select', 870 'sql_from', 871 'sql_where', 872 'total_match_count', 873 'sort_by_sql', 874 'sort_dir', 875 'sort_key', 876 'sql_order_by', 877 ); 878 extract($phpbb_dispatcher->trigger_event('core.search_get_topic_data', compact($vars))); 879 880 $sql = "SELECT $sql_select 881 FROM $sql_from 882 WHERE $sql_where 883 ORDER BY $sql_order_by"; 884 } 885 $result = $db->sql_query($sql); 886 $result_topic_id = 0; 887 888 $rowset = $attachments = $topic_tracking_info = array(); 889 890 if ($show_results == 'topics') 891 { 892 $forums = $rowset = $shadow_topic_list = array(); 893 while ($row = $db->sql_fetchrow($result)) 894 { 895 $row['forum_id'] = (int) $row['forum_id']; 896 $row['topic_id'] = (int) $row['topic_id']; 897 898 if ($row['topic_status'] == ITEM_MOVED) 899 { 900 $shadow_topic_list[$row['topic_moved_id']] = $row['topic_id']; 901 } 902 903 $rowset[$row['topic_id']] = $row; 904 905 if (!isset($forums[$row['forum_id']]) && $user->data['is_registered'] && $config['load_db_lastread']) 906 { 907 $forums[$row['forum_id']]['mark_time'] = $row['f_mark_time']; 908 } 909 $forums[$row['forum_id']]['topic_list'][] = $row['topic_id']; 910 $forums[$row['forum_id']]['rowset'][$row['topic_id']] = &$rowset[$row['topic_id']]; 911 } 912 $db->sql_freeresult($result); 913 914 // If we have some shadow topics, update the rowset to reflect their topic information 915 if (count($shadow_topic_list)) 916 { 917 $sql = 'SELECT * 918 FROM ' . TOPICS_TABLE . ' 919 WHERE ' . $db->sql_in_set('topic_id', array_keys($shadow_topic_list)); 920 $result = $db->sql_query($sql); 921 922 while ($row = $db->sql_fetchrow($result)) 923 { 924 $orig_topic_id = $shadow_topic_list[$row['topic_id']]; 925 926 // We want to retain some values 927 $row = array_merge($row, array( 928 'topic_moved_id' => $rowset[$orig_topic_id]['topic_moved_id'], 929 'topic_status' => $rowset[$orig_topic_id]['topic_status'], 930 'forum_name' => $rowset[$orig_topic_id]['forum_name']) 931 ); 932 933 $rowset[$orig_topic_id] = $row; 934 } 935 $db->sql_freeresult($result); 936 } 937 unset($shadow_topic_list); 938 939 foreach ($forums as $forum_id => $forum) 940 { 941 if ($user->data['is_registered'] && $config['load_db_lastread']) 942 { 943 $topic_tracking_info[$forum_id] = get_topic_tracking($forum_id, $forum['topic_list'], $forum['rowset'], array($forum_id => $forum['mark_time'])); 944 } 945 else if ($config['load_anon_lastread'] || $user->data['is_registered']) 946 { 947 $topic_tracking_info[$forum_id] = get_complete_topic_tracking($forum_id, $forum['topic_list']); 948 949 if (!$user->data['is_registered']) 950 { 951 $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate']) : 0; 952 } 953 } 954 } 955 unset($forums); 956 } 957 else 958 { 959 $text_only_message = ''; 960 $attach_list = array(); 961 962 while ($row = $db->sql_fetchrow($result)) 963 { 964 /** 965 * Modify the row of a post result before the post_text is trimmed 966 * 967 * @event core.search_modify_post_row 968 * @var string hilit String to highlight 969 * @var array row Array with the post data 970 * @var string u_hilit Highlight string to be injected into URL 971 * @var string view Search results view mode 972 * @var array zebra Array with zebra data for the current user 973 * @since 3.2.2-RC1 974 */ 975 $vars = array( 976 'hilit', 977 'row', 978 'u_hilit', 979 'view', 980 'zebra', 981 ); 982 extract($phpbb_dispatcher->trigger_event('core.search_modify_post_row', compact($vars))); 983 984 // We pre-process some variables here for later usage 985 $row['post_text'] = censor_text($row['post_text']); 986 987 $text_only_message = $row['post_text']; 988 // make list items visible as such 989 if ($row['bbcode_uid']) 990 { 991 $text_only_message = str_replace('[*:' . $row['bbcode_uid'] . ']', '⋅ ', $text_only_message); 992 // no BBCode in text only message 993 strip_bbcode($text_only_message, $row['bbcode_uid']); 994 } 995 996 if ($return_chars === 0 || utf8_strlen($text_only_message) < ($return_chars + 3)) 997 { 998 $row['display_text_only'] = false; 999 1000 // Does this post have an attachment? If so, add it to the list 1001 if ($row['post_attachment'] && $config['allow_attachments']) 1002 { 1003 $attach_list[$row['forum_id']][] = $row['post_id']; 1004 } 1005 } 1006 else 1007 { 1008 $row['post_text'] = $text_only_message; 1009 $row['display_text_only'] = true; 1010 } 1011 1012 $rowset[] = $row; 1013 } 1014 $db->sql_freeresult($result); 1015 1016 unset($text_only_message); 1017 1018 // Pull attachment data 1019 if (count($attach_list)) 1020 { 1021 $use_attach_list = $attach_list; 1022 $attach_list = array(); 1023 1024 foreach ($use_attach_list as $forum_id => $_list) 1025 { 1026 if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id)) 1027 { 1028 $attach_list = array_merge($attach_list, $_list); 1029 } 1030 } 1031 } 1032 1033 if (count($attach_list)) 1034 { 1035 $sql = 'SELECT * 1036 FROM ' . ATTACHMENTS_TABLE . ' 1037 WHERE ' . $db->sql_in_set('post_msg_id', $attach_list) . ' 1038 AND in_message = 0 1039 ORDER BY filetime DESC, post_msg_id ASC'; 1040 $result = $db->sql_query($sql); 1041 1042 while ($row = $db->sql_fetchrow($result)) 1043 { 1044 $attachments[$row['post_msg_id']][] = $row; 1045 } 1046 $db->sql_freeresult($result); 1047 } 1048 } 1049 1050 if ($hilit) 1051 { 1052 // Remove bad highlights 1053 $hilit_array = array_filter(explode('|', $hilit), 'strlen'); 1054 foreach ($hilit_array as $key => $value) 1055 { 1056 $hilit_array[$key] = phpbb_clean_search_string($value); 1057 $hilit_array[$key] = str_replace('\*', '\w*?', preg_quote($hilit_array[$key], '#')); 1058 $hilit_array[$key] = preg_replace('#(^|\s)\\\\w\*\?(\s|$)#', '$1\w+?$2', $hilit_array[$key]); 1059 } 1060 $hilit = implode('|', $hilit_array); 1061 } 1062 1063 /** 1064 * Modify the rowset data 1065 * 1066 * @event core.search_modify_rowset 1067 * @var array attachments Array with posts attachments data 1068 * @var string hilit String to highlight 1069 * @var array rowset Array with the search results data 1070 * @var string show_results String indicating the show results mode 1071 * @var array topic_tracking_info Array with the topics tracking data 1072 * @var string u_hilit Highlight string to be injected into URL 1073 * @var string view Search results view mode 1074 * @var array zebra Array with zebra data for the current user 1075 * @since 3.1.0-b4 1076 * @changed 3.1.0-b5 Added var show_results 1077 */ 1078 $vars = array( 1079 'attachments', 1080 'hilit', 1081 'rowset', 1082 'show_results', 1083 'topic_tracking_info', 1084 'u_hilit', 1085 'view', 1086 'zebra', 1087 ); 1088 extract($phpbb_dispatcher->trigger_event('core.search_modify_rowset', compact($vars))); 1089 1090 foreach ($rowset as $row) 1091 { 1092 $forum_id = $row['forum_id']; 1093 $result_topic_id = $row['topic_id']; 1094 $topic_title = censor_text($row['topic_title']); 1095 $replies = $phpbb_content_visibility->get_count('topic_posts', $row, $forum_id) - 1; 1096 1097 $view_topic_url_params = "t=$result_topic_id" . (($u_hilit) ? "&hilit=$u_hilit" : ''); 1098 $view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params); 1099 1100 $folder_img = $folder_alt = $u_mcp_queue = ''; 1101 $topic_type = $posts_unapproved = 0; 1102 $unread_topic = $topic_unapproved = $topic_deleted = false; 1103 1104 if ($show_results == 'topics') 1105 { 1106 if ($config['load_db_track'] && $author_id === $user->data['user_id']) 1107 { 1108 $row['topic_posted'] = 1; 1109 } 1110 1111 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); 1112 1113 $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; 1114 1115 $topic_unapproved = (($row['topic_visibility'] == ITEM_UNAPPROVED || $row['topic_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $forum_id)) ? true : false; 1116 $posts_unapproved = ($row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $auth->acl_get('m_approve', $forum_id)) ? true : false; 1117 $topic_deleted = $row['topic_visibility'] == ITEM_DELETED; 1118 $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) : ''; 1119 $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; 1120 1121 $row['topic_title'] = preg_replace('#(?!<.*)(?<!\w)(' . $hilit . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#isu', '<span class="posthilit">$1</span>', $row['topic_title']); 1122 1123 $tpl_ary = array( 1124 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), 1125 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), 1126 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), 1127 'FIRST_POST_TIME' => $user->format_date($row['topic_time']), 1128 'FIRST_POST_TIME_RFC3339' => gmdate(DATE_RFC3339, $row['topic_time']), 1129 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'], 1130 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']), 1131 'LAST_POST_TIME_RFC3339' => gmdate(DATE_RFC3339, $row['topic_last_post_time']), 1132 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']), 1133 'LAST_VIEW_TIME_RFC3339' => gmdate(DATE_RFC3339, $row['topic_last_view_time']), 1134 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 1135 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 1136 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 1137 1138 'TOPIC_TYPE' => $topic_type, 1139 1140 'TOPIC_IMG_STYLE' => $folder_img, 1141 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), 1142 'TOPIC_FOLDER_IMG_ALT' => $user->lang[$folder_alt], 1143 1144 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '', 1145 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '', 1146 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '', 1147 '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']) : '', 1148 'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', 1149 1150 'S_TOPIC_TYPE' => $row['topic_type'], 1151 'S_USER_POSTED' => (!empty($row['topic_posted'])) ? true : false, 1152 'S_UNREAD_TOPIC' => $unread_topic, 1153 1154 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && $auth->acl_get('m_report', $forum_id)) ? true : false, 1155 'S_TOPIC_UNAPPROVED' => $topic_unapproved, 1156 'S_POSTS_UNAPPROVED' => $posts_unapproved, 1157 'S_TOPIC_DELETED' => $topic_deleted, 1158 'S_HAS_POLL' => ($row['poll_start']) ? true : false, 1159 1160 'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], 1161 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 1162 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), 1163 'U_NEWEST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&view=unread') . '#unread', 1164 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=reports&t=' . $result_topic_id, true, $user->session_id), 1165 'U_MCP_QUEUE' => $u_mcp_queue, 1166 ); 1167 } 1168 else 1169 { 1170 if ((isset($zebra['foe']) && in_array($row['poster_id'], $zebra['foe'])) && (!$view || $view != 'show' || $post_id != $row['post_id'])) 1171 { 1172 $template->assign_block_vars('searchresults', array( 1173 'S_IGNORE_POST' => true, 1174 1175 '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>')) 1176 ); 1177 1178 continue; 1179 } 1180 1181 // Replace naughty words such as farty pants 1182 $row['post_subject'] = censor_text($row['post_subject']); 1183 1184 if ($row['display_text_only']) 1185 { 1186 // now find context for the searched words 1187 $row['post_text'] = get_context($row['post_text'], array_filter(explode('|', $hilit), 'strlen'), $return_chars); 1188 $row['post_text'] = bbcode_nl2br($row['post_text']); 1189 } 1190 else 1191 { 1192 $parse_flags = ($row['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES; 1193 $row['post_text'] = generate_text_for_display($row['post_text'], $row['bbcode_uid'], $row['bbcode_bitfield'], $parse_flags, false); 1194 1195 if (!empty($attachments[$row['post_id']])) 1196 { 1197 parse_attachments($forum_id, $row['post_text'], $attachments[$row['post_id']], $update_count); 1198 1199 // we only display inline attachments 1200 unset($attachments[$row['post_id']]); 1201 } 1202 } 1203 1204 if ($hilit) 1205 { 1206 // post highlighting 1207 $row['post_text'] = preg_replace('#(?!<.*)(?<!\w)(' . $hilit . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#isu', '<span class="posthilit">$1</span>', $row['post_text']); 1208 $row['post_subject'] = preg_replace('#(?!<.*)(?<!\w)(' . $hilit . ')(?!\w|[^<>]*(?:</s(?:cript|tyle))?>)#isu', '<span class="posthilit">$1</span>', $row['post_subject']); 1209 } 1210 1211 $tpl_ary = array( 1212 'POST_AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), 1213 'POST_AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), 1214 'POST_AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), 1215 'U_POST_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), 1216 1217 'POST_SUBJECT' => $row['post_subject'], 1218 'POST_DATE' => (!empty($row['post_time'])) ? $user->format_date($row['post_time']) : '', 1219 'MESSAGE' => $row['post_text'] 1220 ); 1221 } 1222 1223 $tpl_ary = array_merge($tpl_ary, array( 1224 'FORUM_ID' => $forum_id, 1225 'TOPIC_ID' => $result_topic_id, 1226 'POST_ID' => ($show_results == 'posts') ? $row['post_id'] : false, 1227 1228 'FORUM_TITLE' => $row['forum_name'], 1229 'TOPIC_TITLE' => $topic_title, 1230 'TOPIC_REPLIES' => $replies, 1231 'TOPIC_VIEWS' => $row['topic_views'], 1232 1233 'U_VIEW_TOPIC' => $view_topic_url, 1234 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id), 1235 'U_VIEW_POST' => (!empty($row['post_id'])) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id'] . (($u_hilit) ? '&hilit=' . $u_hilit : '')) . '#p' . $row['post_id'] : '', 1236 )); 1237 1238 /** 1239 * Modify the topic data before it is assigned to the template 1240 * 1241 * @event core.search_modify_tpl_ary 1242 * @var array row Array with topic data 1243 * @var array tpl_ary Template block array with topic data 1244 * @var string show_results Display topics or posts 1245 * @var string topic_title Cleaned topic title 1246 * @var int replies The number of topic replies 1247 * @var string view_topic_url The URL to the topic 1248 * @var string folder_img The folder image of the topic 1249 * @var string folder_alt The alt attribute of the topic folder img 1250 * @var int topic_type The topic type 1251 * @var bool unread_topic Whether the topic has unread posts 1252 * @var bool topic_unapproved Whether the topic is unapproved 1253 * @var int posts_unapproved The number of unapproved posts 1254 * @var bool topic_deleted Whether the topic has been deleted 1255 * @var string u_mcp_queue The URL to the corresponding MCP queue page 1256 * @var array zebra The zebra data of the current user 1257 * @var array attachments All the attachments of the search results 1258 * @since 3.1.0-a1 1259 * @changed 3.1.0-b3 Added vars show_results, topic_title, replies, 1260 * view_topic_url, folder_img, folder_alt, topic_type, unread_topic, 1261 * topic_unapproved, posts_unapproved, topic_deleted, u_mcp_queue, 1262 * zebra, attachments 1263 */ 1264 $vars = array( 1265 'row', 1266 'tpl_ary', 1267 'show_results', 1268 'topic_title', 1269 'replies', 1270 'view_topic_url', 1271 'folder_img', 1272 'folder_alt', 1273 'topic_type', 1274 'unread_topic', 1275 'topic_unapproved', 1276 'posts_unapproved', 1277 'topic_deleted', 1278 'u_mcp_queue', 1279 'zebra', 1280 'attachments', 1281 ); 1282 extract($phpbb_dispatcher->trigger_event('core.search_modify_tpl_ary', compact($vars))); 1283 1284 $template->assign_block_vars('searchresults', $tpl_ary); 1285 1286 if ($show_results == 'topics') 1287 { 1288 $pagination->generate_template_pagination($view_topic_url, 'searchresults.pagination', 'start', $replies + 1, $config['posts_per_page'], 1, true, true); 1289 } 1290 } 1291 1292 if ($topic_id && ($topic_id == $result_topic_id)) 1293 { 1294 $template->assign_vars(array( 1295 'SEARCH_TOPIC' => $topic_title, 1296 'L_RETURN_TO_TOPIC' => $user->lang('RETURN_TO', $topic_title), 1297 'U_SEARCH_TOPIC' => $view_topic_url 1298 )); 1299 } 1300 } 1301 unset($rowset); 1302 1303 // Output header 1304 if ($found_more_search_matches) 1305 { 1306 $l_search_matches = $user->lang('FOUND_MORE_SEARCH_MATCHES', (int) $total_match_count); 1307 } 1308 else 1309 { 1310 $l_search_matches = $user->lang('FOUND_SEARCH_MATCHES', (int) $total_match_count); 1311 } 1312 1313 // Check if search backend supports phrase search or not 1314 $phrase_search_disabled = ''; 1315 if (strpos(html_entity_decode($keywords), '"') !== false && method_exists($search, 'supports_phrase_search')) 1316 { 1317 $phrase_search_disabled = $search->supports_phrase_search() ? false : true; 1318 } 1319 1320 $pagination->generate_template_pagination($u_search, 'pagination', 'start', $total_match_count, $per_page, $start); 1321 1322 $template->assign_vars(array( 1323 'SEARCH_TITLE' => $l_search_title, 1324 'SEARCH_MATCHES' => $l_search_matches, 1325 'SEARCH_WORDS' => $keywords, 1326 'SEARCHED_QUERY' => $search->get_search_query(), 1327 'IGNORED_WORDS' => (!empty($common_words)) ? implode(' ', $common_words) : '', 1328 1329 'PHRASE_SEARCH_DISABLED' => $phrase_search_disabled, 1330 1331 'TOTAL_MATCHES' => $total_match_count, 1332 'SEARCH_IN_RESULTS' => ($search_id) ? false : true, 1333 1334 'S_SELECT_SORT_DIR' => $s_sort_dir, 1335 'S_SELECT_SORT_KEY' => $s_sort_key, 1336 'S_SELECT_SORT_DAYS' => $s_limit_days, 1337 'S_SEARCH_ACTION' => $u_search, 1338 'S_SHOW_TOPICS' => ($show_results == 'posts') ? false : true, 1339 1340 'GOTO_PAGE_IMG' => $user->img('icon_post_target', 'GOTO_PAGE'), 1341 'NEWEST_POST_IMG' => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), 1342 'REPORTED_IMG' => $user->img('icon_topic_reported', 'TOPIC_REPORTED'), 1343 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'TOPIC_UNAPPROVED'), 1344 'DELETED_IMG' => $user->img('icon_topic_deleted', 'TOPIC_DELETED'), 1345 'POLL_IMG' => $user->img('icon_topic_poll', 'TOPIC_POLL'), 1346 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), 1347 1348 'U_SEARCH_WORDS' => $u_search, 1349 )); 1350 1351 /** 1352 * Modify the title and/or load data for the search results page 1353 * 1354 * @event core.search_results_modify_search_title 1355 * @var int author_id ID of the author to search by 1356 * @var string l_search_title The title of the search page 1357 * @var string search_id Predefined search type name 1358 * @var string show_results Search results output mode - topics or posts 1359 * @var int start The starting id of the results 1360 * @var int total_match_count The count of search results 1361 * @var string keywords The search keywords 1362 * @since 3.1.0-RC4 1363 * @changed 3.1.6-RC1 Added total_match_count and keywords 1364 */ 1365 $vars = array( 1366 'author_id', 1367 'l_search_title', 1368 'search_id', 1369 'show_results', 1370 'start', 1371 'total_match_count', 1372 'keywords', 1373 ); 1374 extract($phpbb_dispatcher->trigger_event('core.search_results_modify_search_title', compact($vars))); 1375 1376 page_header(($l_search_title) ? $l_search_title : $user->lang['SEARCH']); 1377 1378 $template->set_filenames(array( 1379 'body' => 'search_results.html') 1380 ); 1381 make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx")); 1382 1383 page_footer(); 1384 } 1385 1386 // Search forum 1387 $rowset = array(); 1388 $s_forums = ''; 1389 $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 1390 FROM ' . FORUMS_TABLE . ' f 1391 LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa ON (fa.forum_id = f.forum_id 1392 AND fa.session_id = '" . $db->sql_escape($user->session_id) . "') 1393 ORDER BY f.left_id ASC"; 1394 $result = $db->sql_query($sql); 1395 1396 while ($row = $db->sql_fetchrow($result)) 1397 { 1398 $rowset[(int) $row['forum_id']] = $row; 1399 } 1400 $db->sql_freeresult($result); 1401 1402 $right = $cat_right = $padding_inc = 0; 1403 $padding = $forum_list = $holding = ''; 1404 $pad_store = array('0' => ''); 1405 1406 /** 1407 * Modify the forum select list for advanced search page 1408 * 1409 * @event core.search_modify_forum_select_list 1410 * @var array rowset Array with the forums list data 1411 * @since 3.1.10-RC1 1412 */ 1413 $vars = array('rowset'); 1414 extract($phpbb_dispatcher->trigger_event('core.search_modify_forum_select_list', compact($vars))); 1415 1416 foreach ($rowset as $row) 1417 { 1418 if ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id'])) 1419 { 1420 // Non-postable forum with no subforums, don't display 1421 continue; 1422 } 1423 1424 if ($row['forum_type'] == FORUM_POST && ($row['left_id'] + 1 == $row['right_id']) && !$row['enable_indexing']) 1425 { 1426 // Postable forum with no subforums and indexing disabled, don't display 1427 continue; 1428 } 1429 1430 if ($row['forum_type'] == FORUM_LINK || ($row['forum_password'] && !$row['user_id'])) 1431 { 1432 // if this forum is a link or password protected (user has not entered the password yet) then skip to the next branch 1433 continue; 1434 } 1435 1436 if ($row['left_id'] < $right) 1437 { 1438 $padding .= ' '; 1439 $pad_store[$row['parent_id']] = $padding; 1440 } 1441 else if ($row['left_id'] > $right + 1) 1442 { 1443 if (isset($pad_store[$row['parent_id']])) 1444 { 1445 $padding = $pad_store[$row['parent_id']]; 1446 } 1447 else 1448 { 1449 continue; 1450 } 1451 } 1452 1453 $right = $row['right_id']; 1454 1455 if ($auth->acl_gets('!f_search', '!f_list', $row['forum_id'])) 1456 { 1457 // if the user does not have permissions to search or see this forum skip only this forum/category 1458 continue; 1459 } 1460 1461 $selected = (in_array($row['forum_id'], $search_forum)) ? ' selected="selected"' : ''; 1462 1463 if ($row['left_id'] > $cat_right) 1464 { 1465 // make sure we don't forget anything 1466 $s_forums .= $holding; 1467 $holding = ''; 1468 } 1469 1470 if ($row['right_id'] - $row['left_id'] > 1) 1471 { 1472 $cat_right = max($cat_right, $row['right_id']); 1473 1474 $holding .= '<option value="' . $row['forum_id'] . '"' . $selected . '>' . $padding . $row['forum_name'] . '</option>'; 1475 } 1476 else 1477 { 1478 $s_forums .= $holding . '<option value="' . $row['forum_id'] . '"' . $selected . '>' . $padding . $row['forum_name'] . '</option>'; 1479 $holding = ''; 1480 } 1481 } 1482 1483 if ($holding) 1484 { 1485 $s_forums .= $holding; 1486 } 1487 1488 unset($pad_store); 1489 unset($rowset); 1490 1491 if (!$s_forums) 1492 { 1493 trigger_error('NO_SEARCH'); 1494 } 1495 1496 /** 1497 * Build options for a select list for the number of characters returned. 1498 * 1499 * If the admin defined amount is not within the predefined range, 1500 * and the admin did not set it to unlimited (0), we add that option aswell. 1501 * 1502 * @deprecated 3.3.1-RC1 Templates should use an numeric input, in favor of a select. 1503 */ 1504 $s_characters = '<option value="0">' . $language->lang('ALL_AVAILABLE') . '</option>'; 1505 $i_characters = array_merge([25, 50], range(100, 1000, 100)); 1506 1507 if ($config['default_search_return_chars'] && !in_array((int) $config['default_search_return_chars'], $i_characters)) 1508 { 1509 $i_characters[] = (int) $config['default_search_return_chars']; 1510 sort($i_characters); 1511 } 1512 1513 foreach ($i_characters as $i) 1514 { 1515 $selected = $i === (int) $config['default_search_return_chars'] ? ' selected="selected"' : ''; 1516 $s_characters .= sprintf('<option value="%1$s"%2$s>%1$s</option>', $i, $selected); 1517 } 1518 1519 $s_hidden_fields = array('t' => $topic_id); 1520 1521 if ($_SID) 1522 { 1523 $s_hidden_fields['sid'] = $_SID; 1524 } 1525 1526 if (!empty($_EXTRA_URL)) 1527 { 1528 foreach ($_EXTRA_URL as $url_param) 1529 { 1530 $url_param = explode('=', $url_param, 2); 1531 $s_hidden_fields[$url_param[0]] = $url_param[1]; 1532 } 1533 } 1534 1535 $template->assign_vars(array( 1536 'DEFAULT_RETURN_CHARS' => (int) $config['default_search_return_chars'], 1537 'S_SEARCH_ACTION' => append_sid("{$phpbb_root_path}search.$phpEx", false, true, 0), // We force no ?sid= appending by using 0 1538 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), 1539 'S_CHARACTER_OPTIONS' => $s_characters, 1540 'S_FORUM_OPTIONS' => $s_forums, 1541 'S_SELECT_SORT_DIR' => $s_sort_dir, 1542 'S_SELECT_SORT_KEY' => $s_sort_key, 1543 'S_SELECT_SORT_DAYS' => $s_limit_days, 1544 'S_IN_SEARCH' => true, 1545 )); 1546 1547 // only show recent searches to search administrators 1548 if ($auth->acl_get('a_search')) 1549 { 1550 // Handle large objects differently for Oracle and MSSQL 1551 switch ($db->get_sql_layer()) 1552 { 1553 case 'oracle': 1554 $sql = 'SELECT search_time, search_keywords 1555 FROM ' . SEARCH_RESULTS_TABLE . ' 1556 WHERE dbms_lob.getlength(search_keywords) > 0 1557 ORDER BY search_time DESC'; 1558 break; 1559 1560 case 'mssql_odbc': 1561 case 'mssqlnative': 1562 $sql = 'SELECT search_time, search_keywords 1563 FROM ' . SEARCH_RESULTS_TABLE . ' 1564 WHERE DATALENGTH(search_keywords) > 0 1565 ORDER BY search_time DESC'; 1566 break; 1567 1568 default: 1569 $sql = 'SELECT search_time, search_keywords 1570 FROM ' . SEARCH_RESULTS_TABLE . ' 1571 WHERE search_keywords <> \'\' 1572 ORDER BY search_time DESC'; 1573 break; 1574 } 1575 $result = $db->sql_query_limit($sql, 5); 1576 1577 while ($row = $db->sql_fetchrow($result)) 1578 { 1579 $keywords = $row['search_keywords']; 1580 1581 $template->assign_block_vars('recentsearch', array( 1582 'KEYWORDS' => $keywords, 1583 'TIME' => $user->format_date($row['search_time']), 1584 1585 'U_KEYWORDS' => append_sid("{$phpbb_root_path}search.$phpEx", 'keywords=' . urlencode(html_entity_decode($keywords, ENT_COMPAT))) 1586 )); 1587 } 1588 $db->sql_freeresult($result); 1589 } 1590 1591 // Output the basic page 1592 page_header($user->lang['SEARCH']); 1593 1594 $template->set_filenames(array( 1595 'body' => 'search_body.html') 1596 ); 1597 make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx")); 1598 1599 page_footer();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |