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