Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

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

viewforum.php

Zuletzt modifiziert: 01.05.2026, 11:25 - Dateigröße: 41.37 KiB


0001  <?php
0002  /**
0003  *
0004  * This file is part of the phpBB Forum Software package.
0005  *
0006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007  * @license GNU General Public License, version 2 (GPL-2.0)
0008  *
0009  * For full copyright and license information, please see
0010  * the docs/CREDITS.txt file.
0011  *
0012  */
0013   
0014  /**
0015  * @ignore
0016  */
0017  define('IN_PHPBB', true);
0018  $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
0019  $phpEx = substr(strrchr(__FILE__, '.'), 1);
0020  include($phpbb_root_path . 'common.' . $phpEx);
0021  include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
0022   
0023  // Start session
0024  $user->session_begin();
0025  $auth->acl($user->data);
0026   
0027  // Start initial var setup
0028  $forum_id    = $request->variable('f', 0);
0029  $mark_read    = $request->variable('mark', '');
0030  $start        = $request->variable('start', 0);
0031   
0032  $default_sort_days    = (!empty($user->data['user_topic_show_days'])) ? $user->data['user_topic_show_days'] : 0;
0033  $default_sort_key    = (!empty($user->data['user_topic_sortby_type'])) ? $user->data['user_topic_sortby_type'] : 't';
0034  $default_sort_dir    = (!empty($user->data['user_topic_sortby_dir'])) ? $user->data['user_topic_sortby_dir'] : 'd';
0035   
0036  $sort_days    = $request->variable('st', $default_sort_days);
0037  $sort_key    = $request->variable('sk', $default_sort_key);
0038  $sort_dir    = $request->variable('sd', $default_sort_dir);
0039   
0040  /* @var $pagination \phpbb\pagination */
0041  $pagination = $phpbb_container->get('pagination');
0042   
0043  // Check if the user has actually sent a forum ID with his/her request
0044  // If not give them a nice error page.
0045  if (!$forum_id)
0046  {
0047      trigger_error('NO_FORUM');
0048  }
0049   
0050  $sql_ary = [
0051      'SELECT'    => 'f.*',
0052      'FROM'        => [
0053          FORUMS_TABLE        => 'f',
0054      ],
0055      'WHERE'        => 'f.forum_id = ' . $forum_id,
0056  ];
0057   
0058  $lastread_select = '';
0059   
0060  // Grab appropriate forum data
0061  if ($config['load_db_lastread'] && $user->data['is_registered'])
0062  {
0063      $sql_ary['LEFT_JOIN'][] = [
0064          'FROM' => [FORUMS_TRACK_TABLE => 'ft'],
0065          'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND ft.forum_id = f.forum_id',
0066      ];
0067      $sql_ary['SELECT'] .= ', ft.mark_time';
0068  }
0069   
0070  if ($user->data['is_registered'])
0071  {
0072      $sql_ary['LEFT_JOIN'][] = [
0073          'FROM' => [FORUMS_WATCH_TABLE => 'fw'],
0074          'ON' => 'fw.forum_id = f.forum_id AND fw.user_id = ' . $user->data['user_id'],
0075      ];
0076      $sql_ary['SELECT'] .= ', fw.notify_status';
0077  }
0078   
0079  /**
0080   * You can use this event to modify the sql that selects the forum on the viewforum page.
0081   *
0082   * @event core.viewforum_modify_sql
0083   * @var array    sql_ary        The SQL array to get the data for a forum
0084   * @since 3.3.14-RC1
0085   */
0086  $vars = ['sql_ary'];
0087  extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_sql', compact($vars)));
0088  $result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary));
0089  $forum_data = $db->sql_fetchrow($result);
0090  $db->sql_freeresult($result);
0091   
0092  if (!$forum_data)
0093  {
0094      trigger_error('NO_FORUM');
0095  }
0096   
0097   
0098  // Configure style, language, etc.
0099  $user->setup('viewforum', $forum_data['forum_style']);
0100   
0101  // Redirect to login upon emailed notification links
0102  if (isset($_GET['e']) && !$user->data['is_registered'])
0103  {
0104      login_box('', $user->lang['LOGIN_NOTIFY_FORUM']);
0105  }
0106   
0107  // Permissions check
0108  if (!$auth->acl_gets('f_list', 'f_list_topics', 'f_read', $forum_id) || ($forum_data['forum_type'] == FORUM_LINK && $forum_data['forum_link'] && !$auth->acl_get('f_read', $forum_id)))
0109  {
0110      if ($user->data['user_id'] != ANONYMOUS)
0111      {
0112          send_status_line(403, 'Forbidden');
0113          trigger_error('SORRY_AUTH_READ');
0114      }
0115   
0116      login_box('', $user->lang['LOGIN_VIEWFORUM']);
0117  }
0118   
0119  // Forum is passworded ... check whether access has been granted to this
0120  // user this session, if not show login box
0121  if ($forum_data['forum_password'])
0122  {
0123      login_forum_box($forum_data);
0124  }
0125   
0126  // Is this forum a link? ... User got here either because the
0127  // number of clicks is being tracked or they guessed the id
0128  if ($forum_data['forum_type'] == FORUM_LINK && $forum_data['forum_link'])
0129  {
0130      // Does it have click tracking enabled?
0131      if ($forum_data['forum_flags'] & FORUM_FLAG_LINK_TRACK)
0132      {
0133          $sql = 'UPDATE ' . FORUMS_TABLE . '
0134              SET forum_posts_approved = forum_posts_approved + 1
0135              WHERE forum_id = ' . $forum_id;
0136          $db->sql_query($sql);
0137      }
0138   
0139      // We redirect to the url. The third parameter indicates that external redirects are allowed.
0140      redirect($forum_data['forum_link'], false, true);
0141      return;
0142  }
0143   
0144  // Build navigation links
0145  generate_forum_nav($forum_data);
0146   
0147  // Forum Rules
0148  if ($auth->acl_get('f_read', $forum_id))
0149  {
0150      generate_forum_rules($forum_data);
0151  }
0152   
0153  // Do we have subforums?
0154  $active_forum_ary = $moderators = array();
0155   
0156  if ($forum_data['left_id'] != $forum_data['right_id'] - 1)
0157  {
0158      list($active_forum_ary, $moderators) = display_forums($forum_data, $config['load_moderators'], $config['load_moderators']);
0159  }
0160  else
0161  {
0162      $template->assign_var('S_HAS_SUBFORUM', false);
0163      if ($config['load_moderators'])
0164      {
0165          get_moderators($moderators, $forum_id);
0166      }
0167  }
0168   
0169  // Is a forum specific topic count required?
0170  if ($forum_data['forum_topics_per_page'])
0171  {
0172      $config['topics_per_page'] = $forum_data['forum_topics_per_page'];
0173  }
0174   
0175  /* @var $phpbb_content_visibility \phpbb\content_visibility */
0176  $phpbb_content_visibility = $phpbb_container->get('content.visibility');
0177   
0178  // Dump out the page header and load viewforum template
0179  $topics_count = $phpbb_content_visibility->get_count('forum_topics', $forum_data, $forum_id);
0180  $start = $pagination->validate_start($start, $config['topics_per_page'], $topics_count);
0181   
0182  $page_title = $forum_data['forum_name'] . ($start ? ' - ' . $user->lang('PAGE_TITLE_NUMBER', $pagination->get_on_page($config['topics_per_page'], $start)) : '');
0183   
0184  /**
0185  * You can use this event to modify the page title of the viewforum page
0186  *
0187  * @event core.viewforum_modify_page_title
0188  * @var    string    page_title        Title of the viewforum page
0189  * @var    array    forum_data        Array with forum data
0190  * @var    int        forum_id        The forum ID
0191  * @var    int        start            Start offset used to calculate the page
0192  * @since 3.2.2-RC1
0193  */
0194  $vars = array('page_title', 'forum_data', 'forum_id', 'start');
0195  extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_page_title', compact($vars)));
0196   
0197  page_header($page_title, true, $forum_id);
0198   
0199  $template->set_filenames(array(
0200      'body' => 'viewforum_body.html')
0201  );
0202   
0203  make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"), $forum_id);
0204   
0205  $template->assign_vars(array(
0206      'U_VIEW_FORUM'            => append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id" . (($start == 0) ? '' : "&amp;start=$start")),
0207  ));
0208   
0209  // Not postable forum or showing active topics?
0210  if (!($forum_data['forum_type'] == FORUM_POST || (($forum_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) && $forum_data['forum_type'] == FORUM_CAT)))
0211  {
0212      page_footer();
0213  }
0214   
0215  // Ok, if someone has only list-access, we only display the forum list.
0216  // We also make this circumstance available to the template in case we want to display a notice. ;)
0217  if (!$auth->acl_gets('f_read', 'f_list_topics', $forum_id))
0218  {
0219      $template->assign_vars(array(
0220          'S_NO_READ_ACCESS'        => true,
0221      ));
0222   
0223      page_footer();
0224  }
0225   
0226  // Handle marking posts
0227  if ($mark_read == 'topics')
0228  {
0229      $token = $request->variable('hash', '');
0230      if (check_link_hash($token, 'global'))
0231      {
0232          markread('topics', array($forum_id), false, $request->variable('mark_time', 0));
0233      }
0234      $redirect_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
0235      meta_refresh(3, $redirect_url);
0236   
0237      if ($request->is_ajax())
0238      {
0239          // Tell the ajax script what language vars and URL need to be replaced
0240          $data = array(
0241              'NO_UNREAD_POSTS'    => $user->lang['NO_UNREAD_POSTS'],
0242              'UNREAD_POSTS'        => $user->lang['UNREAD_POSTS'],
0243              'U_MARK_TOPICS'        => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . "&f=$forum_id&mark=topics&mark_time=" . time(), false) : '',
0244              'MESSAGE_TITLE'        => $user->lang['INFORMATION'],
0245              'MESSAGE_TEXT'        => $user->lang['TOPICS_MARKED']
0246          );
0247          $json_response = new \phpbb\json_response();
0248          $json_response->send($data);
0249      }
0250   
0251      trigger_error($user->lang['TOPICS_MARKED'] . '<br /><br />' . sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect_url . '">', '</a>'));
0252  }
0253   
0254  // Do the forum Prune thang - cron type job ...
0255  if (!$config['use_system_cron'])
0256  {
0257      /* @var $cron \phpbb\cron\manager */
0258      $cron = $phpbb_container->get('cron.manager');
0259   
0260      $task = $cron->find_task('cron.task.core.prune_forum');
0261      $task->set_forum_data($forum_data);
0262   
0263      if ($task->is_ready())
0264      {
0265          $cron_task_tag = $task->get_html_tag();
0266          $template->assign_var('RUN_CRON_TASK', $cron_task_tag);
0267      }
0268      else
0269      {
0270          // See if we should prune the shadow topics instead
0271          $task = $cron->find_task('cron.task.core.prune_shadow_topics');
0272          $task->set_forum_data($forum_data);
0273   
0274          if ($task->is_ready())
0275          {
0276              $cron_task_tag = $task->get_html_tag();
0277              $template->assign_var('RUN_CRON_TASK', $cron_task_tag);
0278          }
0279      }
0280  }
0281   
0282  // Forum rules and subscription info
0283  $s_watching_forum = array(
0284      'link'            => '',
0285      'link_toggle'    => '',
0286      'title'            => '',
0287      'title_toggle'    => '',
0288      'is_watching'    => false,
0289  );
0290   
0291  if ($config['allow_forum_notify'] && $forum_data['forum_type'] == FORUM_POST && ($auth->acl_get('f_subscribe', $forum_id) || $user->data['user_id'] == ANONYMOUS))
0292  {
0293      $notify_status = (isset($forum_data['notify_status'])) ? $forum_data['notify_status'] : NULL;
0294      watch_topic_forum('forum', $s_watching_forum, $user->data['user_id'], $forum_id, 0, $notify_status, $start, $forum_data['forum_name']);
0295  }
0296   
0297  $s_forum_rules = '';
0298  gen_forum_auth_level('forum', $forum_id, $forum_data['forum_status']);
0299   
0300  // Topic ordering options
0301  $limit_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
0302   
0303  $sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']);
0304  $sort_by_sql = array('a' => 't.topic_first_poster_name', 't' => array('t.topic_last_post_time', 't.topic_last_post_id'), 'r' => (($auth->acl_get('m_approve', $forum_id)) ? 't.topic_posts_approved + t.topic_posts_unapproved + t.topic_posts_softdeleted' : 't.topic_posts_approved'), 's' => 'LOWER(t.topic_title)', 'v' => 't.topic_views');
0305   
0306  /**
0307   * Modify the topic ordering if needed
0308   *
0309   * @event core.viewforum_modify_topic_ordering
0310   * @var array    sort_by_text    Topic ordering options
0311   * @var array    sort_by_sql        Topic orderings options SQL equivalent
0312   * @since 3.2.5-RC1
0313   */
0314  $vars = array(
0315      'sort_by_text',
0316      'sort_by_sql',
0317  );
0318  extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_topic_ordering', compact($vars)));
0319   
0320  $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
0321  gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param, $default_sort_days, $default_sort_key, $default_sort_dir);
0322   
0323  // Limit topics to certain time frame, obtain correct topic count
0324  if ($sort_days)
0325  {
0326      $min_post_time = time() - ($sort_days * 86400);
0327   
0328      $sql_array = array(
0329          'SELECT'    => 'COUNT(t.topic_id) AS num_topics',
0330          'FROM'        => array(
0331              TOPICS_TABLE    => 't',
0332          ),
0333          'WHERE'        => 't.forum_id = ' . $forum_id . '
0334              AND (t.topic_last_post_time >= ' . $min_post_time . '
0335                  OR t.topic_type = ' . POST_ANNOUNCE . '
0336                  OR t.topic_type = ' . POST_GLOBAL . ')
0337              AND ' . $phpbb_content_visibility->get_visibility_sql('topic', $forum_id, 't.'),
0338      );
0339   
0340      /**
0341      * Modify the sort data SQL query for getting additional fields if needed
0342      *
0343      * @event core.viewforum_modify_sort_data_sql
0344      * @var int        forum_id        The forum_id whose topics are being listed
0345      * @var int        start            Variable containing start for pagination
0346      * @var int        sort_days        The oldest topic displayable in elapsed days
0347      * @var string    sort_key        The sorting by. It is one of the first character of (in low case):
0348      *                                Author, Post time, Replies, Subject, Views
0349      * @var string    sort_dir        Either "a" for ascending or "d" for descending
0350      * @var array    sql_array        The SQL array to get the data of all topics
0351      * @since 3.1.9-RC1
0352      */
0353      $vars = array(
0354          'forum_id',
0355          'start',
0356          'sort_days',
0357          'sort_key',
0358          'sort_dir',
0359          'sql_array',
0360      );
0361      extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_sort_data_sql', compact($vars)));
0362   
0363      $result = $db->sql_query($db->sql_build_query('SELECT', $sql_array));
0364      $topics_count = (int) $db->sql_fetchfield('num_topics');
0365      $db->sql_freeresult($result);
0366   
0367      if (isset($_POST['sort']))
0368      {
0369          $start = 0;
0370      }
0371      $sql_limit_time = "AND t.topic_last_post_time >= $min_post_time";
0372   
0373      // Make sure we have information about day selection ready
0374      $template->assign_var('S_SORT_DAYS', true);
0375  }
0376  else
0377  {
0378      $sql_limit_time = '';
0379  }
0380   
0381  // Basic pagewide vars
0382  $post_alt = ($forum_data['forum_status'] == ITEM_LOCKED) ? $user->lang['FORUM_LOCKED'] : $user->lang['POST_NEW_TOPIC'];
0383   
0384  // Display active topics?
0385  $s_display_active = ($forum_data['forum_type'] == FORUM_CAT && ($forum_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS)) ? true : false;
0386   
0387  // Send the forum id... and maybe some other fields, depending on permissions
0388  $s_search_hidden_fields = [
0389      'fid' => [$forum_id],
0390  ];
0391   
0392  if ($auth->acl_get('f_list_topics', $forum_id) && !$auth->acl_get('f_read', $forum_id))
0393  {
0394      // If the user has list access but not read access, then force the search to only be a topic title search
0395      $s_search_hidden_fields['sr'] = 'topics';
0396      $s_search_hidden_fields['sf'] = 'titleonly';
0397  }
0398   
0399  if ($_SID)
0400  {
0401      $s_search_hidden_fields['sid'] = $_SID;
0402  }
0403   
0404  if (!empty($_EXTRA_URL))
0405  {
0406      foreach ($_EXTRA_URL as $url_param)
0407      {
0408          $url_param = explode('=', $url_param, 2);
0409          $s_search_hidden_fields[$url_param[0]] = $url_param[1];
0410      }
0411  }
0412   
0413  $template->assign_vars(array(
0414      'MODERATORS'    => (!empty($moderators[$forum_id])) ? implode($user->lang['COMMA_SEPARATOR'], $moderators[$forum_id]) : '',
0415   
0416      'POST_IMG'                    => ($forum_data['forum_status'] == ITEM_LOCKED) ? $user->img('button_topic_locked', $post_alt) : $user->img('button_topic_new', $post_alt),
0417      'NEWEST_POST_IMG'            => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'),
0418      'LAST_POST_IMG'                => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'),
0419      'FOLDER_IMG'                => $user->img('topic_read', 'NO_UNREAD_POSTS'),
0420      'FOLDER_UNREAD_IMG'            => $user->img('topic_unread', 'UNREAD_POSTS'),
0421      'FOLDER_HOT_IMG'            => $user->img('topic_read_hot', 'NO_UNREAD_POSTS_HOT'),
0422      'FOLDER_HOT_UNREAD_IMG'        => $user->img('topic_unread_hot', 'UNREAD_POSTS_HOT'),
0423      'FOLDER_LOCKED_IMG'            => $user->img('topic_read_locked', 'NO_UNREAD_POSTS_LOCKED'),
0424      'FOLDER_LOCKED_UNREAD_IMG'    => $user->img('topic_unread_locked', 'UNREAD_POSTS_LOCKED'),
0425      'FOLDER_STICKY_IMG'            => $user->img('sticky_read', 'POST_STICKY'),
0426      'FOLDER_STICKY_UNREAD_IMG'    => $user->img('sticky_unread', 'POST_STICKY'),
0427      'FOLDER_ANNOUNCE_IMG'        => $user->img('announce_read', 'POST_ANNOUNCEMENT'),
0428      'FOLDER_ANNOUNCE_UNREAD_IMG'=> $user->img('announce_unread', 'POST_ANNOUNCEMENT'),
0429      'FOLDER_MOVED_IMG'            => $user->img('topic_moved', 'TOPIC_MOVED'),
0430      'REPORTED_IMG'                => $user->img('icon_topic_reported', 'TOPIC_REPORTED'),
0431      'UNAPPROVED_IMG'            => $user->img('icon_topic_unapproved', 'TOPIC_UNAPPROVED'),
0432      'DELETED_IMG'                => $user->img('icon_topic_deleted', 'TOPIC_DELETED'),
0433      'POLL_IMG'                    => $user->img('icon_topic_poll', 'TOPIC_POLL'),
0434      'GOTO_PAGE_IMG'                => $user->img('icon_post_target', 'GOTO_PAGE'),
0435   
0436      'L_NO_TOPICS'             => ($forum_data['forum_status'] == ITEM_LOCKED) ? $user->lang['POST_FORUM_LOCKED'] : $user->lang['NO_TOPICS'],
0437   
0438      'S_DISPLAY_POST_INFO'    => ($forum_data['forum_type'] == FORUM_POST && ($auth->acl_get('f_post', $forum_id) || $user->data['user_id'] == ANONYMOUS)) ? true : false,
0439   
0440      'S_IS_POSTABLE'            => ($forum_data['forum_type'] == FORUM_POST) ? true : false,
0441      'S_USER_CAN_POST'        => ($auth->acl_get('f_post', $forum_id)) ? true : false,
0442      'S_DISPLAY_ACTIVE'        => $s_display_active,
0443      'S_SELECT_SORT_DIR'        => $s_sort_dir,
0444      'S_SELECT_SORT_KEY'        => $s_sort_key,
0445      'S_SELECT_SORT_DAYS'    => $s_limit_days,
0446      'S_TOPIC_ICONS'            => ($s_display_active && count($active_forum_ary)) ? max($active_forum_ary['enable_icons']) : (($forum_data['enable_icons']) ? true : false),
0447      'U_WATCH_FORUM_LINK'    => $s_watching_forum['link'],
0448      'U_WATCH_FORUM_TOGGLE'    => $s_watching_forum['link_toggle'],
0449      'S_WATCH_FORUM_TITLE'    => $s_watching_forum['title'],
0450      'S_WATCH_FORUM_TOGGLE'    => $s_watching_forum['title_toggle'],
0451      'S_WATCHING_FORUM'        => $s_watching_forum['is_watching'],
0452      'S_FORUM_ACTION'        => append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id" . (($start == 0) ? '' : "&amp;start=$start")),
0453      'S_DISPLAY_SEARCHBOX'    => ($auth->acl_get('u_search') && $auth->acl_get('f_search', $forum_id) && $config['load_search']) ? true : false,
0454      'S_SEARCHBOX_ACTION'    => append_sid("{$phpbb_root_path}search.$phpEx"),
0455      'S_SEARCH_LOCAL_HIDDEN_FIELDS'    => build_hidden_fields($s_search_hidden_fields),
0456      'S_SINGLE_MODERATOR'    => (!empty($moderators[$forum_id]) && count($moderators[$forum_id]) > 1) ? false : true,
0457      'S_IS_LOCKED'            => ($forum_data['forum_status'] == ITEM_LOCKED) ? true : false,
0458      'S_VIEWFORUM'            => true,
0459   
0460      'U_MCP'                => ($auth->acl_get('m_', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "f=$forum_id&amp;i=main&amp;mode=forum_view", true, $user->session_id) : '',
0461      'U_POST_NEW_TOPIC'    => ($auth->acl_get('f_post', $forum_id) || $user->data['user_id'] == ANONYMOUS) ? append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=post&amp;f=' . $forum_id) : '',
0462      'U_VIEW_FORUM'        => append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id" . ((strlen($u_sort_param)) ? "&amp;$u_sort_param" : '') . (($start == 0) ? '' : "&amp;start=$start")),
0463      'U_CANONICAL'        => generate_board_url() . '/' . append_sid("viewforum.$phpEx", "f=$forum_id" . (($start) ? "&amp;start=$start" : ''), true, ''),
0464      'U_MARK_TOPICS'        => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . "&amp;f=$forum_id&amp;mark=topics&amp;mark_time=" . time()) : '',
0465      'U_SEARCH_FORUM'    => append_sid("{$phpbb_root_path}search.$phpEx", 'fid%5B%5D=' . $forum_id),
0466  ));
0467   
0468  // Grab icons
0469  $icons = $cache->obtain_icons();
0470   
0471  // Grab all topic data
0472  $rowset = $announcement_list = $topic_list = $global_announce_forums = array();
0473   
0474  $sql_array = array(
0475      'SELECT'    => 't.*',
0476      'FROM'        => array(
0477          TOPICS_TABLE        => 't'
0478      ),
0479      'LEFT_JOIN'    => array(),
0480  );
0481   
0482  /**
0483  * Event to modify the SQL query before the topic data is retrieved
0484  *
0485  * It may also be used to override the above assigned template vars
0486  *
0487  * @event core.viewforum_get_topic_data
0488  * @var    array    forum_data            Array with forum data
0489  * @var    array    sql_array            The SQL array to get the data of all topics
0490  * @var    int        forum_id            The forum_id whose topics are being listed
0491  * @var    int        topics_count        The total number of topics for display
0492  * @var    int        sort_days            The oldest topic displayable in elapsed days
0493  * @var    string    sort_key            The sorting by. It is one of the first character of (in low case):
0494  *                                    Author, Post time, Replies, Subject, Views
0495  * @var    string    sort_dir            Either "a" for ascending or "d" for descending
0496  * @since 3.1.0-a1
0497  * @changed 3.1.0-RC4 Added forum_data var
0498  * @changed 3.1.4-RC1 Added forum_id, topics_count, sort_days, sort_key and sort_dir vars
0499  * @changed 3.1.9-RC1 Fix types of properties
0500  */
0501  $vars = array(
0502      'forum_data',
0503      'sql_array',
0504      'forum_id',
0505      'topics_count',
0506      'sort_days',
0507      'sort_key',
0508      'sort_dir',
0509  );
0510  extract($phpbb_dispatcher->trigger_event('core.viewforum_get_topic_data', compact($vars)));
0511   
0512  $sql_approved = ' AND ' . $phpbb_content_visibility->get_visibility_sql('topic', $forum_id, 't.');
0513   
0514  if ($user->data['is_registered'])
0515  {
0516      if ($config['load_db_track'])
0517      {
0518          $sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_POSTED_TABLE => 'tp'), 'ON' => 'tp.topic_id = t.topic_id AND tp.user_id = ' . $user->data['user_id']);
0519          $sql_array['SELECT'] .= ', tp.topic_posted';
0520      }
0521   
0522      if ($config['load_db_lastread'])
0523      {
0524          $sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_TRACK_TABLE => 'tt'), 'ON' => 'tt.topic_id = t.topic_id AND tt.user_id = ' . $user->data['user_id']);
0525          $sql_array['SELECT'] .= ', tt.mark_time';
0526   
0527          if ($s_display_active && count($active_forum_ary))
0528          {
0529              $sql_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TRACK_TABLE => 'ft'), 'ON' => 'ft.forum_id = t.forum_id AND ft.user_id = ' . $user->data['user_id']);
0530              $sql_array['SELECT'] .= ', ft.mark_time AS forum_mark_time';
0531          }
0532      }
0533  }
0534   
0535  if ($forum_data['forum_type'] == FORUM_POST)
0536  {
0537      // Get global announcement forums
0538      $g_forum_ary = $auth->acl_getf('f_read', true);
0539      $g_forum_ary = array_unique(array_keys($g_forum_ary));
0540   
0541      $sql_anounce_array['LEFT_JOIN'] = $sql_array['LEFT_JOIN'];
0542      $sql_anounce_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TABLE => 'f'), 'ON' => 'f.forum_id = t.forum_id');
0543      $sql_anounce_array['SELECT'] = $sql_array['SELECT'] . ', f.forum_name';
0544   
0545      // Obtain announcements ... removed sort ordering, sort by time in all cases
0546      $sql_ary = array(
0547          'SELECT'    => $sql_anounce_array['SELECT'],
0548          'FROM'        => $sql_array['FROM'],
0549          'LEFT_JOIN'    => $sql_anounce_array['LEFT_JOIN'],
0550   
0551          'WHERE'        => '(t.forum_id = ' . $forum_id . '
0552                  AND t.topic_type = ' . POST_ANNOUNCE . ') OR
0553              (' . $db->sql_in_set('t.forum_id', $g_forum_ary, false, true) . '
0554                  AND t.topic_type = ' . POST_GLOBAL . ')',
0555   
0556          'ORDER_BY'    => 't.topic_time DESC',
0557      );
0558   
0559      /**
0560      * Event to modify the SQL query before the announcement topic ids data is retrieved
0561      *
0562      * @event core.viewforum_get_announcement_topic_ids_data
0563      * @var    array    forum_data            Data about the forum
0564      * @var    array    g_forum_ary            Global announcement forums array
0565      * @var    array    sql_anounce_array    SQL announcement array
0566      * @var    array    sql_ary                SQL query array to get the announcement topic ids data
0567      * @var    int        forum_id            The forum ID
0568      *
0569      * @since 3.1.10-RC1
0570      */
0571      $vars = array(
0572          'forum_data',
0573          'g_forum_ary',
0574          'sql_anounce_array',
0575          'sql_ary',
0576          'forum_id',
0577      );
0578      extract($phpbb_dispatcher->trigger_event('core.viewforum_get_announcement_topic_ids_data', compact($vars)));
0579   
0580      $sql = $db->sql_build_query('SELECT', $sql_ary);
0581      $result = $db->sql_query($sql);
0582   
0583      while ($row = $db->sql_fetchrow($result))
0584      {
0585          if (!$phpbb_content_visibility->is_visible('topic', $row['forum_id'], $row))
0586          {
0587              // Do not display announcements that are waiting for approval or soft deleted.
0588              continue;
0589          }
0590   
0591          $rowset[$row['topic_id']] = $row;
0592          $announcement_list[] = $row['topic_id'];
0593   
0594          if ($forum_id != $row['forum_id'])
0595          {
0596              $topics_count++;
0597              $global_announce_forums[] = $row['forum_id'];
0598          }
0599      }
0600      $db->sql_freeresult($result);
0601  }
0602   
0603  $forum_tracking_info = array();
0604   
0605  if ($user->data['is_registered'] && $config['load_db_lastread'])
0606  {
0607      $forum_tracking_info[$forum_id] = $forum_data['mark_time'];
0608   
0609      if (!empty($global_announce_forums))
0610      {
0611          $sql = 'SELECT forum_id, mark_time
0612              FROM ' . FORUMS_TRACK_TABLE . '
0613              WHERE ' . $db->sql_in_set('forum_id', $global_announce_forums) . '
0614                  AND user_id = ' . $user->data['user_id'];
0615          $result = $db->sql_query($sql);
0616   
0617          while ($row = $db->sql_fetchrow($result))
0618          {
0619              $forum_tracking_info[$row['forum_id']] = $row['mark_time'];
0620          }
0621          $db->sql_freeresult($result);
0622      }
0623  }
0624   
0625  // If the user is trying to reach late pages, start searching from the end
0626  $store_reverse = false;
0627  $sql_limit = $config['topics_per_page'];
0628  if ($start > $topics_count / 2)
0629  {
0630      $store_reverse = true;
0631   
0632      // Select the sort order
0633      $direction = (($sort_dir == 'd') ? 'ASC' : 'DESC');
0634   
0635      $sql_limit = $pagination->reverse_limit($start, $sql_limit, $topics_count - count($announcement_list));
0636      $sql_start = $pagination->reverse_start($start, $sql_limit, $topics_count - count($announcement_list));
0637  }
0638  else
0639  {
0640      // Select the sort order
0641      $direction = (($sort_dir == 'd') ? 'DESC' : 'ASC');
0642      $sql_start = $start;
0643  }
0644   
0645  /**
0646   * Modify the topics sort ordering if needed
0647   *
0648   * @event core.viewforum_modify_sort_direction
0649   * @var string    direction    Topics sort order
0650   * @since 3.2.5-RC1
0651   */
0652  $vars = array(
0653      'direction',
0654  );
0655  extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_sort_direction', compact($vars)));
0656   
0657  if (is_array($sort_by_sql[$sort_key]))
0658  {
0659      $sql_sort_order = implode(' ' . $direction . ', ', $sort_by_sql[$sort_key]) . ' ' . $direction;
0660  }
0661  else
0662  {
0663      $sql_sort_order = $sort_by_sql[$sort_key] . ' ' . $direction;
0664  }
0665   
0666  if ($forum_data['forum_type'] == FORUM_POST || !count($active_forum_ary))
0667  {
0668      $sql_where = 't.forum_id = ' . $forum_id;
0669  }
0670  else if (empty($active_forum_ary['exclude_forum_id']))
0671  {
0672      $sql_where = $db->sql_in_set('t.forum_id', $active_forum_ary['forum_id']);
0673  }
0674  else
0675  {
0676      $get_forum_ids = array_diff($active_forum_ary['forum_id'], $active_forum_ary['exclude_forum_id']);
0677      $sql_where = (count($get_forum_ids)) ? $db->sql_in_set('t.forum_id', $get_forum_ids) : 't.forum_id = ' . $forum_id;
0678  }
0679   
0680  // Grab just the sorted topic ids
0681  $sql_ary = array(
0682      'SELECT'    => 't.topic_id',
0683      'FROM'        => array(
0684          TOPICS_TABLE => 't',
0685      ),
0686      'WHERE'        => "$sql_where
0687          AND t.topic_type IN (" . POST_NORMAL . ', ' . POST_STICKY . ")
0688          $sql_approved
0689          $sql_limit_time",
0690      'ORDER_BY'    => 't.topic_type ' . ((!$store_reverse) ? 'DESC' : 'ASC') . ', ' . $sql_sort_order,
0691  );
0692   
0693  /**
0694  * Event to modify the SQL query before the topic ids data is retrieved
0695  *
0696  * @event core.viewforum_get_topic_ids_data
0697  * @var    array    forum_data        Data about the forum
0698  * @var    array    sql_ary            SQL query array to get the topic ids data
0699  * @var    string    sql_approved    Topic visibility SQL string
0700  * @var    int        sql_limit        Number of records to select
0701  * @var    string    sql_limit_time    SQL string to limit topic_last_post_time data
0702  * @var    array    sql_sort_order    SQL sorting string
0703  * @var    int        sql_start        Offset point to start selection from
0704  * @var    string    sql_where        SQL WHERE clause string
0705  * @var    bool    store_reverse    Flag indicating if we select from the late pages
0706  *
0707  * @since 3.1.0-RC4
0708  *
0709  * @changed 3.1.3 Added forum_data
0710  */
0711  $vars = array(
0712      'forum_data',
0713      'sql_ary',
0714      'sql_approved',
0715      'sql_limit',
0716      'sql_limit_time',
0717      'sql_sort_order',
0718      'sql_start',
0719      'sql_where',
0720      'store_reverse',
0721  );
0722  extract($phpbb_dispatcher->trigger_event('core.viewforum_get_topic_ids_data', compact($vars)));
0723   
0724  $sql = $db->sql_build_query('SELECT', $sql_ary);
0725  $result = $db->sql_query_limit($sql, $sql_limit, $sql_start);
0726   
0727  while ($row = $db->sql_fetchrow($result))
0728  {
0729      $topic_list[] = (int) $row['topic_id'];
0730  }
0731  $db->sql_freeresult($result);
0732   
0733  // For storing shadow topics
0734  $shadow_topic_list = array();
0735   
0736  if (count($topic_list))
0737  {
0738      // SQL array for obtaining topics/stickies
0739      $sql_array = array(
0740          'SELECT'        => $sql_array['SELECT'],
0741          'FROM'            => $sql_array['FROM'],
0742          'LEFT_JOIN'        => $sql_array['LEFT_JOIN'],
0743          'WHERE'            => $db->sql_in_set('t.topic_id', $topic_list),
0744      );
0745   
0746      /**
0747      * Event to modify the SQL query before obtaining topics/stickies
0748      *
0749      * @event core.viewforum_modify_topic_list_sql
0750      * @var    int        forum_id            The forum ID
0751      * @var    array    forum_data            Data about the forum
0752      * @var    array    topic_list            Topic ids array
0753      * @var    array    sql_array            SQL query array for obtaining topics/stickies
0754      *
0755      * @since 3.2.10-RC1
0756      * @since 3.3.1-RC1
0757      */
0758      $vars = [
0759          'forum_id',
0760          'forum_data',
0761          'topic_list',
0762          'sql_array',
0763      ];
0764      extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_topic_list_sql', compact($vars)));
0765   
0766      // If store_reverse, then first obtain topics, then stickies, else the other way around...
0767      // Funnily enough you typically save one query if going from the last page to the middle (store_reverse) because
0768      // the number of stickies are not known
0769      $sql = $db->sql_build_query('SELECT', $sql_array);
0770      $result = $db->sql_query($sql);
0771   
0772      while ($row = $db->sql_fetchrow($result))
0773      {
0774          if ($row['topic_status'] == ITEM_MOVED)
0775          {
0776              $shadow_topic_list[$row['topic_moved_id']] = $row['topic_id'];
0777          }
0778   
0779          $rowset[$row['topic_id']] = $row;
0780      }
0781      $db->sql_freeresult($result);
0782  }
0783   
0784  // If we have some shadow topics, update the rowset to reflect their topic information
0785  if (count($shadow_topic_list))
0786  {
0787      // SQL array for obtaining shadow topics
0788      $sql_array = array(
0789          'SELECT'    => 't.*',
0790          'FROM'        => array(
0791              TOPICS_TABLE        => 't'
0792          ),
0793          'WHERE'        => $db->sql_in_set('t.topic_id', array_keys($shadow_topic_list)),
0794      );
0795   
0796      /**
0797      * Event to modify the SQL query before the shadowtopic data is retrieved
0798      *
0799      * @event core.viewforum_get_shadowtopic_data
0800      * @var    array    sql_array        SQL array to get the data of any shadowtopics
0801      * @since 3.1.0-a1
0802      */
0803      $vars = array('sql_array');
0804      extract($phpbb_dispatcher->trigger_event('core.viewforum_get_shadowtopic_data', compact($vars)));
0805   
0806      $sql = $db->sql_build_query('SELECT', $sql_array);
0807      $result = $db->sql_query($sql);
0808   
0809      while ($row = $db->sql_fetchrow($result))
0810      {
0811          $orig_topic_id = $shadow_topic_list[$row['topic_id']];
0812   
0813          // If the shadow topic is already listed within the rowset (happens for active topics for example), then do not include it...
0814          if (isset($rowset[$row['topic_id']]))
0815          {
0816              // We need to remove any trace regarding this topic. :)
0817              unset($rowset[$orig_topic_id]);
0818              unset($topic_list[array_search($orig_topic_id, $topic_list)]);
0819              $topics_count--;
0820   
0821              continue;
0822          }
0823   
0824          // Do not include those topics the user has no permission to access
0825          if (!$auth->acl_gets('f_read', 'f_list_topics', $row['forum_id']))
0826          {
0827              // We need to remove any trace regarding this topic. :)
0828              unset($rowset[$orig_topic_id]);
0829              unset($topic_list[array_search($orig_topic_id, $topic_list)]);
0830              $topics_count--;
0831   
0832              continue;
0833          }
0834   
0835          // We want to retain some values
0836          $row = array_merge($row, array(
0837              'topic_moved_id'    => $rowset[$orig_topic_id]['topic_moved_id'],
0838              'topic_status'        => $rowset[$orig_topic_id]['topic_status'],
0839              'topic_type'        => $rowset[$orig_topic_id]['topic_type'],
0840              'topic_title'        => $rowset[$orig_topic_id]['topic_title'],
0841          ));
0842   
0843          // Shadow topics are never reported
0844          $row['topic_reported'] = 0;
0845   
0846          $rowset[$orig_topic_id] = $row;
0847      }
0848      $db->sql_freeresult($result);
0849  }
0850  unset($shadow_topic_list);
0851   
0852  // Ok, adjust topics count for active topics list
0853  if ($s_display_active)
0854  {
0855      $topics_count = 1;
0856  }
0857   
0858  // We need to remove the global announcements from the forums total topic count,
0859  // otherwise the number is different from the one on the forum list
0860  $total_topic_count = $topics_count - count($announcement_list);
0861   
0862  $base_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id" . ((strlen($u_sort_param)) ? "&amp;$u_sort_param" : ''));
0863  $pagination->generate_template_pagination($base_url, 'pagination', 'start', $total_topic_count, $config['topics_per_page'], $start);
0864   
0865  $template->assign_vars(array(
0866      'TOTAL_TOPICS'    => ($s_display_active) ? false : $user->lang('VIEW_FORUM_TOPICS', (int) $total_topic_count),
0867  ));
0868   
0869  $topic_list = ($store_reverse) ? array_merge($announcement_list, array_reverse($topic_list)) : array_merge($announcement_list, $topic_list);
0870  $topic_tracking_info = $tracking_topics = array();
0871   
0872  /**
0873  * Modify topics data before we display the viewforum page
0874  *
0875  * @event core.viewforum_modify_topics_data
0876  * @var    array    topic_list            Array with current viewforum page topic ids
0877  * @var    array    rowset                Array with topics data (in topic_id => topic_data format)
0878  * @var    int        total_topic_count    Forum's total topic count
0879  * @var    int        forum_id            Forum identifier
0880  * @since 3.1.0-b3
0881  * @changed 3.1.11-RC1 Added forum_id
0882  */
0883  $vars = array('topic_list', 'rowset', 'total_topic_count', 'forum_id');
0884  extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_topics_data', compact($vars)));
0885   
0886  // Okay, lets dump out the page ...
0887  if (count($topic_list))
0888  {
0889      $mark_forum_read = true;
0890      $mark_time_forum = 0;
0891   
0892      // Generate topic forum list...
0893      $topic_forum_list = array();
0894      foreach ($rowset as $t_id => $row)
0895      {
0896          if (isset($forum_tracking_info[$row['forum_id']]))
0897          {
0898              $row['forum_mark_time'] = $forum_tracking_info[$row['forum_id']];
0899          }
0900   
0901          $topic_forum_list[$row['forum_id']]['forum_mark_time'] = ($config['load_db_lastread'] && $user->data['is_registered'] && isset($row['forum_mark_time'])) ? $row['forum_mark_time'] : 0;
0902          $topic_forum_list[$row['forum_id']]['topics'][] = (int) $t_id;
0903      }
0904   
0905      if ($config['load_db_lastread'] && $user->data['is_registered'])
0906      {
0907          foreach ($topic_forum_list as $f_id => $topic_row)
0908          {
0909              $topic_tracking_info += get_topic_tracking($f_id, $topic_row['topics'], $rowset, array($f_id => $topic_row['forum_mark_time']));
0910          }
0911      }
0912      else if ($config['load_anon_lastread'] || $user->data['is_registered'])
0913      {
0914          foreach ($topic_forum_list as $f_id => $topic_row)
0915          {
0916              $topic_tracking_info += get_complete_topic_tracking($f_id, $topic_row['topics']);
0917          }
0918      }
0919   
0920      unset($topic_forum_list);
0921   
0922      if (!$s_display_active)
0923      {
0924          if ($config['load_db_lastread'] && $user->data['is_registered'])
0925          {
0926              $mark_time_forum = (!empty($forum_data['mark_time'])) ? $forum_data['mark_time'] : $user->data['user_lastmark'];
0927          }
0928          else if ($config['load_anon_lastread'] || $user->data['is_registered'])
0929          {
0930              if (!$user->data['is_registered'])
0931              {
0932                  $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate']) : 0;
0933              }
0934              $mark_time_forum = (isset($tracking_topics['f'][$forum_id])) ? (int) (base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate']) : $user->data['user_lastmark'];
0935          }
0936      }
0937   
0938      $s_type_switch = 0;
0939      foreach ($topic_list as $topic_id)
0940      {
0941          $row = &$rowset[$topic_id];
0942   
0943          $topic_forum_id = ($row['forum_id']) ? (int) $row['forum_id'] : $forum_id;
0944   
0945          // This will allow the style designer to output a different header
0946          // or even separate the list of announcements from sticky and normal topics
0947          $s_type_switch_test = ($row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL) ? 1 : 0;
0948   
0949          // Replies
0950          $replies = $phpbb_content_visibility->get_count('topic_posts', $row, $topic_forum_id) - 1;
0951          // Correction for case of unapproved topic visible to poster
0952          if ($replies < 0)
0953          {
0954              $replies = 0;
0955          }
0956   
0957          if ($row['topic_status'] == ITEM_MOVED)
0958          {
0959              $topic_id = $row['topic_moved_id'];
0960              $unread_topic = false;
0961          }
0962          else
0963          {
0964              $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false;
0965          }
0966   
0967          // Get folder img, topic status/type related information
0968          $folder_img = $folder_alt = $topic_type = '';
0969          topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type);
0970   
0971          // Generate all the URIs ...
0972          $view_topic_url_params = 't=' . $topic_id;
0973          $view_topic_url = $auth->acl_get('f_read', $forum_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params) : false;
0974   
0975          $topic_unapproved = (($row['topic_visibility'] == ITEM_UNAPPROVED || $row['topic_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $row['forum_id']));
0976          $posts_unapproved = ($row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $auth->acl_get('m_approve', $row['forum_id']));
0977          $topic_deleted = $row['topic_visibility'] == ITEM_DELETED;
0978   
0979          $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . "&amp;t=$topic_id", true, $user->session_id) : '';
0980          $u_mcp_queue = (!$u_mcp_queue && $topic_deleted) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=deleted_topics&amp;t=' . $topic_id, true, $user->session_id) : $u_mcp_queue;
0981   
0982          // Send vars to template
0983          $topic_row = array(
0984              'FORUM_ID'                    => $row['forum_id'],
0985              'TOPIC_ID'                    => $topic_id,
0986              'TOPIC_AUTHOR'                => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
0987              'TOPIC_AUTHOR_COLOUR'        => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
0988              'TOPIC_AUTHOR_FULL'            => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
0989              'FIRST_POST_TIME'            => $user->format_date($row['topic_time']),
0990              'FIRST_POST_TIME_RFC3339'    => gmdate(DATE_RFC3339, $row['topic_time']),
0991              'LAST_POST_SUBJECT'            => censor_text($row['topic_last_post_subject']),
0992              'LAST_POST_TIME'            => $user->format_date($row['topic_last_post_time']),
0993              'LAST_POST_TIME_RFC3339'    => gmdate(DATE_RFC3339, $row['topic_last_post_time']),
0994              'LAST_VIEW_TIME'            => $user->format_date($row['topic_last_view_time']),
0995              'LAST_VIEW_TIME_RFC3339'    => gmdate(DATE_RFC3339, $row['topic_last_view_time']),
0996              'LAST_POST_AUTHOR'            => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
0997              'LAST_POST_AUTHOR_COLOUR'    => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
0998              'LAST_POST_AUTHOR_FULL'        => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
0999   
1000              'REPLIES'            => $replies,
1001              'VIEWS'                => $row['topic_views'],
1002              'TOPIC_TITLE'        => censor_text($row['topic_title']),
1003              'TOPIC_TYPE'        => $topic_type,
1004              'FORUM_NAME'        => (isset($row['forum_name'])) ? $row['forum_name'] : $forum_data['forum_name'],
1005   
1006              'TOPIC_IMG_STYLE'        => $folder_img,
1007              'TOPIC_FOLDER_IMG'        => $user->img($folder_img, $folder_alt),
1008              'TOPIC_FOLDER_IMG_ALT'    => $user->lang[$folder_alt],
1009   
1010              'TOPIC_ICON_IMG'        => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '',
1011              'TOPIC_ICON_IMG_WIDTH'    => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '',
1012              'TOPIC_ICON_IMG_HEIGHT'    => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '',
1013              'ATTACH_ICON_IMG'        => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
1014              'UNAPPROVED_IMG'        => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '',
1015   
1016              'S_TOPIC_TYPE'            => $row['topic_type'],
1017              'S_USER_POSTED'            => (isset($row['topic_posted']) && $row['topic_posted']) ? true : false,
1018              'S_UNREAD_TOPIC'        => $unread_topic,
1019              'S_TOPIC_REPORTED'        => (!empty($row['topic_reported']) && $auth->acl_get('m_report', $row['forum_id'])) ? true : false,
1020              'S_TOPIC_UNAPPROVED'    => $topic_unapproved,
1021              'S_POSTS_UNAPPROVED'    => $posts_unapproved,
1022              'S_TOPIC_DELETED'        => $topic_deleted,
1023              'S_HAS_POLL'            => ($row['poll_start']) ? true : false,
1024              'S_POST_ANNOUNCE'        => ($row['topic_type'] == POST_ANNOUNCE) ? true : false,
1025              'S_POST_GLOBAL'            => ($row['topic_type'] == POST_GLOBAL) ? true : false,
1026              'S_POST_STICKY'            => ($row['topic_type'] == POST_STICKY) ? true : false,
1027              'S_TOPIC_LOCKED'        => ($row['topic_status'] == ITEM_LOCKED) ? true : false,
1028              'S_TOPIC_MOVED'            => ($row['topic_status'] == ITEM_MOVED) ? true : false,
1029   
1030              'U_NEWEST_POST'            => $auth->acl_get('f_read', $forum_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&amp;view=unread') . '#unread' : false,
1031              'U_LAST_POST'            => $auth->acl_get('f_read', $forum_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'] : false,
1032              'U_LAST_POST_AUTHOR'    => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
1033              'U_TOPIC_AUTHOR'        => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
1034              'U_VIEW_TOPIC'            => $view_topic_url,
1035              'U_VIEW_FORUM'            => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']),
1036              'U_MCP_REPORT'            => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=reports&amp;t=' . $topic_id, true, $user->session_id),
1037              'U_MCP_QUEUE'            => $u_mcp_queue,
1038   
1039              'S_TOPIC_TYPE_SWITCH'    => ($s_type_switch == $s_type_switch_test) ? -1 : $s_type_switch_test,
1040          );
1041   
1042          /**
1043          * Modify the topic data before it is assigned to the template
1044          *
1045          * @event core.viewforum_modify_topicrow
1046          * @var    array    row                    Array with topic data
1047          * @var    array    topic_row            Template array with topic data
1048          * @var    bool    s_type_switch        Flag indicating if the topic type is [global] announcement
1049          * @var    bool    s_type_switch_test    Flag indicating if the test topic type is [global] announcement
1050          * @since 3.1.0-a1
1051          *
1052          * @changed 3.1.10-RC1 Added s_type_switch, s_type_switch_test
1053          */
1054          $vars = array('row', 'topic_row', 's_type_switch', 's_type_switch_test');
1055          extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_topicrow', compact($vars)));
1056   
1057          $template->assign_block_vars('topicrow', $topic_row);
1058   
1059          $pagination->generate_template_pagination($topic_row['U_VIEW_TOPIC'], 'topicrow.pagination', 'start', (int) $topic_row['REPLIES'] + 1, $config['posts_per_page'], 1, true, true);
1060   
1061          $s_type_switch = ($row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL) ? 1 : 0;
1062   
1063          /**
1064          * Event after the topic data has been assigned to the template
1065          *
1066          * @event core.viewforum_topic_row_after
1067          * @var    array    row                Array with the topic data
1068          * @var    array    rowset            Array with topics data (in topic_id => topic_data format)
1069          * @var    bool    s_type_switch    Flag indicating if the topic type is [global] announcement
1070          * @var    int        topic_id        The topic ID
1071          * @var    array    topic_list        Array with current viewforum page topic ids
1072          * @var    array    topic_row        Template array with topic data
1073          * @since 3.1.3-RC1
1074          */
1075          $vars = array(
1076              'row',
1077              'rowset',
1078              's_type_switch',
1079              'topic_id',
1080              'topic_list',
1081              'topic_row',
1082          );
1083          extract($phpbb_dispatcher->trigger_event('core.viewforum_topic_row_after', compact($vars)));
1084   
1085          if ($unread_topic)
1086          {
1087              $mark_forum_read = false;
1088          }
1089   
1090          unset($rowset[$topic_id]);
1091      }
1092  }
1093   
1094  /**
1095  * This event is to perform additional actions on viewforum page
1096  *
1097  * @event core.viewforum_generate_page_after
1098  * @var    array    forum_data    Array with the forum data
1099  * @since 3.2.2-RC1
1100  */
1101  $vars = array('forum_data');
1102  extract($phpbb_dispatcher->trigger_event('core.viewforum_generate_page_after', compact($vars)));
1103   
1104  // This is rather a fudge but it's the best I can think of without requiring information
1105  // on all topics (as we do in 2.0.x). It looks for unread or new topics, if it doesn't find
1106  // any it updates the forum last read cookie. This requires that the user visit the forum
1107  // after reading a topic
1108  if ($forum_data['forum_type'] == FORUM_POST && count($topic_list) && $mark_forum_read)
1109  {
1110      update_forum_tracking_info($forum_id, $forum_data['forum_last_post_time'], false, $mark_time_forum);
1111  }
1112   
1113  page_footer();
1114