phpBB
Statistics
| Revision:

root / branches / phpBB-3_0_0 / phpBB / includes / acp / acp_search.php

History | View | Annotate | Download (16.8 kB)

1
<?php
2
/**
3
*
4
* @package acp
5
* @version $Id: acp_search.php 11063 2011-03-15 01:15:08Z git-gate $
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
?>