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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

log.php

Zuletzt modifiziert: 09.10.2024, 12:52 - Dateigröße: 27.09 KiB


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&amp;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']] . '&amp;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']] . '&amp;t=' . $row['topic_id'] . '&amp;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&amp;mode=topic_logs&amp;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