[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * @package acp 5 * @version $Id$ 6 * @copyright (c) 2005 phpBB Group 7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License 8 * 9 */ 10 11 /** 12 * @ignore 13 */ 14 if (!defined('IN_PHPBB')) 15 { 16 exit; 17 } 18 19 /** 20 * @package acp 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 $db, $user, $auth, $template, $cache; 54 global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; 55 56 $submit = (isset($_POST['submit'])) ? true : false; 57 58 $search_types = $this->get_search_types(); 59 60 $settings = array( 61 'search_interval' => 'float', 62 'search_anonymous_interval' => 'float', 63 'load_search' => 'bool', 64 'limit_search_load' => 'float', 65 'min_search_author_chars' => 'integer', 66 'max_num_search_keywords' => 'integer', 67 'search_store_results' => 'integer', 68 ); 69 70 $search = null; 71 $error = false; 72 $search_options = ''; 73 foreach ($search_types as $type) 74 { 75 if ($this->init_search($type, $search, $error)) 76 { 77 continue; 78 } 79 80 $name = ucfirst(strtolower(str_replace('_', ' ', $type))); 81 $selected = ($config['search_type'] == $type) ? ' selected="selected"' : ''; 82 $search_options .= '<option value="' . $type . '"' . $selected . '>' . $name . '</option>'; 83 84 if (method_exists($search, 'acp')) 85 { 86 $vars = $search->acp(); 87 88 if (!$submit) 89 { 90 $template->assign_block_vars('backend', array( 91 'NAME' => $name, 92 'SETTINGS' => $vars['tpl']) 93 ); 94 } 95 else if (is_array($vars['config'])) 96 { 97 $settings = array_merge($settings, $vars['config']); 98 } 99 } 100 } 101 unset($search); 102 unset($error); 103 104 $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => ''), true) : array(); 105 $updated = request_var('updated', false); 106 107 foreach ($settings as $config_name => $var_type) 108 { 109 if (!isset($cfg_array[$config_name])) 110 { 111 continue; 112 } 113 114 // e.g. integer:4:12 (min 4, max 12) 115 $var_type = explode(':', $var_type); 116 117 $config_value = $cfg_array[$config_name]; 118 settype($config_value, $var_type[0]); 119 120 if (isset($var_type[1])) 121 { 122 $config_value = max($var_type[1], $config_value); 123 } 124 125 if (isset($var_type[2])) 126 { 127 $config_value = min($var_type[2], $config_value); 128 } 129 130 // only change config if anything was actually changed 131 if ($submit && ($config[$config_name] != $config_value)) 132 { 133 set_config($config_name, $config_value); 134 $updated = true; 135 } 136 } 137 138 if ($submit) 139 { 140 $extra_message = ''; 141 if ($updated) 142 { 143 add_log('admin', 'LOG_CONFIG_SEARCH'); 144 } 145 146 if (isset($cfg_array['search_type']) && in_array($cfg_array['search_type'], $search_types, true) && ($cfg_array['search_type'] != $config['search_type'])) 147 { 148 $search = null; 149 $error = false; 150 151 if (!$this->init_search($cfg_array['search_type'], $search, $error)) 152 { 153 if (confirm_box(true)) 154 { 155 if (!method_exists($search, 'init') || !($error = $search->init())) 156 { 157 set_config('search_type', $cfg_array['search_type']); 158 159 if (!$updated) 160 { 161 add_log('admin', 'LOG_CONFIG_SEARCH'); 162 } 163 $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>'; 164 } 165 else 166 { 167 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 168 } 169 } 170 else 171 { 172 confirm_box(false, $user->lang['CONFIRM_SEARCH_BACKEND'], build_hidden_fields(array( 173 'i' => $id, 174 'mode' => $mode, 175 'submit' => true, 176 'updated' => $updated, 177 'config' => array('search_type' => $cfg_array['search_type']), 178 ))); 179 } 180 } 181 else 182 { 183 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 184 } 185 } 186 187 $search = null; 188 $error = false; 189 if (!$this->init_search($config['search_type'], $search, $error)) 190 { 191 if ($updated) 192 { 193 if (method_exists($search, 'config_updated')) 194 { 195 if ($search->config_updated()) 196 { 197 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 198 } 199 } 200 } 201 } 202 else 203 { 204 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 205 } 206 207 trigger_error($user->lang['CONFIG_UPDATED'] . $extra_message . adm_back_link($this->u_action)); 208 } 209 unset($cfg_array); 210 211 $this->tpl_name = 'acp_search'; 212 $this->page_title = 'ACP_SEARCH_SETTINGS'; 213 214 $template->assign_vars(array( 215 'LIMIT_SEARCH_LOAD' => (float) $config['limit_search_load'], 216 'MIN_SEARCH_AUTHOR_CHARS' => (int) $config['min_search_author_chars'], 217 'SEARCH_INTERVAL' => (float) $config['search_interval'], 218 'SEARCH_GUEST_INTERVAL' => (float) $config['search_anonymous_interval'], 219 'SEARCH_STORE_RESULTS' => (int) $config['search_store_results'], 220 'MAX_NUM_SEARCH_KEYWORDS' => (int) $config['max_num_search_keywords'], 221 222 'S_SEARCH_TYPES' => $search_options, 223 'S_YES_SEARCH' => (bool) $config['load_search'], 224 'S_SETTINGS' => true, 225 226 'U_ACTION' => $this->u_action) 227 ); 228 } 229 230 function index($id, $mode) 231 { 232 global $db, $user, $auth, $template, $cache; 233 global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; 234 235 if (isset($_REQUEST['action']) && is_array($_REQUEST['action'])) 236 { 237 $action = request_var('action', array('' => false)); 238 $action = key($action); 239 } 240 else 241 { 242 $action = request_var('action', ''); 243 } 244 $this->state = explode(',', $config['search_indexing_state']); 245 246 if (isset($_POST['cancel'])) 247 { 248 $action = ''; 249 $this->state = array(); 250 $this->save_state(); 251 } 252 253 if ($action) 254 { 255 switch ($action) 256 { 257 case 'progress_bar': 258 $type = request_var('type', ''); 259 $this->display_progress_bar($type); 260 break; 261 262 case 'delete': 263 $this->state[1] = 'delete'; 264 break; 265 266 case 'create': 267 $this->state[1] = 'create'; 268 break; 269 270 default: 271 trigger_error('NO_ACTION', E_USER_ERROR); 272 break; 273 } 274 275 if (empty($this->state[0])) 276 { 277 $this->state[0] = request_var('search_type', ''); 278 } 279 280 $this->search = null; 281 $error = false; 282 if ($this->init_search($this->state[0], $this->search, $error)) 283 { 284 trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); 285 } 286 $name = ucfirst(strtolower(str_replace('_', ' ', $this->state[0]))); 287 288 $action = &$this->state[1]; 289 290 $this->max_post_id = $this->get_max_post_id(); 291 292 $post_counter = (isset($this->state[2])) ? $this->state[2] : 0; 293 $this->state[2] = &$post_counter; 294 $this->save_state(); 295 296 switch ($action) 297 { 298 case 'delete': 299 if (method_exists($this->search, 'delete_index')) 300 { 301 // pass a reference to myself so the $search object can make use of save_state() and attributes 302 if ($error = $this->search->delete_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=delete", false))) 303 { 304 $this->state = array(''); 305 $this->save_state(); 306 trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); 307 } 308 } 309 else 310 { 311 $starttime = explode(' ', microtime()); 312 $starttime = $starttime[1] + $starttime[0]; 313 $row_count = 0; 314 while (still_on_time() && $post_counter <= $this->max_post_id) 315 { 316 $sql = 'SELECT post_id, poster_id, forum_id 317 FROM ' . POSTS_TABLE . ' 318 WHERE post_id >= ' . (int) ($post_counter + 1) . ' 319 AND post_id <= ' . (int) ($post_counter + $this->batch_size); 320 $result = $db->sql_query($sql); 321 322 $ids = $posters = $forum_ids = array(); 323 while ($row = $db->sql_fetchrow($result)) 324 { 325 $ids[] = $row['post_id']; 326 $posters[] = $row['poster_id']; 327 $forum_ids[] = $row['forum_id']; 328 } 329 $db->sql_freeresult($result); 330 $row_count += sizeof($ids); 331 332 if (sizeof($ids)) 333 { 334 $this->search->index_remove($ids, $posters, $forum_ids); 335 } 336 337 $post_counter += $this->batch_size; 338 } 339 // save the current state 340 $this->save_state(); 341 342 if ($post_counter <= $this->max_post_id) 343 { 344 $mtime = explode(' ', microtime()); 345 $totaltime = $mtime[0] + $mtime[1] - $starttime; 346 $rows_per_second = $row_count / $totaltime; 347 meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter)); 348 trigger_error(sprintf($user->lang['SEARCH_INDEX_DELETE_REDIRECT'], $post_counter, $row_count, $rows_per_second)); 349 } 350 } 351 352 $this->search->tidy(); 353 354 $this->state = array(''); 355 $this->save_state(); 356 357 add_log('admin', 'LOG_SEARCH_INDEX_REMOVED', $name); 358 trigger_error($user->lang['SEARCH_INDEX_REMOVED'] . adm_back_link($this->u_action) . $this->close_popup_js()); 359 break; 360 361 case 'create': 362 if (method_exists($this->search, 'create_index')) 363 { 364 // pass a reference to acp_search so the $search object can make use of save_state() and attributes 365 if ($error = $this->search->create_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=create", false))) 366 { 367 $this->state = array(''); 368 $this->save_state(); 369 trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); 370 } 371 } 372 else 373 { 374 $sql = 'SELECT forum_id, enable_indexing 375 FROM ' . FORUMS_TABLE; 376 $result = $db->sql_query($sql, 3600); 377 378 while ($row = $db->sql_fetchrow($result)) 379 { 380 $forums[$row['forum_id']] = (bool) $row['enable_indexing']; 381 } 382 $db->sql_freeresult($result); 383 384 $starttime = explode(' ', microtime()); 385 $starttime = $starttime[1] + $starttime[0]; 386 $row_count = 0; 387 while (still_on_time() && $post_counter <= $this->max_post_id) 388 { 389 $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id 390 FROM ' . POSTS_TABLE . ' 391 WHERE post_id >= ' . (int) ($post_counter + 1) . ' 392 AND post_id <= ' . (int) ($post_counter + $this->batch_size); 393 $result = $db->sql_query($sql); 394 395 $buffer = $db->sql_buffer_nested_transactions(); 396 397 if ($buffer) 398 { 399 $rows = $db->sql_fetchrowset($result); 400 $rows[] = false; // indicate end of array for while loop below 401 402 $db->sql_freeresult($result); 403 } 404 405 $i = 0; 406 while ($row = ($buffer ? $rows[$i++] : $db->sql_fetchrow($result))) 407 { 408 // Indexing enabled for this forum or global announcement? 409 // Global announcements get indexed by default. 410 if (!$row['forum_id'] || (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']])) 411 { 412 $this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); 413 } 414 $row_count++; 415 } 416 if (!$buffer) 417 { 418 $db->sql_freeresult($result); 419 } 420 421 $post_counter += $this->batch_size; 422 } 423 // save the current state 424 $this->save_state(); 425 426 // pretend the number of posts was as big as the number of ids we indexed so far 427 // just an estimation as it includes deleted posts 428 $num_posts = $config['num_posts']; 429 $config['num_posts'] = min($config['num_posts'], $post_counter); 430 $this->search->tidy(); 431 $config['num_posts'] = $num_posts; 432 433 if ($post_counter <= $this->max_post_id) 434 { 435 $mtime = explode(' ', microtime()); 436 $totaltime = $mtime[0] + $mtime[1] - $starttime; 437 $rows_per_second = $row_count / $totaltime; 438 meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter)); 439 trigger_error(sprintf($user->lang['SEARCH_INDEX_CREATE_REDIRECT'], $post_counter, $row_count, $rows_per_second)); 440 } 441 } 442 443 $this->search->tidy(); 444 445 $this->state = array(''); 446 $this->save_state(); 447 448 add_log('admin', 'LOG_SEARCH_INDEX_CREATED', $name); 449 trigger_error($user->lang['SEARCH_INDEX_CREATED'] . adm_back_link($this->u_action) . $this->close_popup_js()); 450 break; 451 } 452 } 453 454 $search_types = $this->get_search_types(); 455 456 $search = null; 457 $error = false; 458 $search_options = ''; 459 foreach ($search_types as $type) 460 { 461 if ($this->init_search($type, $search, $error) || !method_exists($search, 'index_created')) 462 { 463 continue; 464 } 465 466 $name = ucfirst(strtolower(str_replace('_', ' ', $type))); 467 468 $data = array(); 469 if (method_exists($search, 'index_stats')) 470 { 471 $data = $search->index_stats(); 472 } 473 474 $statistics = array(); 475 foreach ($data as $statistic => $value) 476 { 477 $n = sizeof($statistics); 478 if ($n && sizeof($statistics[$n - 1]) < 3) 479 { 480 $statistics[$n - 1] += array('statistic_2' => $statistic, 'value_2' => $value); 481 } 482 else 483 { 484 $statistics[] = array('statistic_1' => $statistic, 'value_1' => $value); 485 } 486 } 487 488 $template->assign_block_vars('backend', array( 489 'L_NAME' => $name, 490 'NAME' => $type, 491 492 'S_ACTIVE' => ($type == $config['search_type']) ? true : false, 493 'S_HIDDEN_FIELDS' => build_hidden_fields(array('search_type' => $type)), 494 'S_INDEXED' => (bool) $search->index_created(), 495 'S_STATS' => (bool) sizeof($statistics)) 496 ); 497 498 foreach ($statistics as $statistic) 499 { 500 $template->assign_block_vars('backend.data', array( 501 'STATISTIC_1' => $statistic['statistic_1'], 502 'VALUE_1' => $statistic['value_1'], 503 'STATISTIC_2' => (isset($statistic['statistic_2'])) ? $statistic['statistic_2'] : '', 504 'VALUE_2' => (isset($statistic['value_2'])) ? $statistic['value_2'] : '') 505 ); 506 } 507 } 508 unset($search); 509 unset($error); 510 unset($statistics); 511 unset($data); 512 513 $this->tpl_name = 'acp_search'; 514 $this->page_title = 'ACP_SEARCH_INDEX'; 515 516 $template->assign_vars(array( 517 'S_INDEX' => true, 518 'U_ACTION' => $this->u_action, 519 'U_PROGRESS_BAR' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=progress_bar"), 520 'UA_PROGRESS_BAR' => addslashes(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=progress_bar")), 521 )); 522 523 if (isset($this->state[1])) 524 { 525 $template->assign_vars(array( 526 'S_CONTINUE_INDEXING' => $this->state[1], 527 'U_CONTINUE_INDEXING' => $this->u_action . '&action=' . $this->state[1], 528 'L_CONTINUE' => ($this->state[1] == 'create') ? $user->lang['CONTINUE_INDEXING'] : $user->lang['CONTINUE_DELETING_INDEX'], 529 'L_CONTINUE_EXPLAIN' => ($this->state[1] == 'create') ? $user->lang['CONTINUE_INDEXING_EXPLAIN'] : $user->lang['CONTINUE_DELETING_INDEX_EXPLAIN']) 530 ); 531 } 532 } 533 534 function display_progress_bar($type) 535 { 536 global $template, $user; 537 538 $l_type = ($type == 'create') ? 'INDEXING_IN_PROGRESS' : 'DELETING_INDEX_IN_PROGRESS'; 539 540 adm_page_header($user->lang[$l_type]); 541 542 $template->set_filenames(array( 543 'body' => 'progress_bar.html') 544 ); 545 546 $template->assign_vars(array( 547 'L_PROGRESS' => $user->lang[$l_type], 548 'L_PROGRESS_EXPLAIN' => $user->lang[$l_type . '_EXPLAIN']) 549 ); 550 551 adm_page_footer(); 552 } 553 554 function close_popup_js() 555 { 556 return "<script type=\"text/javascript\">\n" . 557 "// <![CDATA[\n" . 558 " close_waitscreen = 1;\n" . 559 "// ]]>\n" . 560 "</script>\n"; 561 } 562 563 function get_search_types() 564 { 565 global $phpbb_root_path, $phpEx; 566 567 $search_types = array(); 568 569 $dp = @opendir($phpbb_root_path . 'includes/search'); 570 571 if ($dp) 572 { 573 while (($file = readdir($dp)) !== false) 574 { 575 if ((preg_match('#\.' . $phpEx . '$#', $file)) && ($file != "search.$phpEx")) 576 { 577 $search_types[] = preg_replace('#^(.*?)\.' . $phpEx . '$#', '\1', $file); 578 } 579 } 580 closedir($dp); 581 582 sort($search_types); 583 } 584 585 return $search_types; 586 } 587 588 function get_max_post_id() 589 { 590 global $db; 591 592 $sql = 'SELECT MAX(post_id) as max_post_id 593 FROM '. POSTS_TABLE; 594 $result = $db->sql_query($sql); 595 $max_post_id = (int) $db->sql_fetchfield('max_post_id'); 596 $db->sql_freeresult($result); 597 598 return $max_post_id; 599 } 600 601 function save_state($state = false) 602 { 603 if ($state) 604 { 605 $this->state = $state; 606 } 607 608 ksort($this->state); 609 610 set_config('search_indexing_state', implode(',', $this->state), true); 611 } 612 613 /** 614 * Initialises a search backend object 615 * 616 * @return false if no error occurred else an error message 617 */ 618 function init_search($type, &$search, &$error) 619 { 620 global $phpbb_root_path, $phpEx, $user; 621 622 if (!preg_match('#^\w+$#', $type) || !file_exists("{$phpbb_root_path}includes/search/$type.$phpEx")) 623 { 624 $error = $user->lang['NO_SUCH_SEARCH_MODULE']; 625 return $error; 626 } 627 628 include_once("{$phpbb_root_path}includes/search/$type.$phpEx"); 629 630 if (!class_exists($type)) 631 { 632 $error = $user->lang['NO_SUCH_SEARCH_MODULE']; 633 return $error; 634 } 635 636 $error = false; 637 $search = new $type($error); 638 639 return $error; 640 } 641 } 642 643 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Oct 2 15:03:47 2013 | Cross-referenced by PHPXref 0.7.1 |