[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/includes/acp/ -> acp_search.php (source)

   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&amp;mode=index') . '">&raquo; ' . $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 . '&amp;action=delete&amp;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 . '&amp;action=create&amp;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&amp;mode=$mode&amp;action=progress_bar"),
 520              'UA_PROGRESS_BAR'        => addslashes(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&amp;mode=$mode&amp;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 . '&amp;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  ?>


Generated: Wed Oct 2 15:03:47 2013 Cross-referenced by PHPXref 0.7.1