[ 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 if (!defined('IN_PHPBB')) 18 { 19 exit; 20 } 21 22 class acp_search 23 { 24 var $u_action; 25 var $state; 26 var $search; 27 var $max_post_id; 28 var $batch_size = 100; 29 30 function main($id, $mode) 31 { 32 global $user; 33 34 $user->add_lang('acp/search'); 35 36 // For some this may be of help... 37 @ini_set('memory_limit', '128M'); 38 39 switch ($mode) 40 { 41 case 'settings': 42 $this->settings($id, $mode); 43 break; 44 45 case 'index': 46 $this->index($id, $mode); 47 break; 48 } 49 } 50 51 function settings($id, $mode) 52 { 53 global $user, $template, $phpbb_log, $request; 54 global $config, $phpbb_admin_path, $phpEx; 55 56 $submit = $request->is_set_post('submit'); 57 58 if ($submit && !check_link_hash($request->variable('hash', ''), 'acp_search')) 59 { 60 trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); 61 } 62 63 $search_types = $this->get_search_types(); 64 65 $settings = [ 66 'search_interval' => 'float', 67 'search_anonymous_interval' => 'float', 68 'load_search' => 'bool', 69 'limit_search_load' => 'float', 70 'min_search_author_chars' => 'integer', 71 'max_num_search_keywords' => 'integer', 72 'default_search_return_chars' => 'integer', 73 'search_store_results' => 'integer', 74 ]; 75 76 $search = null; 77 $error = false; 78 $search_options = ''; 79 foreach ($search_types as $type) 80 { 81 if ($this->init_search($type, $search, $error)) 82 { 83 continue; 84 } 85 86 $name = $search->get_name(); 87 88 $selected = ($config['search_type'] == $type) ? ' selected="selected"' : ''; 89 $identifier = substr($type, strrpos($type, '\\') + 1); 90 $search_options .= "<option value=\"$type\"$selected data-toggle-setting=\"#search_{$identifier}_settings\">$name</option>"; 91 92 if (method_exists($search, 'acp')) 93 { 94 $vars = $search->acp(); 95 96 if (!$submit) 97 { 98 $template->assign_block_vars('backend', array( 99 'NAME' => $name, 100 'SETTINGS' => $vars['tpl'], 101 'IDENTIFIER' => $identifier, 102 )); 103 } 104 else if (is_array($vars['config'])) 105 { 106 $settings = array_merge($settings, $vars['config']); 107 } 108 } 109 } 110 unset($search); 111 unset($error); 112 113 $cfg_array = (isset($_REQUEST['config'])) ? $request->variable('config', array('' => ''), true) : array(); 114 $updated = $request->variable('updated', false); 115 116 foreach ($settings as $config_name => $var_type) 117 { 118 if (!isset($cfg_array[$config_name])) 119 { 120 continue; 121 } 122 123 // e.g. integer:4:12 (min 4, max 12) 124 $var_type = explode(':', $var_type); 125 126 $config_value = $cfg_array[$config_name]; 127 settype($config_value, $var_type[0]); 128 129 if (isset($var_type[1])) 130 { 131 $config_value = max($var_type[1], $config_value); 132 } 133 134 if (isset($var_type[2])) 135 { 136 $config_value = min($var_type[2], $config_value); 137 } 138 139 // only change config if anything was actually changed 140 if ($submit && ($config[$config_name] != $config_value)) 141 { 142 $config->set($config_name, $config_value); 143 $updated = true; 144 } 145 } 146 147 if ($submit) 148 { 149 $extra_message = ''; 150 if ($updated) 151 { 152 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH'); 153 } 154 155 if (isset($cfg_array['search_type']) && in_array($cfg_array['search_type'], $search_types, true) && ($cfg_array['search_type'] != $config['search_type'])) 156 { 157 $search = null; 158 $error = false; 159 160 if (!$this->init_search($cfg_array['search_type'], $search, $error)) 161 { 162 if (confirm_box(true)) 163 { 164 if (!method_exists($search, 'init') || !($error = $search->init())) 165 { 166 $config->set('search_type', $cfg_array['search_type']); 167 168 if (!$updated) 169 { 170 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH'); 171 } 172 $extra_message = '<br />' . $user->lang['SWITCHED_SEARCH_BACKEND'] . '<br /><a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=search&mode=index') . '">» ' . $user->lang['GO_TO_SEARCH_INDEX'] . '</a>'; 173 } 174 else 175 { 176 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 177 } 178 } 179 else 180 { 181 confirm_box(false, $user->lang['CONFIRM_SEARCH_BACKEND'], build_hidden_fields(array( 182 'i' => $id, 183 'mode' => $mode, 184 'submit' => true, 185 'updated' => $updated, 186 'config' => array('search_type' => $cfg_array['search_type']), 187 ))); 188 } 189 } 190 else 191 { 192 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 193 } 194 } 195 196 $search = null; 197 $error = false; 198 if (!$this->init_search($config['search_type'], $search, $error)) 199 { 200 if ($updated) 201 { 202 if (method_exists($search, 'config_updated')) 203 { 204 if ($search->config_updated()) 205 { 206 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 207 } 208 } 209 } 210 } 211 else 212 { 213 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 214 } 215 216 trigger_error($user->lang['CONFIG_UPDATED'] . $extra_message . adm_back_link($this->u_action)); 217 } 218 unset($cfg_array); 219 220 $this->tpl_name = 'acp_search'; 221 $this->page_title = 'ACP_SEARCH_SETTINGS'; 222 223 $template->assign_vars([ 224 'DEFAULT_SEARCH_RETURN_CHARS' => (int) $config['default_search_return_chars'], 225 'LIMIT_SEARCH_LOAD' => (float) $config['limit_search_load'], 226 'MIN_SEARCH_AUTHOR_CHARS' => (int) $config['min_search_author_chars'], 227 'SEARCH_INTERVAL' => (float) $config['search_interval'], 228 'SEARCH_GUEST_INTERVAL' => (float) $config['search_anonymous_interval'], 229 'SEARCH_STORE_RESULTS' => (int) $config['search_store_results'], 230 'MAX_NUM_SEARCH_KEYWORDS' => (int) $config['max_num_search_keywords'], 231 232 'S_SEARCH_TYPES' => $search_options, 233 'S_YES_SEARCH' => (bool) $config['load_search'], 234 'S_SETTINGS' => true, 235 236 'U_ACTION' => $this->u_action . '&hash=' . generate_link_hash('acp_search'), 237 ]); 238 } 239 240 function index($id, $mode) 241 { 242 global $db, $language, $user, $template, $phpbb_log, $request; 243 global $config, $phpbb_admin_path, $phpEx; 244 245 $action = $request->variable('action', ''); 246 $this->state = explode(',', $config['search_indexing_state']); 247 248 if ($request->is_set_post('cancel')) 249 { 250 $action = ''; 251 $this->state = array(); 252 $this->save_state(); 253 } 254 $submit = $request->is_set_post('submit'); 255 256 if (!check_link_hash($request->variable('hash', ''), 'acp_search') && in_array($action, array('create', 'delete'))) 257 { 258 trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); 259 } 260 261 if ($action) 262 { 263 switch ($action) 264 { 265 case 'delete': 266 $this->state[1] = 'delete'; 267 break; 268 269 case 'create': 270 $this->state[1] = 'create'; 271 break; 272 273 default: 274 trigger_error('NO_ACTION', E_USER_ERROR); 275 break; 276 } 277 278 if (empty($this->state[0])) 279 { 280 $this->state[0] = $request->variable('search_type', ''); 281 } 282 283 $this->search = null; 284 $error = false; 285 if ($this->init_search($this->state[0], $this->search, $error)) 286 { 287 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 288 } 289 $name = $this->search->get_name(); 290 291 $action = &$this->state[1]; 292 293 $this->max_post_id = $this->get_max_post_id(); 294 295 $post_counter = (isset($this->state[2])) ? $this->state[2] : 0; 296 $this->state[2] = &$post_counter; 297 $this->save_state(); 298 299 switch ($action) 300 { 301 case 'delete': 302 if (method_exists($this->search, 'delete_index')) 303 { 304 // pass a reference to myself so the $search object can make use of save_state() and attributes 305 if ($error = $this->search->delete_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=delete&hash=" . generate_link_hash('acp_search'), false))) 306 { 307 $this->state = array(''); 308 $this->save_state(); 309 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 310 } 311 } 312 else if ($submit) 313 { 314 meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search'))); 315 $template->assign_vars([ 316 'S_INDEX_PROGRESS' => true, 317 'INDEXING_TITLE' => $language->lang('DELETING_INDEX_IN_PROGRESS'), 318 'INDEXING_EXPLAIN' => $language->lang('DELETING_INDEX_IN_PROGRESS_EXPLAIN'), 319 'INDEXING_PROGRESS_BAR' => $this->get_post_index_progress($post_counter), 320 ]); 321 322 $this->tpl_name = 'acp_search'; 323 $this->page_title = 'ACP_SEARCH_INDEX'; 324 325 return; 326 } 327 else 328 { 329 $starttime = microtime(true); 330 $row_count = 0; 331 while (still_on_time() && $post_counter < $this->max_post_id) 332 { 333 $sql = 'SELECT post_id, poster_id, forum_id 334 FROM ' . POSTS_TABLE . ' 335 WHERE post_id > ' . (int) $post_counter . ' 336 ORDER BY post_id ASC'; 337 $result = $db->sql_query_limit($sql, $this->batch_size); 338 339 $ids = $posters = $forum_ids = array(); 340 while ($row = $db->sql_fetchrow($result)) 341 { 342 $ids[] = $row['post_id']; 343 $posters[] = $row['poster_id']; 344 $forum_ids[] = $row['forum_id']; 345 } 346 $db->sql_freeresult($result); 347 $row_count += count($ids); 348 349 if (count($ids)) 350 { 351 $this->search->index_remove($ids, $posters, $forum_ids); 352 $post_counter = $ids[count($ids) - 1]; 353 } 354 } 355 // save the current state 356 $this->save_state(); 357 358 if ($post_counter < $this->max_post_id) 359 { 360 $totaltime = microtime(true) - $starttime; 361 $rows_per_second = $row_count / $totaltime; 362 meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search'))); 363 364 $template->assign_vars([ 365 'S_INDEX_PROGRESS' => true, 366 'INDEXING_TITLE' => $language->lang('DELETING_INDEX_IN_PROGRESS'), 367 'INDEXING_EXPLAIN' => $language->lang('DELETING_INDEX_IN_PROGRESS_EXPLAIN'), 368 'INDEXING_PROGRESS' => $language->lang('SEARCH_INDEX_DELETE_REDIRECT', $row_count, $post_counter), 369 'INDEXING_RATE' => $language->lang('SEARCH_INDEX_DELETE_REDIRECT_RATE', $rows_per_second), 370 'INDEXING_PROGRESS_BAR' => $this->get_post_index_progress($post_counter), 371 ]); 372 373 $this->tpl_name = 'acp_search'; 374 $this->page_title = 'ACP_SEARCH_INDEX'; 375 376 return; 377 } 378 } 379 380 $this->search->tidy(); 381 382 $this->state = array(''); 383 $this->save_state(); 384 385 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_REMOVED', false, array($name)); 386 trigger_error($user->lang['SEARCH_INDEX_REMOVED'] . adm_back_link($this->u_action)); 387 break; 388 389 case 'create': 390 if (method_exists($this->search, 'create_index')) 391 { 392 // pass a reference to acp_search so the $search object can make use of save_state() and attributes 393 if ($error = $this->search->create_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=create", false))) 394 { 395 $this->state = array(''); 396 $this->save_state(); 397 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 398 } 399 } 400 else if ($submit) 401 { 402 meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search'))); 403 404 $template->assign_vars([ 405 'S_INDEX_PROGRESS' => true, 406 'INDEXING_TITLE' => $language->lang('INDEXING_IN_PROGRESS'), 407 'INDEXING_EXPLAIN' => $language->lang('INDEXING_IN_PROGRESS_EXPLAIN'), 408 'INDEXING_PROGRESS_BAR' => $this->get_post_index_progress($post_counter), 409 ]); 410 411 $this->tpl_name = 'acp_search'; 412 $this->page_title = 'ACP_SEARCH_INDEX'; 413 414 return; 415 } 416 else 417 { 418 $sql = 'SELECT forum_id, enable_indexing 419 FROM ' . FORUMS_TABLE; 420 $result = $db->sql_query($sql, 3600); 421 422 while ($row = $db->sql_fetchrow($result)) 423 { 424 $forums[$row['forum_id']] = (bool) $row['enable_indexing']; 425 } 426 $db->sql_freeresult($result); 427 428 $starttime = microtime(true); 429 $row_count = 0; 430 while (still_on_time() && $post_counter < $this->max_post_id) 431 { 432 $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id 433 FROM ' . POSTS_TABLE . ' 434 WHERE post_id > ' . (int) $post_counter . ' 435 ORDER BY post_id ASC'; 436 $result = $db->sql_query_limit($sql, $this->batch_size); 437 438 $buffer = $db->sql_buffer_nested_transactions(); 439 440 if ($buffer) 441 { 442 $rows = $db->sql_fetchrowset($result); 443 $rows[] = false; // indicate end of array for while loop below 444 445 $db->sql_freeresult($result); 446 } 447 448 $i = 0; 449 while ($row = ($buffer ? $rows[$i++] : $db->sql_fetchrow($result))) 450 { 451 // Indexing enabled for this forum 452 if (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']]) 453 { 454 $this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); 455 } 456 $row_count++; 457 $post_counter = $row['post_id']; 458 } 459 if (!$buffer) 460 { 461 $db->sql_freeresult($result); 462 } 463 } 464 // save the current state 465 $this->save_state(); 466 467 // pretend the number of posts was as big as the number of ids we indexed so far 468 // just an estimation as it includes deleted posts 469 $num_posts = $config['num_posts']; 470 $config['num_posts'] = min($config['num_posts'], $post_counter); 471 $this->search->tidy(); 472 $config['num_posts'] = $num_posts; 473 474 if ($post_counter < $this->max_post_id) 475 { 476 $totaltime = microtime(true) - $starttime; 477 $rows_per_second = $row_count / $totaltime; 478 meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search'))); 479 $template->assign_vars([ 480 'S_INDEX_PROGRESS' => true, 481 'INDEXING_TITLE' => $language->lang('INDEXING_IN_PROGRESS'), 482 'INDEXING_EXPLAIN' => $language->lang('INDEXING_IN_PROGRESS_EXPLAIN'), 483 'INDEXING_PROGRESS' => $language->lang('SEARCH_INDEX_CREATE_REDIRECT', $row_count, $post_counter), 484 'INDEXING_RATE' => $language->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second), 485 'INDEXING_PROGRESS_BAR' => $this->get_post_index_progress($post_counter), 486 ]); 487 488 $this->tpl_name = 'acp_search'; 489 $this->page_title = 'ACP_SEARCH_INDEX'; 490 491 return; 492 } 493 } 494 495 $this->search->tidy(); 496 497 $this->state = array(''); 498 $this->save_state(); 499 500 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_CREATED', false, array($name)); 501 trigger_error($user->lang['SEARCH_INDEX_CREATED'] . adm_back_link($this->u_action)); 502 break; 503 } 504 } 505 506 $search_types = $this->get_search_types(); 507 508 $search = null; 509 $error = false; 510 foreach ($search_types as $type) 511 { 512 if ($this->init_search($type, $search, $error) || !method_exists($search, 'index_created')) 513 { 514 continue; 515 } 516 517 $name = $search->get_name(); 518 519 $data = array(); 520 if (method_exists($search, 'index_stats')) 521 { 522 $data = $search->index_stats(); 523 } 524 525 $statistics = array(); 526 foreach ($data as $statistic => $value) 527 { 528 $n = count($statistics); 529 if ($n && count($statistics[$n - 1]) < 3) 530 { 531 $statistics[$n - 1] += array('statistic_2' => $statistic, 'value_2' => $value); 532 } 533 else 534 { 535 $statistics[] = array('statistic_1' => $statistic, 'value_1' => $value); 536 } 537 } 538 539 $template->assign_block_vars('backend', array( 540 'L_NAME' => $name, 541 'NAME' => $type, 542 543 'S_ACTIVE' => ($type == $config['search_type']) ? true : false, 544 'S_HIDDEN_FIELDS' => build_hidden_fields(array('search_type' => $type)), 545 'S_INDEXED' => (bool) $search->index_created(), 546 'S_STATS' => (bool) count($statistics)) 547 ); 548 549 foreach ($statistics as $statistic) 550 { 551 $template->assign_block_vars('backend.data', array( 552 'STATISTIC_1' => $statistic['statistic_1'], 553 'VALUE_1' => $statistic['value_1'], 554 'STATISTIC_2' => (isset($statistic['statistic_2'])) ? $statistic['statistic_2'] : '', 555 'VALUE_2' => (isset($statistic['value_2'])) ? $statistic['value_2'] : '') 556 ); 557 } 558 } 559 unset($search); 560 unset($error); 561 unset($statistics); 562 unset($data); 563 564 $this->tpl_name = 'acp_search'; 565 $this->page_title = 'ACP_SEARCH_INDEX'; 566 567 $template->assign_vars(array( 568 'S_INDEX' => true, 569 'U_ACTION' => $this->u_action . '&hash=' . generate_link_hash('acp_search'), 570 )); 571 572 if (isset($this->state[1])) 573 { 574 $template->assign_vars(array( 575 'S_CONTINUE_INDEXING' => $this->state[1], 576 'U_CONTINUE_INDEXING' => $this->u_action . '&action=' . $this->state[1] . '&hash=' . generate_link_hash('acp_search'), 577 'CONTINUE_PROGRESS' => (isset($this->state[2]) && $this->state[2] > 0) ? $this->get_post_index_progress($this->state[2]) : $this->get_post_index_progress(0) 578 )); 579 } 580 } 581 582 function get_search_types() 583 { 584 global $phpbb_extension_manager; 585 586 $finder = $phpbb_extension_manager->get_finder(); 587 588 return $finder 589 ->extension_suffix('_backend') 590 ->extension_directory('/search') 591 ->core_path('phpbb/search/') 592 ->get_classes(); 593 } 594 595 function get_max_post_id() 596 { 597 global $db; 598 599 $sql = 'SELECT MAX(post_id) as max_post_id 600 FROM '. POSTS_TABLE; 601 $result = $db->sql_query($sql); 602 $max_post_id = (int) $db->sql_fetchfield('max_post_id'); 603 $db->sql_freeresult($result); 604 605 return $max_post_id; 606 } 607 608 /** 609 * Get progress stats of search index with HTML progress bar. 610 * 611 * @param int $post_counter Post ID of last post indexed. 612 * @return array Returns array with progress bar data. 613 */ 614 function get_post_index_progress(int $post_counter) 615 { 616 global $db, $language; 617 618 $sql = 'SELECT COUNT(post_id) as done_count 619 FROM ' . POSTS_TABLE . ' 620 WHERE post_id <= ' . (int) $post_counter; 621 $result = $db->sql_query($sql); 622 $done_count = (int) $db->sql_fetchfield('done_count'); 623 $db->sql_freeresult($result); 624 625 $sql = 'SELECT COUNT(post_id) as remain_count 626 FROM ' . POSTS_TABLE . ' 627 WHERE post_id > ' . (int) $post_counter; 628 $result = $db->sql_query($sql); 629 $remain_count = (int) $db->sql_fetchfield('remain_count'); 630 $db->sql_freeresult($result); 631 632 $total_count = $done_count + $remain_count; 633 $percent = ($done_count / $total_count) * 100; 634 635 return [ 636 'VALUE' => $done_count, 637 'TOTAL' => $total_count, 638 'PERCENTAGE' => $percent, 639 'REMAINING' => $remain_count, 640 ]; 641 } 642 643 function save_state($state = false) 644 { 645 global $config; 646 647 if ($state) 648 { 649 $this->state = $state; 650 } 651 652 ksort($this->state); 653 654 $config->set('search_indexing_state', implode(',', $this->state), true); 655 } 656 657 /** 658 * Initialises a search backend object 659 * 660 * @return false if no error occurred else an error message 661 */ 662 function init_search($type, &$search, &$error) 663 { 664 global $phpbb_root_path, $phpEx, $user, $auth, $config, $db, $phpbb_dispatcher; 665 666 if (!class_exists($type) || !method_exists($type, 'keyword_search')) 667 { 668 $error = $user->lang['NO_SUCH_SEARCH_MODULE']; 669 return $error; 670 } 671 672 $error = false; 673 $search = new $type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); 674 675 return $error; 676 } 677 }
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 |