Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
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 |
log.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 namespace phpbb\log;
015
016 /**
017 * This class is used to add entries into the log table.
018 */
019 class log implements \phpbb\log\log_interface
020 {
021 /**
022 * If set, administrative user profile links will be returned and messages
023 * will not be censored.
024 * @var bool
025 */
026 protected $is_in_admin;
027
028 /**
029 * An array with the disabled log types. Logs of such types will not be
030 * added when add() is called.
031 * @var array
032 */
033 protected $disabled_types;
034
035 /**
036 * Keeps the total log count of the last call to get_logs()
037 * @var int
038 */
039 protected $entry_count;
040
041 /**
042 * Keeps the offset of the last valid page of the last call to get_logs()
043 * @var int
044 */
045 protected $last_page_offset;
046
047 /**
048 * The table we use to store our logs.
049 * @var string
050 */
051 protected $log_table;
052
053 /**
054 * Database object
055 * @var \phpbb\db\driver\driver
056 */
057 protected $db;
058
059 /**
060 * User object
061 * @var \phpbb\user
062 */
063 protected $user;
064
065 /**
066 * Auth object
067 * @var \phpbb\auth\auth
068 */
069 protected $auth;
070
071 /**
072 * Event dispatcher object
073 * @var \phpbb\event\dispatcher_interface
074 */
075 protected $dispatcher;
076
077 /**
078 * phpBB root path
079 * @var string
080 */
081 protected $phpbb_root_path;
082
083 /**
084 * Admin root path
085 * @var string
086 */
087 protected $phpbb_admin_path;
088
089 /**
090 * PHP Extension
091 * @var string
092 */
093 protected $php_ext;
094
095 /**
096 * Constructor
097 *
098 * @param \phpbb\db\driver\driver_interface $db Database object
099 * @param \phpbb\user $user User object
100 * @param \phpbb\auth\auth $auth Auth object
101 * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher
102 * @param string $phpbb_root_path Root path
103 * @param string $relative_admin_path Relative admin root path
104 * @param string $php_ext PHP Extension
105 * @param string $log_table Name of the table we use to store our logs
106 */
107 public function __construct($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, $relative_admin_path, $php_ext, $log_table)
108 {
109 $this->db = $db;
110 $this->user = $user;
111 $this->auth = $auth;
112 $this->dispatcher = $phpbb_dispatcher;
113 $this->phpbb_root_path = $phpbb_root_path;
114 $this->phpbb_admin_path = $this->phpbb_root_path . $relative_admin_path;
115 $this->php_ext = $php_ext;
116 $this->log_table = $log_table;
117
118 /*
119 * IN_ADMIN is set after the session is created,
120 * so we need to take ADMIN_START into account as well, otherwise
121 * it will not work for the \phpbb\log\log object we create in common.php
122 */
123 $this->set_is_admin((defined('ADMIN_START') && ADMIN_START) || (defined('IN_ADMIN') && IN_ADMIN));
124 $this->enable();
125 }
126
127 /**
128 * Set is_in_admin in order to return administrative user profile links
129 * in get_logs()
130 *
131 * @param bool $is_in_admin Are we called from within the acp?
132 * @return null
133 */
134 public function set_is_admin($is_in_admin)
135 {
136 $this->is_in_admin = (bool) $is_in_admin;
137 }
138
139 /**
140 * Returns the is_in_admin option
141 *
142 * @return bool
143 */
144 public function get_is_admin()
145 {
146 return $this->is_in_admin;
147 }
148
149 /**
150 * Set table name
151 *
152 * @param string $log_table Can overwrite the table to use for the logs
153 * @return null
154 */
155 public function set_log_table($log_table)
156 {
157 $this->log_table = $log_table;
158 }
159
160 /**
161 * {@inheritDoc}
162 */
163 public function is_enabled($type = '')
164 {
165 if ($type == '' || $type == 'all')
166 {
167 return !isset($this->disabled_types['all']);
168 }
169 return !isset($this->disabled_types[$type]) && !isset($this->disabled_types['all']);
170 }
171
172 /**
173 * {@inheritDoc}
174 */
175 public function disable($type = '')
176 {
177 if (is_array($type))
178 {
179 foreach ($type as $disable_type)
180 {
181 $this->disable($disable_type);
182 }
183 return;
184 }
185
186 // Empty string is an equivalent for all types.
187 if ($type == '')
188 {
189 $type = 'all';
190 }
191 $this->disabled_types[$type] = true;
192 }
193
194 /**
195 * {@inheritDoc}
196 */
197 public function enable($type = '')
198 {
199 if (is_array($type))
200 {
201 foreach ($type as $enable_type)
202 {
203 $this->enable($enable_type);
204 }
205 return;
206 }
207
208 if ($type == '' || $type == 'all')
209 {
210 $this->disabled_types = array();
211 return;
212 }
213 unset($this->disabled_types[$type]);
214 }
215
216 /**
217 * {@inheritDoc}
218 */
219 public function add($mode, $user_id, $log_ip, $log_operation, $log_time = false, $additional_data = array())
220 {
221 if (!$this->is_enabled($mode))
222 {
223 return false;
224 }
225
226 if ($log_time === false)
227 {
228 $log_time = time();
229 }
230
231 $sql_ary = array(
232 'user_id' => !empty($user_id) ? $user_id : ANONYMOUS,
233 'log_ip' => !empty($log_ip) ? $log_ip : '',
234 'log_time' => $log_time,
235 'log_operation' => $log_operation,
236 );
237
238 switch ($mode)
239 {
240 case 'admin':
241 $sql_ary += array(
242 'log_type' => LOG_ADMIN,
243 'log_data' => (!empty($additional_data)) ? serialize($additional_data) : '',
244 );
245 break;
246
247 case 'mod':
248 $forum_id = isset($additional_data['forum_id']) ? (int) $additional_data['forum_id'] : 0;
249 unset($additional_data['forum_id']);
250 $topic_id = isset($additional_data['topic_id']) ? (int) $additional_data['topic_id'] : 0;
251 unset($additional_data['topic_id']);
252 $post_id = isset($additional_data['post_id']) ? (int) $additional_data['post_id'] : 0;
253 unset($additional_data['post_id']);
254 $sql_ary += array(
255 'log_type' => LOG_MOD,
256 'forum_id' => $forum_id,
257 'topic_id' => $topic_id,
258 'post_id' => $post_id,
259 'log_data' => (!empty($additional_data)) ? serialize($additional_data) : '',
260 );
261 break;
262
263 case 'user':
264 $reportee_id = (int) $additional_data['reportee_id'];
265 unset($additional_data['reportee_id']);
266
267 $sql_ary += array(
268 'log_type' => LOG_USERS,
269 'reportee_id' => $reportee_id,
270 'log_data' => (!empty($additional_data)) ? serialize($additional_data) : '',
271 );
272 break;
273
274 case 'critical':
275 $sql_ary += array(
276 'log_type' => LOG_CRITICAL,
277 'log_data' => (!empty($additional_data)) ? serialize($additional_data) : '',
278 );
279 break;
280 }
281
282 /**
283 * Allows to modify log data before we add it to the database
284 *
285 * NOTE: if sql_ary does not contain a log_type value, the entry will
286 * not be stored in the database. So ensure to set it, if needed.
287 *
288 * @event core.add_log
289 * @var string mode Mode of the entry we log
290 * @var int user_id ID of the user who triggered the log
291 * @var string log_ip IP of the user who triggered the log
292 * @var string log_operation Language key of the log operation
293 * @var int log_time Timestamp, when the log was added
294 * @var array additional_data Array with additional log data
295 * @var array sql_ary Array with log data we insert into the
296 * database. If sql_ary[log_type] is not set,
297 * we won't add the entry to the database.
298 * @since 3.1.0-a1
299 */
300 $vars = array(
301 'mode',
302 'user_id',
303 'log_ip',
304 'log_operation',
305 'log_time',
306 'additional_data',
307 'sql_ary',
308 );
309 extract($this->dispatcher->trigger_event('core.add_log', compact($vars)));
310
311 // We didn't find a log_type, so we don't save it in the database.
312 if (!isset($sql_ary['log_type']))
313 {
314 return false;
315 }
316
317 $this->db->sql_query('INSERT INTO ' . $this->log_table . ' ' . $this->db->sql_build_array('INSERT', $sql_ary));
318
319 return $this->db->sql_nextid();
320 }
321
322 /**
323 * {@inheritDoc}
324 */
325 public function delete($mode, $conditions = array())
326 {
327 switch ($mode)
328 {
329 case 'admin':
330 $log_type = LOG_ADMIN;
331 break;
332
333 case 'mod':
334 $log_type = LOG_MOD;
335 break;
336
337 case 'user':
338 $log_type = LOG_USERS;
339 break;
340
341 case 'users':
342 $log_type = LOG_USERS;
343 break;
344
345 case 'critical':
346 $log_type = LOG_CRITICAL;
347 break;
348
349 default:
350 $log_type = false;
351 }
352
353 /**
354 * Allows to modify log data before we delete it from the database
355 *
356 * NOTE: if sql_ary does not contain a log_type value, the entry will
357 * not be deleted in the database. So ensure to set it, if needed.
358 *
359 * @event core.delete_log
360 * @var string mode Mode of the entry we log
361 * @var string log_type Type ID of the log (should be different than false)
362 * @var array conditions An array of conditions, 3 different forms are accepted
363 * 1) <key> => <value> transformed into 'AND <key> = <value>' (value should be an integer)
364 * 2) <key> => array(<operator>, <value>) transformed into 'AND <key> <operator> <value>' (values can't be an array)
365 * 3) <key> => array('IN' => array(<values>)) transformed into 'AND <key> IN <values>'
366 * A special field, keywords, can also be defined. In this case only the log entries that have the keywords in log_operation or log_data will be deleted.
367 * @since 3.1.0-b4
368 */
369 $vars = array(
370 'mode',
371 'log_type',
372 'conditions',
373 );
374 extract($this->dispatcher->trigger_event('core.delete_log', compact($vars)));
375
376 if ($log_type === false)
377 {
378 return;
379 }
380
381 $sql_where = 'WHERE log_type = ' . $log_type;
382
383 if (isset($conditions['keywords']))
384 {
385 $sql_where .= $this->generate_sql_keyword($conditions['keywords'], '');
386
387 unset($conditions['keywords']);
388 }
389
390 foreach ($conditions as $field => $field_value)
391 {
392 $sql_where .= ' AND ';
393
394 if (is_array($field_value) && sizeof($field_value) == 2 && !is_array($field_value[1]))
395 {
396 $sql_where .= $field . ' ' . $field_value[0] . ' ' . $field_value[1];
397 }
398 else if (is_array($field_value) && isset($field_value['IN']) && is_array($field_value['IN']))
399 {
400 $sql_where .= $this->db->sql_in_set($field, $field_value['IN']);
401 }
402 else
403 {
404 $sql_where .= $field . ' = ' . $field_value;
405 }
406 }
407
408 $sql = 'DELETE FROM ' . $this->log_table . "
409 $sql_where";
410 $this->db->sql_query($sql);
411
412 $this->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CLEAR_' . strtoupper($mode));
413 }
414
415 /**
416 * {@inheritDoc}
417 */
418 public function get_logs($mode, $count_logs = true, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $log_time = 0, $sort_by = 'l.log_time DESC', $keywords = '')
419 {
420 $this->entry_count = 0;
421 $this->last_page_offset = $offset;
422
423 $topic_id_list = $reportee_id_list = array();
424
425 $profile_url = ($this->get_is_admin() && $this->phpbb_admin_path) ? append_sid("{$this->phpbb_admin_path}index.{$this->php_ext}", 'i=users&mode=overview') : append_sid("{$this->phpbb_root_path}memberlist.{$this->php_ext}", 'mode=viewprofile');
426
427 switch ($mode)
428 {
429 case 'admin':
430 $log_type = LOG_ADMIN;
431 $sql_additional = '';
432 break;
433
434 case 'mod':
435 $log_type = LOG_MOD;
436 $sql_additional = '';
437
438 if ($topic_id)
439 {
440 $sql_additional = 'AND l.topic_id = ' . (int) $topic_id;
441 }
442 else if (is_array($forum_id))
443 {
444 $sql_additional = 'AND ' . $this->db->sql_in_set('l.forum_id', array_map('intval', $forum_id));
445 }
446 else if ($forum_id)
447 {
448 $sql_additional = 'AND l.forum_id = ' . (int) $forum_id;
449 }
450 break;
451
452 case 'user':
453 $log_type = LOG_USERS;
454 $sql_additional = 'AND l.reportee_id = ' . (int) $user_id;
455 break;
456
457 case 'users':
458 $log_type = LOG_USERS;
459 $sql_additional = '';
460 break;
461
462 case 'critical':
463 $log_type = LOG_CRITICAL;
464 $sql_additional = '';
465 break;
466
467 default:
468 $log_type = false;
469 $sql_additional = '';
470 }
471
472 /**
473 * Overwrite log type and limitations before we count and get the logs
474 *
475 * NOTE: if log_type is false, no entries will be returned.
476 *
477 * @event core.get_logs_modify_type
478 * @var string mode Mode of the entries we display
479 * @var bool count_logs Do we count all matching entries?
480 * @var int limit Limit the number of entries
481 * @var int offset Offset when fetching the entries
482 * @var mixed forum_id Limit entries to the forum_id,
483 * can also be an array of forum_ids
484 * @var int topic_id Limit entries to the topic_id
485 * @var int user_id Limit entries to the user_id
486 * @var int log_time Limit maximum age of log entries
487 * @var string sort_by SQL order option
488 * @var string keywords Will only return entries that have the
489 * keywords in log_operation or log_data
490 * @var string profile_url URL to the users profile
491 * @var int log_type Limit logs to a certain type. If log_type
492 * is false, no entries will be returned.
493 * @var string sql_additional Additional conditions for the entries,
494 * e.g.: 'AND l.forum_id = 1'
495 * @since 3.1.0-a1
496 */
497 $vars = array(
498 'mode',
499 'count_logs',
500 'limit',
501 'offset',
502 'forum_id',
503 'topic_id',
504 'user_id',
505 'log_time',
506 'sort_by',
507 'keywords',
508 'profile_url',
509 'log_type',
510 'sql_additional',
511 );
512 extract($this->dispatcher->trigger_event('core.get_logs_modify_type', compact($vars)));
513
514 if ($log_type === false)
515 {
516 $this->last_page_offset = 0;
517 return array();
518 }
519
520 $sql_keywords = '';
521 if (!empty($keywords))
522 {
523 // Get the SQL condition for our keywords
524 $sql_keywords = $this->generate_sql_keyword($keywords);
525 }
526
527 $get_logs_sql_ary = array(
528 'SELECT' => 'l.*, u.username, u.username_clean, u.user_colour',
529 'FROM' => array(
530 $this->log_table => 'l',
531 USERS_TABLE => 'u',
532 ),
533 'WHERE' => 'l.log_type = ' . (int) $log_type . "
534 AND l.user_id = u.user_id
535 $sql_keywords
536 $sql_additional",
537
538 'ORDER_BY' => $sort_by,
539 );
540
541 if ($log_time)
542 {
543 $get_logs_sql_ary['WHERE'] = 'l.log_time >= ' . (int) $log_time . '
544 AND ' . $get_logs_sql_ary['WHERE'];
545 }
546
547 /**
548 * Modify the query to obtain the logs data
549 *
550 * @event core.get_logs_main_query_before
551 * @var array get_logs_sql_ary The array in the format of the query builder with the query
552 * to get the log count and the log list
553 * @var string mode Mode of the entries we display
554 * @var bool count_logs Do we count all matching entries?
555 * @var int limit Limit the number of entries
556 * @var int offset Offset when fetching the entries
557 * @var mixed forum_id Limit entries to the forum_id,
558 * can also be an array of forum_ids
559 * @var int topic_id Limit entries to the topic_id
560 * @var int user_id Limit entries to the user_id
561 * @var int log_time Limit maximum age of log entries
562 * @var string sort_by SQL order option
563 * @var string keywords Will only return entries that have the
564 * keywords in log_operation or log_data
565 * @var string profile_url URL to the users profile
566 * @var int log_type Limit logs to a certain type. If log_type
567 * is false, no entries will be returned.
568 * @var string sql_additional Additional conditions for the entries,
569 * e.g.: 'AND l.forum_id = 1'
570 * @since 3.1.5-RC1
571 */
572 $vars = array(
573 'get_logs_sql_ary',
574 'mode',
575 'count_logs',
576 'limit',
577 'offset',
578 'forum_id',
579 'topic_id',
580 'user_id',
581 'log_time',
582 'sort_by',
583 'keywords',
584 'profile_url',
585 'log_type',
586 'sql_additional',
587 );
588 extract($this->dispatcher->trigger_event('core.get_logs_main_query_before', compact($vars)));
589
590 if ($count_logs)
591 {
592 $count_logs_sql_ary = $get_logs_sql_ary;
593
594 $count_logs_sql_ary['SELECT'] = 'COUNT(l.log_id) AS total_entries';
595 unset($count_logs_sql_ary['ORDER_BY']);
596
597 $sql = $this->db->sql_build_query('SELECT', $count_logs_sql_ary);
598 $result = $this->db->sql_query($sql);
599 $this->entry_count = (int) $this->db->sql_fetchfield('total_entries');
600 $this->db->sql_freeresult($result);
601
602 if ($this->entry_count == 0)
603 {
604 // Save the queries, because there are no logs to display
605 $this->last_page_offset = 0;
606 return array();
607 }
608
609 // Return the user to the last page that is valid
610 while ($this->last_page_offset >= $this->entry_count)
611 {
612 $this->last_page_offset = max(0, $this->last_page_offset - $limit);
613 }
614 }
615
616 $sql = $this->db->sql_build_query('SELECT', $get_logs_sql_ary);
617 $result = $this->db->sql_query_limit($sql, $limit, $this->last_page_offset);
618
619 $i = 0;
620 $log = array();
621 while ($row = $this->db->sql_fetchrow($result))
622 {
623 $row['forum_id'] = (int) $row['forum_id'];
624 if ($row['topic_id'])
625 {
626 $topic_id_list[] = (int) $row['topic_id'];
627 }
628
629 if ($row['reportee_id'])
630 {
631 $reportee_id_list[] = (int) $row['reportee_id'];
632 }
633
634 $log_entry_data = array(
635 'id' => (int) $row['log_id'],
636
637 'reportee_id' => (int) $row['reportee_id'],
638 'reportee_username' => '',
639 'reportee_username_full'=> '',
640
641 'user_id' => (int) $row['user_id'],
642 'username' => $row['username'],
643 'username_full' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $profile_url),
644
645 'ip' => $row['log_ip'],
646 'time' => (int) $row['log_time'],
647 'forum_id' => (int) $row['forum_id'],
648 'topic_id' => (int) $row['topic_id'],
649 'post_id' => (int) $row['post_id'],
650
651 'viewforum' => ($row['forum_id'] && $this->auth->acl_get('f_read', $row['forum_id'])) ? append_sid("{$this->phpbb_root_path}viewforum.{$this->php_ext}", 'f=' . $row['forum_id']) : false,
652 'action' => (isset($this->user->lang[$row['log_operation']])) ? $row['log_operation'] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}',
653 );
654
655 /**
656 * Modify the entry's data before it is returned
657 *
658 * @event core.get_logs_modify_entry_data
659 * @var array row Entry data from the database
660 * @var array log_entry_data Entry's data which is returned
661 * @since 3.1.0-a1
662 */
663 $vars = array('row', 'log_entry_data');
664 extract($this->dispatcher->trigger_event('core.get_logs_modify_entry_data', compact($vars)));
665
666 $log[$i] = $log_entry_data;
667
668 if (!empty($row['log_data']))
669 {
670 $log_data_ary = unserialize($row['log_data']);
671 $log_data_ary = ($log_data_ary !== false) ? $log_data_ary : array();
672
673 if (isset($this->user->lang[$row['log_operation']]))
674 {
675 // Check if there are more occurrences of % than
676 // arguments, if there are we fill out the arguments
677 // array. It doesn't matter if we add more arguments than
678 // placeholders.
679 $num_args = 0;
680 if (!is_array($this->user->lang[$row['log_operation']]))
681 {
682 $num_args = substr_count($this->user->lang[$row['log_operation']], '%');
683 }
684 else
685 {
686 foreach ($this->user->lang[$row['log_operation']] as $case => $plural_string)
687 {
688 $num_args = max($num_args, substr_count($plural_string, '%'));
689 }
690 }
691
692 if (($num_args - sizeof($log_data_ary)) > 0)
693 {
694 $log_data_ary = array_merge($log_data_ary, array_fill(0, $num_args - sizeof($log_data_ary), ''));
695 }
696
697 $lang_arguments = array_merge(array($log[$i]['action']), $log_data_ary);
698 $log[$i]['action'] = call_user_func_array(array($this->user, 'lang'), $lang_arguments);
699
700 // If within the admin panel we do not censor text out
701 if ($this->get_is_admin())
702 {
703 $log[$i]['action'] = bbcode_nl2br($log[$i]['action']);
704 }
705 else
706 {
707 $log[$i]['action'] = bbcode_nl2br(censor_text($log[$i]['action']));
708 }
709 }
710 else if (!empty($log_data_ary))
711 {
712 $log[$i]['action'] .= '<br />' . implode('', $log_data_ary);
713 }
714
715 /* Apply make_clickable... has to be seen if it is for good. :/
716 // Seems to be not for the moment, reconsider later...
717 $log[$i]['action'] = make_clickable($log[$i]['action']);
718 */
719 }
720 else
721 {
722 $log[$i]['action'] = $this->user->lang($log[$i]['action']);
723 }
724
725 $i++;
726 }
727 $this->db->sql_freeresult($result);
728
729 /**
730 * Get some additional data after we got all log entries
731 *
732 * @event core.get_logs_get_additional_data
733 * @var array log Array with all our log entries
734 * @var array topic_id_list Array of topic ids, for which we
735 * get the permission data
736 * @var array reportee_id_list Array of additional user IDs we
737 * get the username strings for
738 * @since 3.1.0-a1
739 */
740 $vars = array('log', 'topic_id_list', 'reportee_id_list');
741 extract($this->dispatcher->trigger_event('core.get_logs_get_additional_data', compact($vars)));
742
743 if (sizeof($topic_id_list))
744 {
745 $topic_auth = $this->get_topic_auth($topic_id_list);
746
747 foreach ($log as $key => $row)
748 {
749 $log[$key]['viewtopic'] = (isset($topic_auth['f_read'][$row['topic_id']])) ? append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&t=' . $row['topic_id']) : false;
750 $log[$key]['viewpost'] = (isset($topic_auth['f_read'][$row['topic_id']]) && $row['post_id']) ? append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&t=' . $row['topic_id'] . '&p=' . $row['post_id']) : false;
751 $log[$key]['viewlogs'] = (isset($topic_auth['m_'][$row['topic_id']])) ? append_sid("{$this->phpbb_root_path}mcp.{$this->php_ext}", 'i=logs&mode=topic_logs&t=' . $row['topic_id'], true, $this->user->session_id) : false;
752 }
753 }
754
755 if (sizeof($reportee_id_list))
756 {
757 $reportee_data_list = $this->get_reportee_data($reportee_id_list);
758
759 foreach ($log as $key => $row)
760 {
761 if (!isset($reportee_data_list[$row['reportee_id']]))
762 {
763 continue;
764 }
765
766 $log[$key]['reportee_username'] = $reportee_data_list[$row['reportee_id']]['username'];
767 $log[$key]['reportee_username_full'] = get_username_string('full', $row['reportee_id'], $reportee_data_list[$row['reportee_id']]['username'], $reportee_data_list[$row['reportee_id']]['user_colour'], false, $profile_url);
768 }
769 }
770
771 /**
772 * Allow modifying or execute extra final filter on log entries
773 *
774 * @event core.get_logs_after
775 * @var array log Array with all our log entries
776 * @var array topic_id_list Array of topic ids, for which we
777 * get the permission data
778 * @var array reportee_id_list Array of additional user IDs we
779 * get the username strings for
780 * @var string mode Mode of the entries we display
781 * @var bool count_logs Do we count all matching entries?
782 * @var int limit Limit the number of entries
783 * @var int offset Offset when fetching the entries
784 * @var mixed forum_id Limit entries to the forum_id,
785 * can also be an array of forum_ids
786 * @var int topic_id Limit entries to the topic_id
787 * @var int user_id Limit entries to the user_id
788 * @var int log_time Limit maximum age of log entries
789 * @var string sort_by SQL order option
790 * @var string keywords Will only return entries that have the
791 * keywords in log_operation or log_data
792 * @var string profile_url URL to the users profile
793 * @var int log_type The type of logs it was filtered
794 * @since 3.1.3-RC1
795 */
796 $vars = array(
797 'log',
798 'topic_id_list',
799 'reportee_id_list',
800 'mode',
801 'count_logs',
802 'limit',
803 'offset',
804 'forum_id',
805 'topic_id',
806 'user_id',
807 'log_time',
808 'sort_by',
809 'keywords',
810 'profile_url',
811 'log_type',
812 );
813 extract($this->dispatcher->trigger_event('core.get_logs_after', compact($vars)));
814
815 return $log;
816 }
817
818 /**
819 * Generates a sql condition for the specified keywords
820 *
821 * @param string $keywords The keywords the user specified to search for
822 * @param string $table_alias The alias of the logs' table ('l.' by default)
823 * @param string $statement_operator The operator used to prefix the statement ('AND' by default)
824 *
825 * @return string Returns the SQL condition searching for the keywords
826 */
827 protected function generate_sql_keyword($keywords, $table_alias = 'l.', $statement_operator = 'AND')
828 {
829 // Use no preg_quote for $keywords because this would lead to sole
830 // backslashes being added. We also use an OR connection here for
831 // spaces and the | string. Currently, regex is not supported for
832 // searching (but may come later).
833 $keywords = preg_split('#[\s|]+#u', utf8_strtolower($keywords), 0, PREG_SPLIT_NO_EMPTY);
834 $sql_keywords = '';
835
836 if (!empty($keywords))
837 {
838 $keywords_pattern = array();
839
840 // Build pattern and keywords...
841 for ($i = 0, $num_keywords = sizeof($keywords); $i < $num_keywords; $i++)
842 {
843 $keywords_pattern[] = preg_quote($keywords[$i], '#');
844 $keywords[$i] = $this->db->sql_like_expression($this->db->get_any_char() . $keywords[$i] . $this->db->get_any_char());
845 }
846
847 $keywords_pattern = '#' . implode('|', $keywords_pattern) . '#ui';
848
849 $operations = array();
850 foreach ($this->user->lang as $key => $value)
851 {
852 if (substr($key, 0, 4) == 'LOG_')
853 {
854 if (is_array($value))
855 {
856 foreach ($value as $plural_value)
857 {
858 if (preg_match($keywords_pattern, $plural_value))
859 {
860 $operations[] = $key;
861 break;
862 }
863 }
864 }
865 else if (preg_match($keywords_pattern, $value))
866 {
867 $operations[] = $key;
868 }
869 }
870 }
871
872 $sql_keywords = ' ' . $statement_operator . ' (';
873 if (!empty($operations))
874 {
875 $sql_keywords .= $this->db->sql_in_set($table_alias . 'log_operation', $operations) . ' OR ';
876 }
877 $sql_lower = $this->db->sql_lower_text($table_alias . 'log_data');
878 $sql_keywords .= " $sql_lower " . implode(" OR $sql_lower ", $keywords) . ')';
879 }
880
881 return $sql_keywords;
882 }
883
884 /**
885 * Determine whether the user is allowed to read and/or moderate the forum of the topic
886 *
887 * @param array $topic_ids Array with the topic ids
888 *
889 * @return array Returns an array with two keys 'm_' and 'read_f' which are also an array of topic_id => forum_id sets when the permissions are given. Sample:
890 * array(
891 * 'permission' => array(
892 * topic_id => forum_id
893 * ),
894 * ),
895 */
896 protected function get_topic_auth(array $topic_ids)
897 {
898 $forum_auth = array('f_read' => array(), 'm_' => array());
899 $topic_ids = array_unique($topic_ids);
900
901 $sql_ary = array(
902 'SELECT' => 'topic_id, forum_id',
903 'FROM' => array(
904 TOPICS_TABLE => 't',
905 ),
906 'WHERE' => $this->db->sql_in_set('topic_id', array_map('intval', $topic_ids)),
907 );
908
909 /**
910 * Allow modifying SQL query before topic data is retrieved.
911 *
912 * @event core.phpbb_log_get_topic_auth_sql_before
913 * @var array topic_ids Array with unique topic IDs
914 * @var array sql_ary SQL array
915 * @since 3.1.11-RC1
916 */
917 $vars = array(
918 'topic_ids',
919 'sql_ary',
920 );
921 extract($this->dispatcher->trigger_event('core.phpbb_log_get_topic_auth_sql_before', compact($vars)));
922
923 $sql = $this->db->sql_build_query('SELECT', $sql_ary);
924 $result = $this->db->sql_query($sql);
925
926 while ($row = $this->db->sql_fetchrow($result))
927 {
928 $row['topic_id'] = (int) $row['topic_id'];
929 $row['forum_id'] = (int) $row['forum_id'];
930
931 if ($this->auth->acl_get('f_read', $row['forum_id']))
932 {
933 $forum_auth['f_read'][$row['topic_id']] = $row['forum_id'];
934 }
935
936 if ($this->auth->acl_gets('a_', 'm_', $row['forum_id']))
937 {
938 $forum_auth['m_'][$row['topic_id']] = $row['forum_id'];
939 }
940 }
941 $this->db->sql_freeresult($result);
942
943 return $forum_auth;
944 }
945
946 /**
947 * Get the data for all reportee from the database
948 *
949 * @param array $reportee_ids Array with the user ids of the reportees
950 *
951 * @return array Returns an array with the reportee data
952 */
953 protected function get_reportee_data(array $reportee_ids)
954 {
955 $reportee_ids = array_unique($reportee_ids);
956 $reportee_data_list = array();
957
958 $sql = 'SELECT user_id, username, user_colour
959 FROM ' . USERS_TABLE . '
960 WHERE ' . $this->db->sql_in_set('user_id', $reportee_ids);
961 $result = $this->db->sql_query($sql);
962
963 while ($row = $this->db->sql_fetchrow($result))
964 {
965 $reportee_data_list[$row['user_id']] = $row;
966 }
967 $this->db->sql_freeresult($result);
968
969 return $reportee_data_list;
970 }
971
972 /**
973 * {@inheritDoc}
974 */
975 public function get_log_count()
976 {
977 return ($this->entry_count) ? $this->entry_count : 0;
978 }
979
980 /**
981 * {@inheritDoc}
982 */
983 public function get_valid_offset()
984 {
985 return ($this->last_page_offset) ? $this->last_page_offset : 0;
986 }
987 }
988