Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
acp_search.php
001 <?php
002 /**
003 *
004 * This file is part of the phpBB Forum Software package.
005 *
006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
007 * @license GNU General Public License, version 2 (GPL-2.0)
008 *
009 * For full copyright and license information, please see
010 * the docs/CREDITS.txt file.
011 *
012 */
013
014 /**
015 * @ignore
016 */
017 if (!defined('IN_PHPBB'))
018 {
019 exit;
020 }
021
022 class acp_search
023 {
024 var $u_action;
025 var $state;
026 var $search;
027 var $max_post_id;
028 var $batch_size = 100;
029
030 function main($id, $mode)
031 {
032 global $user;
033
034 $user->add_lang('acp/search');
035
036 // For some this may be of help...
037 @ini_set('memory_limit', '128M');
038
039 switch ($mode)
040 {
041 case 'settings':
042 $this->settings($id, $mode);
043 break;
044
045 case 'index':
046 $this->index($id, $mode);
047 break;
048 }
049 }
050
051 function settings($id, $mode)
052 {
053 global $user, $template, $phpbb_log, $request;
054 global $config, $phpbb_admin_path, $phpEx;
055
056 $submit = $request->is_set_post('submit');
057
058 if ($submit && !check_link_hash($request->variable('hash', ''), 'acp_search'))
059 {
060 trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
061 }
062
063 $search_types = $this->get_search_types();
064
065 $settings = [
066 'search_interval' => 'float',
067 'search_anonymous_interval' => 'float',
068 'load_search' => 'bool',
069 'limit_search_load' => 'float',
070 'min_search_author_chars' => 'integer',
071 'max_num_search_keywords' => 'integer',
072 'default_search_return_chars' => 'integer',
073 'search_store_results' => 'integer',
074 ];
075
076 $search = null;
077 $error = false;
078 $search_options = '';
079 foreach ($search_types as $type)
080 {
081 if ($this->init_search($type, $search, $error))
082 {
083 continue;
084 }
085
086 $name = $search->get_name();
087
088 $selected = ($config['search_type'] == $type) ? ' selected="selected"' : '';
089 $identifier = substr($type, strrpos($type, '\\') + 1);
090 $search_options .= "<option value=\"$type\"$selected data-toggle-setting=\"#search_{$identifier}_settings\">$name</option>";
091
092 if (method_exists($search, 'acp'))
093 {
094 $vars = $search->acp();
095
096 if (!$submit)
097 {
098 $template->assign_block_vars('backend', array(
099 '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 }
678