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

mcp_main.php

Zuletzt modifiziert: 09.10.2024, 12:52 - Dateigröße: 48.27 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  if (!defined('IN_PHPBB'))
 0018  {
 0019      exit;
 0020  }
 0021   
 0022  /**
 0023  * mcp_main
 0024  * Handling mcp actions
 0025  */
 0026  class mcp_main
 0027  {
 0028      var $p_master;
 0029      var $u_action;
 0030   
 0031      function mcp_main(&$p_master)
 0032      {
 0033          $this->p_master = &$p_master;
 0034      }
 0035   
 0036      function main($id, $mode)
 0037      {
 0038          global $auth, $user, $action;
 0039          global $phpbb_root_path, $phpEx, $request;
 0040          global $phpbb_dispatcher;
 0041   
 0042          $quickmod = ($mode == 'quickmod') ? true : false;
 0043   
 0044          switch ($action)
 0045          {
 0046              case 'lock':
 0047              case 'unlock':
 0048                  $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
 0049   
 0050                  if (!sizeof($topic_ids))
 0051                  {
 0052                      trigger_error('NO_TOPIC_SELECTED');
 0053                  }
 0054   
 0055                  lock_unlock($action, $topic_ids);
 0056              break;
 0057   
 0058              case 'lock_post':
 0059              case 'unlock_post':
 0060   
 0061                  $post_ids = (!$quickmod) ? $request->variable('post_id_list', array(0)) : array($request->variable('p', 0));
 0062   
 0063                  if (!sizeof($post_ids))
 0064                  {
 0065                      trigger_error('NO_POST_SELECTED');
 0066                  }
 0067   
 0068                  lock_unlock($action, $post_ids);
 0069              break;
 0070   
 0071              case 'make_announce':
 0072              case 'make_sticky':
 0073              case 'make_global':
 0074              case 'make_normal':
 0075   
 0076                  $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
 0077   
 0078                  if (!sizeof($topic_ids))
 0079                  {
 0080                      trigger_error('NO_TOPIC_SELECTED');
 0081                  }
 0082   
 0083                  change_topic_type($action, $topic_ids);
 0084              break;
 0085   
 0086              case 'move':
 0087                  $user->add_lang('viewtopic');
 0088   
 0089                  $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
 0090   
 0091                  if (!sizeof($topic_ids))
 0092                  {
 0093                      trigger_error('NO_TOPIC_SELECTED');
 0094                  }
 0095   
 0096                  mcp_move_topic($topic_ids);
 0097              break;
 0098   
 0099              case 'fork':
 0100                  $user->add_lang('viewtopic');
 0101   
 0102                  $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
 0103   
 0104                  if (!sizeof($topic_ids))
 0105                  {
 0106                      trigger_error('NO_TOPIC_SELECTED');
 0107                  }
 0108   
 0109                  mcp_fork_topic($topic_ids);
 0110              break;
 0111   
 0112              case 'delete_topic':
 0113                  $user->add_lang('viewtopic');
 0114   
 0115                  // f parameter is not reliable for permission usage, however we just use it to decide
 0116                  // which permission we will check later on. So if it is manipulated, we will still catch it later on.
 0117                  $forum_id = $request->variable('f', 0);
 0118                  $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
 0119                  $soft_delete = (($request->is_set_post('confirm') && !$request->is_set_post('delete_permanent')) || !$auth->acl_get('m_delete', $forum_id)) ? true : false;
 0120   
 0121                  if (!sizeof($topic_ids))
 0122                  {
 0123                      trigger_error('NO_TOPIC_SELECTED');
 0124                  }
 0125   
 0126                  mcp_delete_topic($topic_ids, $soft_delete, $request->variable('delete_reason', '', true));
 0127              break;
 0128   
 0129              case 'delete_post':
 0130                  $user->add_lang('posting');
 0131   
 0132                  // f parameter is not reliable for permission usage, however we just use it to decide
 0133                  // which permission we will check later on. So if it is manipulated, we will still catch it later on.
 0134                  $forum_id = $request->variable('f', 0);
 0135                  $post_ids = (!$quickmod) ? $request->variable('post_id_list', array(0)) : array($request->variable('p', 0));
 0136                  $soft_delete = (($request->is_set_post('confirm') && !$request->is_set_post('delete_permanent')) || !$auth->acl_get('m_delete', $forum_id)) ? true : false;
 0137   
 0138                  if (!sizeof($post_ids))
 0139                  {
 0140                      trigger_error('NO_POST_SELECTED');
 0141                  }
 0142   
 0143                  mcp_delete_post($post_ids, $soft_delete, $request->variable('delete_reason', '', true));
 0144              break;
 0145   
 0146              case 'restore_topic':
 0147                  $user->add_lang('posting');
 0148   
 0149                  $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
 0150   
 0151                  if (!sizeof($topic_ids))
 0152                  {
 0153                      trigger_error('NO_TOPIC_SELECTED');
 0154                  }
 0155   
 0156                  mcp_restore_topic($topic_ids);
 0157              break;
 0158   
 0159              default:
 0160                  /**
 0161                  * This event allows you to handle custom quickmod options
 0162                  *
 0163                  * @event core.modify_quickmod_actions
 0164                  * @var    string    action        Topic quick moderation action name
 0165                  * @var    bool    quickmod    Flag indicating whether MCP is in quick moderation mode
 0166                  * @since 3.1.0-a4
 0167                  * @change 3.1.0-RC4 Added variables: action, quickmod
 0168                  */
 0169                  $vars = array('action', 'quickmod');
 0170                  extract($phpbb_dispatcher->trigger_event('core.modify_quickmod_actions', compact($vars)));
 0171              break;
 0172          }
 0173   
 0174          switch ($mode)
 0175          {
 0176              case 'front':
 0177                  include($phpbb_root_path . 'includes/mcp/mcp_front.' . $phpEx);
 0178   
 0179                  $user->add_lang('acp/common');
 0180   
 0181                  mcp_front_view($id, $mode, $action);
 0182   
 0183                  $this->tpl_name = 'mcp_front';
 0184                  $this->page_title = 'MCP_MAIN';
 0185              break;
 0186   
 0187              case 'forum_view':
 0188                  include($phpbb_root_path . 'includes/mcp/mcp_forum.' . $phpEx);
 0189   
 0190                  $user->add_lang('viewforum');
 0191   
 0192                  $forum_id = $request->variable('f', 0);
 0193   
 0194                  $forum_info = phpbb_get_forum_data($forum_id, 'm_', true);
 0195   
 0196                  if (!sizeof($forum_info))
 0197                  {
 0198                      $this->main('main', 'front');
 0199                      return;
 0200                  }
 0201   
 0202                  $forum_info = $forum_info[$forum_id];
 0203   
 0204                  mcp_forum_view($id, $mode, $action, $forum_info);
 0205   
 0206                  $this->tpl_name = 'mcp_forum';
 0207                  $this->page_title = 'MCP_MAIN_FORUM_VIEW';
 0208              break;
 0209   
 0210              case 'topic_view':
 0211                  include($phpbb_root_path . 'includes/mcp/mcp_topic.' . $phpEx);
 0212   
 0213                  mcp_topic_view($id, $mode, $action);
 0214   
 0215                  $this->tpl_name = 'mcp_topic';
 0216                  $this->page_title = 'MCP_MAIN_TOPIC_VIEW';
 0217              break;
 0218   
 0219              case 'post_details':
 0220                  include($phpbb_root_path . 'includes/mcp/mcp_post.' . $phpEx);
 0221   
 0222                  mcp_post_details($id, $mode, $action);
 0223   
 0224                  $this->tpl_name = ($action == 'whois') ? 'mcp_whois' : 'mcp_post';
 0225                  $this->page_title = 'MCP_MAIN_POST_DETAILS';
 0226              break;
 0227   
 0228              default:
 0229                  if ($quickmod)
 0230                  {
 0231                      switch ($action)
 0232                      {
 0233                          case 'lock':
 0234                          case 'unlock':
 0235                          case 'make_announce':
 0236                          case 'make_sticky':
 0237                          case 'make_global':
 0238                          case 'make_normal':
 0239                          case 'make_onindex':
 0240                          case 'move':
 0241                          case 'fork':
 0242                          case 'delete_topic':
 0243                              trigger_error('TOPIC_NOT_EXIST');
 0244                          break;
 0245   
 0246                          case 'lock_post':
 0247                          case 'unlock_post':
 0248                          case 'delete_post':
 0249                              trigger_error('POST_NOT_EXIST');
 0250                          break;
 0251                      }
 0252                  }
 0253   
 0254                  trigger_error('NO_MODE', E_USER_ERROR);
 0255              break;
 0256          }
 0257      }
 0258  }
 0259   
 0260  /**
 0261  * Lock/Unlock Topic/Post
 0262  */
 0263  function lock_unlock($action, $ids)
 0264  {
 0265      global $user, $db, $request, $phpbb_log, $phpbb_dispatcher;
 0266   
 0267      if ($action == 'lock' || $action == 'unlock')
 0268      {
 0269          $table = TOPICS_TABLE;
 0270          $sql_id = 'topic_id';
 0271          $set_id = 'topic_status';
 0272          $l_prefix = 'TOPIC';
 0273      }
 0274      else
 0275      {
 0276          $table = POSTS_TABLE;
 0277          $sql_id = 'post_id';
 0278          $set_id = 'post_edit_locked';
 0279          $l_prefix = 'POST';
 0280      }
 0281   
 0282      $orig_ids = $ids;
 0283   
 0284      if (!phpbb_check_ids($ids, $table, $sql_id, array('m_lock')))
 0285      {
 0286          // Make sure that for f_user_lock only the lock action is triggered.
 0287          if ($action != 'lock')
 0288          {
 0289              return;
 0290          }
 0291   
 0292          $ids = $orig_ids;
 0293   
 0294          if (!phpbb_check_ids($ids, $table, $sql_id, array('f_user_lock')))
 0295          {
 0296              return;
 0297          }
 0298      }
 0299      unset($orig_ids);
 0300   
 0301      $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
 0302      $redirect = reapply_sid($redirect);
 0303   
 0304      $s_hidden_fields = build_hidden_fields(array(
 0305          $sql_id . '_list'    => $ids,
 0306          'action'            => $action,
 0307          'redirect'            => $redirect)
 0308      );
 0309   
 0310      if (confirm_box(true))
 0311      {
 0312          $sql = "UPDATE $table
 0313              SET $set_id = " . (($action == 'lock' || $action == 'lock_post') ? ITEM_LOCKED : ITEM_UNLOCKED) . '
 0314              WHERE ' . $db->sql_in_set($sql_id, $ids);
 0315          $db->sql_query($sql);
 0316   
 0317          $data = ($action == 'lock' || $action == 'unlock') ? phpbb_get_topic_data($ids) : phpbb_get_post_data($ids);
 0318   
 0319          foreach ($data as $id => $row)
 0320          {
 0321              $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($action), false, array(
 0322                  'forum_id' => $row['forum_id'],
 0323                  'topic_id' => $row['topic_id'],
 0324                  'post_id'  => isset($row['post_id']) ? $row['post_id'] : 0,
 0325                  $row['topic_title']
 0326              ));
 0327          }
 0328   
 0329          /**
 0330           * Perform additional actions after locking/unlocking posts/topics
 0331           *
 0332           * @event core.mcp_lock_unlock_after
 0333           * @var    string    action                Variable containing the action we perform on the posts/topics ('lock', 'unlock', 'lock_post' or 'unlock_post')
 0334           * @var    array    ids                    Array containing the post/topic IDs that have been locked/unlocked
 0335           * @var    array    data                Array containing posts/topics data
 0336           * @since 3.1.7-RC1
 0337           */
 0338          $vars = array(
 0339              'action',
 0340              'ids',
 0341              'data',
 0342          );
 0343          extract($phpbb_dispatcher->trigger_event('core.mcp_lock_unlock_after', compact($vars)));
 0344   
 0345          $success_msg = $l_prefix . ((sizeof($ids) == 1) ? '' : 'S') . '_' . (($action == 'lock' || $action == 'lock_post') ? 'LOCKED' : 'UNLOCKED') . '_SUCCESS';
 0346   
 0347          meta_refresh(2, $redirect);
 0348          $message = $user->lang[$success_msg];
 0349   
 0350          if (!$request->is_ajax())
 0351          {
 0352              $message .= '<br /><br />' . $user->lang('RETURN_PAGE', '<a href="' . $redirect . '">', '</a>');
 0353          }
 0354          trigger_error($message);
 0355      }
 0356      else
 0357      {
 0358          confirm_box(false, strtoupper($action) . '_' . $l_prefix . ((sizeof($ids) == 1) ? '' : 'S'), $s_hidden_fields);
 0359      }
 0360   
 0361      redirect($redirect);
 0362  }
 0363   
 0364  /**
 0365  * Change Topic Type
 0366  */
 0367  function change_topic_type($action, $topic_ids)
 0368  {
 0369      global $user, $db, $request, $phpbb_log;
 0370   
 0371      switch ($action)
 0372      {
 0373          case 'make_announce':
 0374              $new_topic_type = POST_ANNOUNCE;
 0375              $check_acl = 'f_announce';
 0376              $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_ANNOUNCEMENT' : 'MCP_MAKE_ANNOUNCEMENTS';
 0377          break;
 0378   
 0379          case 'make_global':
 0380              $new_topic_type = POST_GLOBAL;
 0381              $check_acl = 'f_announce_global';
 0382              $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_GLOBAL' : 'MCP_MAKE_GLOBALS';
 0383          break;
 0384   
 0385          case 'make_sticky':
 0386              $new_topic_type = POST_STICKY;
 0387              $check_acl = 'f_sticky';
 0388              $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_STICKY' : 'MCP_MAKE_STICKIES';
 0389          break;
 0390   
 0391          default:
 0392              $new_topic_type = POST_NORMAL;
 0393              $check_acl = false;
 0394              $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_NORMAL' : 'MCP_MAKE_NORMALS';
 0395          break;
 0396      }
 0397   
 0398      $forum_id = phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', $check_acl, true);
 0399   
 0400      if ($forum_id === false)
 0401      {
 0402          return;
 0403      }
 0404   
 0405      $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
 0406      $redirect = reapply_sid($redirect);
 0407   
 0408      $s_hidden_fields = array(
 0409          'topic_id_list'    => $topic_ids,
 0410          'f'                => $forum_id,
 0411          'action'        => $action,
 0412          'redirect'        => $redirect,
 0413      );
 0414   
 0415      if (confirm_box(true))
 0416      {
 0417          $sql = 'UPDATE ' . TOPICS_TABLE . "
 0418              SET topic_type = $new_topic_type
 0419              WHERE " . $db->sql_in_set('topic_id', $topic_ids);
 0420          $db->sql_query($sql);
 0421   
 0422          if (($new_topic_type == POST_GLOBAL) && sizeof($topic_ids))
 0423          {
 0424              // Delete topic shadows for global announcements
 0425              $sql = 'DELETE FROM ' . TOPICS_TABLE . '
 0426                  WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids);
 0427              $db->sql_query($sql);
 0428   
 0429              $sql = 'UPDATE ' . TOPICS_TABLE . "
 0430                  SET topic_type = $new_topic_type
 0431                      WHERE " . $db->sql_in_set('topic_id', $topic_ids);
 0432              $db->sql_query($sql);
 0433          }
 0434   
 0435          $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_TYPE_CHANGED' : 'TOPICS_TYPE_CHANGED';
 0436   
 0437          if (sizeof($topic_ids))
 0438          {
 0439              $data = phpbb_get_topic_data($topic_ids);
 0440   
 0441              foreach ($data as $topic_id => $row)
 0442              {
 0443                  $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_TOPIC_TYPE_CHANGED', false, array(
 0444                      'forum_id' => $forum_id,
 0445                      'topic_id' => $topic_id,
 0446                      $row['topic_title']
 0447                  ));
 0448              }
 0449          }
 0450   
 0451          meta_refresh(2, $redirect);
 0452          $message = $user->lang[$success_msg];
 0453   
 0454          if (!$request->is_ajax())
 0455          {
 0456              $message .= '<br /><br />' . $user->lang('RETURN_PAGE', '<a href="' . $redirect . '">', '</a>');
 0457          }
 0458          trigger_error($message);
 0459      }
 0460      else
 0461      {
 0462          confirm_box(false, $l_new_type, build_hidden_fields($s_hidden_fields));
 0463      }
 0464   
 0465      redirect($redirect);
 0466  }
 0467   
 0468  /**
 0469  * Move Topic
 0470  */
 0471  function mcp_move_topic($topic_ids)
 0472  {
 0473      global $auth, $user, $db, $template, $phpbb_log, $request, $phpbb_dispatcher;
 0474      global $phpEx, $phpbb_root_path;
 0475   
 0476      // Here we limit the operation to one forum only
 0477      $forum_id = phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_move'), true);
 0478   
 0479      if ($forum_id === false)
 0480      {
 0481          return;
 0482      }
 0483   
 0484      $to_forum_id = $request->variable('to_forum_id', 0);
 0485      $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
 0486      $additional_msg = $success_msg = '';
 0487   
 0488      $s_hidden_fields = build_hidden_fields(array(
 0489          'topic_id_list'    => $topic_ids,
 0490          'f'                => $forum_id,
 0491          'action'        => 'move',
 0492          'redirect'        => $redirect)
 0493      );
 0494   
 0495      if ($to_forum_id)
 0496      {
 0497          $forum_data = phpbb_get_forum_data($to_forum_id, 'f_post');
 0498   
 0499          if (!sizeof($forum_data))
 0500          {
 0501              $additional_msg = $user->lang['FORUM_NOT_EXIST'];
 0502          }
 0503          else
 0504          {
 0505              $forum_data = $forum_data[$to_forum_id];
 0506   
 0507              if ($forum_data['forum_type'] != FORUM_POST)
 0508              {
 0509                  $additional_msg = $user->lang['FORUM_NOT_POSTABLE'];
 0510              }
 0511              else if (!$auth->acl_get('f_post', $to_forum_id) || (!$auth->acl_get('m_approve', $to_forum_id) && !$auth->acl_get('f_noapprove', $to_forum_id)))
 0512              {
 0513                  $additional_msg = $user->lang['USER_CANNOT_POST'];
 0514              }
 0515              else if ($forum_id == $to_forum_id)
 0516              {
 0517                  $additional_msg = $user->lang['CANNOT_MOVE_SAME_FORUM'];
 0518              }
 0519          }
 0520      }
 0521      else if (isset($_POST['confirm']))
 0522      {
 0523          $additional_msg = $user->lang['FORUM_NOT_EXIST'];
 0524      }
 0525   
 0526      if (!$to_forum_id || $additional_msg)
 0527      {
 0528          $request->overwrite('confirm', null, \phpbb\request\request_interface::POST);
 0529          $request->overwrite('confirm_key', null);
 0530      }
 0531   
 0532      if (confirm_box(true))
 0533      {
 0534          $topic_data = phpbb_get_topic_data($topic_ids);
 0535          $leave_shadow = (isset($_POST['move_leave_shadow'])) ? true : false;
 0536   
 0537          $forum_sync_data = array();
 0538   
 0539          $forum_sync_data[$forum_id] = current($topic_data);
 0540          $forum_sync_data[$to_forum_id] = $forum_data;
 0541   
 0542          $topics_moved = $topics_moved_unapproved = $topics_moved_softdeleted = 0;
 0543          $posts_moved = $posts_moved_unapproved = $posts_moved_softdeleted = 0;
 0544   
 0545          foreach ($topic_data as $topic_id => $topic_info)
 0546          {
 0547              if ($topic_info['topic_visibility'] == ITEM_APPROVED)
 0548              {
 0549                  $topics_moved++;
 0550              }
 0551              else if ($topic_info['topic_visibility'] == ITEM_UNAPPROVED || $topic_info['topic_visibility'] == ITEM_REAPPROVE)
 0552              {
 0553                  $topics_moved_unapproved++;
 0554              }
 0555              else if ($topic_info['topic_visibility'] == ITEM_DELETED)
 0556              {
 0557                  $topics_moved_softdeleted++;
 0558              }
 0559   
 0560              $posts_moved += $topic_info['topic_posts_approved'];
 0561              $posts_moved_unapproved += $topic_info['topic_posts_unapproved'];
 0562              $posts_moved_softdeleted += $topic_info['topic_posts_softdeleted'];
 0563          }
 0564   
 0565          $db->sql_transaction('begin');
 0566   
 0567          // Move topics, but do not resync yet
 0568          move_topics($topic_ids, $to_forum_id, false);
 0569   
 0570          if ($request->is_set_post('move_lock_topics') && $auth->acl_get('m_lock', $to_forum_id))
 0571          {
 0572              $sql = 'UPDATE ' . TOPICS_TABLE . '
 0573                  SET topic_status = ' . ITEM_LOCKED . '
 0574                  WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
 0575              $db->sql_query($sql);
 0576          }
 0577   
 0578          $shadow_topics = 0;
 0579          $forum_ids = array($to_forum_id);
 0580          foreach ($topic_data as $topic_id => $row)
 0581          {
 0582              // Get the list of forums to resync
 0583              $forum_ids[] = $row['forum_id'];
 0584   
 0585              // We add the $to_forum_id twice, because 'forum_id' is updated
 0586              // when the topic is moved again later.
 0587              $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MOVE', false, array(
 0588                  'forum_id'        => (int) $to_forum_id,
 0589                  'topic_id'        => (int) $topic_id,
 0590                  $row['forum_name'],
 0591                  $forum_data['forum_name'],
 0592                  (int) $row['forum_id'],
 0593                  (int) $forum_data['forum_id'],
 0594              ));
 0595   
 0596              // Leave a redirection if required and only if the topic is visible to users
 0597              if ($leave_shadow && $row['topic_visibility'] == ITEM_APPROVED && $row['topic_type'] != POST_GLOBAL)
 0598              {
 0599                  $shadow = array(
 0600                      'forum_id'                =>    (int) $row['forum_id'],
 0601                      'icon_id'                =>    (int) $row['icon_id'],
 0602                      'topic_attachment'        =>    (int) $row['topic_attachment'],
 0603                      'topic_visibility'        =>    ITEM_APPROVED, // a shadow topic is always approved
 0604                      'topic_reported'        =>    0, // a shadow topic is never reported
 0605                      'topic_title'            =>    (string) $row['topic_title'],
 0606                      'topic_poster'            =>    (int) $row['topic_poster'],
 0607                      'topic_time'            =>    (int) $row['topic_time'],
 0608                      'topic_time_limit'        =>    (int) $row['topic_time_limit'],
 0609                      'topic_views'            =>    (int) $row['topic_views'],
 0610                      'topic_posts_approved'    =>    (int) $row['topic_posts_approved'],
 0611                      'topic_posts_unapproved'=>    (int) $row['topic_posts_unapproved'],
 0612                      'topic_posts_softdeleted'=>    (int) $row['topic_posts_softdeleted'],
 0613                      'topic_status'            =>    ITEM_MOVED,
 0614                      'topic_type'            =>    POST_NORMAL,
 0615                      'topic_first_post_id'    =>    (int) $row['topic_first_post_id'],
 0616                      'topic_first_poster_colour'=>(string) $row['topic_first_poster_colour'],
 0617                      'topic_first_poster_name'=>    (string) $row['topic_first_poster_name'],
 0618                      'topic_last_post_id'    =>    (int) $row['topic_last_post_id'],
 0619                      'topic_last_poster_id'    =>    (int) $row['topic_last_poster_id'],
 0620                      'topic_last_poster_colour'=>(string) $row['topic_last_poster_colour'],
 0621                      'topic_last_poster_name'=>    (string) $row['topic_last_poster_name'],
 0622                      'topic_last_post_subject'=>    (string) $row['topic_last_post_subject'],
 0623                      'topic_last_post_time'    =>    (int) $row['topic_last_post_time'],
 0624                      'topic_last_view_time'    =>    (int) $row['topic_last_view_time'],
 0625                      'topic_moved_id'        =>    (int) $row['topic_id'],
 0626                      'topic_bumped'            =>    (int) $row['topic_bumped'],
 0627                      'topic_bumper'            =>    (int) $row['topic_bumper'],
 0628                      'poll_title'            =>    (string) $row['poll_title'],
 0629                      'poll_start'            =>    (int) $row['poll_start'],
 0630                      'poll_length'            =>    (int) $row['poll_length'],
 0631                      'poll_max_options'        =>    (int) $row['poll_max_options'],
 0632                      'poll_last_vote'        =>    (int) $row['poll_last_vote']
 0633                  );
 0634   
 0635                  /**
 0636                  * Perform actions before shadow topic is created.
 0637                  *
 0638                  * @event core.mcp_main_modify_shadow_sql
 0639                  * @var    array    shadow    SQL array to be used by $db->sql_build_array
 0640                  * @since 3.1.11-RC1
 0641                  */
 0642                  $vars = array(
 0643                      'shadow',
 0644                  );
 0645                  extract($phpbb_dispatcher->trigger_event('core.mcp_main_modify_shadow_sql', compact($vars)));
 0646   
 0647                  $db->sql_query('INSERT INTO ' . TOPICS_TABLE . $db->sql_build_array('INSERT', $shadow));
 0648   
 0649                  // Shadow topics only count on new "topics" and not posts... a shadow topic alone has 0 posts
 0650                  $shadow_topics++;
 0651              }
 0652          }
 0653          unset($topic_data);
 0654   
 0655          $sync_sql = array();
 0656          if ($posts_moved)
 0657          {
 0658              $sync_sql[$to_forum_id][] = 'forum_posts_approved = forum_posts_approved + ' . (int) $posts_moved;
 0659              $sync_sql[$forum_id][] = 'forum_posts_approved = forum_posts_approved - ' . (int) $posts_moved;
 0660          }
 0661          if ($posts_moved_unapproved)
 0662          {
 0663              $sync_sql[$to_forum_id][] = 'forum_posts_unapproved = forum_posts_unapproved + ' . (int) $posts_moved_unapproved;
 0664              $sync_sql[$forum_id][] = 'forum_posts_unapproved = forum_posts_unapproved - ' . (int) $posts_moved_unapproved;
 0665          }
 0666          if ($posts_moved_softdeleted)
 0667          {
 0668              $sync_sql[$to_forum_id][] = 'forum_posts_softdeleted = forum_posts_softdeleted + ' . (int) $posts_moved_softdeleted;
 0669              $sync_sql[$forum_id][] = 'forum_posts_softdeleted = forum_posts_softdeleted - ' . (int) $posts_moved_softdeleted;
 0670          }
 0671   
 0672          if ($topics_moved)
 0673          {
 0674              $sync_sql[$to_forum_id][] = 'forum_topics_approved = forum_topics_approved + ' . (int) $topics_moved;
 0675              if ($topics_moved - $shadow_topics > 0)
 0676              {
 0677                  $sync_sql[$forum_id][] = 'forum_topics_approved = forum_topics_approved - ' . (int) ($topics_moved - $shadow_topics);
 0678              }
 0679          }
 0680          if ($topics_moved_unapproved)
 0681          {
 0682              $sync_sql[$to_forum_id][] = 'forum_topics_unapproved = forum_topics_unapproved + ' . (int) $topics_moved_unapproved;
 0683              $sync_sql[$forum_id][] = 'forum_topics_unapproved = forum_topics_unapproved - ' . (int) $topics_moved_unapproved;
 0684          }
 0685          if ($topics_moved_softdeleted)
 0686          {
 0687              $sync_sql[$to_forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted + ' . (int) $topics_moved_softdeleted;
 0688              $sync_sql[$forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted - ' . (int) $topics_moved_softdeleted;
 0689          }
 0690   
 0691          $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_MOVED_SUCCESS' : 'TOPICS_MOVED_SUCCESS';
 0692   
 0693          foreach ($sync_sql as $forum_id_key => $array)
 0694          {
 0695              $sql = 'UPDATE ' . FORUMS_TABLE . '
 0696                  SET ' . implode(', ', $array) . '
 0697                  WHERE forum_id = ' . $forum_id_key;
 0698              $db->sql_query($sql);
 0699          }
 0700   
 0701          $db->sql_transaction('commit');
 0702   
 0703          sync('forum', 'forum_id', array($forum_id, $to_forum_id));
 0704      }
 0705      else
 0706      {
 0707          $template->assign_vars(array(
 0708              'S_FORUM_SELECT'        => make_forum_select($to_forum_id, $forum_id, false, true, true, true),
 0709              'S_CAN_LEAVE_SHADOW'    => true,
 0710              'S_CAN_LOCK_TOPIC'        => ($auth->acl_get('m_lock', $to_forum_id)) ? true : false,
 0711              'ADDITIONAL_MSG'        => $additional_msg)
 0712          );
 0713   
 0714          confirm_box(false, 'MOVE_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html');
 0715      }
 0716   
 0717      $redirect = $request->variable('redirect', "index.$phpEx");
 0718      $redirect = reapply_sid($redirect);
 0719   
 0720      if (!$success_msg)
 0721      {
 0722          redirect($redirect);
 0723      }
 0724      else
 0725      {
 0726          meta_refresh(3, $redirect);
 0727   
 0728          $message = $user->lang[$success_msg];
 0729          $message .= '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>');
 0730          $message .= '<br /><br />' . sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id") . '">', '</a>');
 0731          $message .= '<br /><br />' . sprintf($user->lang['RETURN_NEW_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$to_forum_id") . '">', '</a>');
 0732   
 0733          trigger_error($message);
 0734      }
 0735  }
 0736   
 0737  /**
 0738  * Restore Topics
 0739  */
 0740  function mcp_restore_topic($topic_ids)
 0741  {
 0742      global $user, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log;
 0743   
 0744      if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_approve')))
 0745      {
 0746          return;
 0747      }
 0748   
 0749      $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
 0750      $forum_id = $request->variable('f', 0);
 0751   
 0752      $s_hidden_fields = build_hidden_fields(array(
 0753          'topic_id_list'    => $topic_ids,
 0754          'f'                => $forum_id,
 0755          'action'        => 'restore_topic',
 0756          'redirect'        => $redirect,
 0757      ));
 0758      $success_msg = '';
 0759   
 0760      if (confirm_box(true))
 0761      {
 0762          $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_RESTORED_SUCCESS' : 'TOPICS_RESTORED_SUCCESS';
 0763   
 0764          $data = phpbb_get_topic_data($topic_ids);
 0765   
 0766          /* @var $phpbb_content_visibility \phpbb\content_visibility */
 0767          $phpbb_content_visibility = $phpbb_container->get('content.visibility');
 0768          foreach ($data as $topic_id => $row)
 0769          {
 0770              $return = $phpbb_content_visibility->set_topic_visibility(ITEM_APPROVED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), '');
 0771              if (!empty($return))
 0772              {
 0773                  $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_RESTORE_TOPIC', false, array(
 0774                      'forum_id' => $row['forum_id'],
 0775                      'topic_id' => $topic_id,
 0776                      $row['topic_title'],
 0777                      $row['topic_first_poster_name']
 0778                  ));
 0779              }
 0780          }
 0781      }
 0782      else
 0783      {
 0784          confirm_box(false, (sizeof($topic_ids) == 1) ? 'RESTORE_TOPIC' : 'RESTORE_TOPICS', $s_hidden_fields);
 0785      }
 0786   
 0787      $topic_id = $request->variable('t', 0);
 0788      if (!$request->is_set('quickmod', \phpbb\request\request_interface::REQUEST))
 0789      {
 0790          $redirect = $request->variable('redirect', "index.$phpEx");
 0791          $redirect = reapply_sid($redirect);
 0792          $redirect_message = 'PAGE';
 0793      }
 0794      else if ($topic_id)
 0795      {
 0796          $redirect = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id);
 0797          $redirect_message = 'TOPIC';
 0798      }
 0799      else
 0800      {
 0801          $redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
 0802          $redirect_message = 'FORUM';
 0803      }
 0804   
 0805      if (!$success_msg)
 0806      {
 0807          redirect($redirect);
 0808      }
 0809      else
 0810      {
 0811          meta_refresh(3, $redirect);
 0812          trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_' . $redirect_message], '<a href="' . $redirect . '">', '</a>'));
 0813      }
 0814  }
 0815   
 0816  /**
 0817  * Delete Topics
 0818  */
 0819  function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_topic')
 0820  {
 0821      global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log;
 0822   
 0823      $check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete';
 0824      if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array($check_permission)))
 0825      {
 0826          return;
 0827      }
 0828   
 0829      $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
 0830      $forum_id = $request->variable('f', 0);
 0831   
 0832      $s_hidden_fields = array(
 0833          'topic_id_list'    => $topic_ids,
 0834          'f'                => $forum_id,
 0835          'action'        => $action,
 0836          'redirect'        => $redirect,
 0837      );
 0838      $success_msg = '';
 0839   
 0840      if (confirm_box(true))
 0841      {
 0842          $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_DELETED_SUCCESS' : 'TOPICS_DELETED_SUCCESS';
 0843   
 0844          $data = phpbb_get_topic_data($topic_ids);
 0845   
 0846          foreach ($data as $topic_id => $row)
 0847          {
 0848              if ($row['topic_moved_id'])
 0849              {
 0850                  $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_SHADOW_TOPIC', false, array(
 0851                      'forum_id' => $row['forum_id'],
 0852                      'topic_id' => $topic_id,
 0853                      $row['topic_title']
 0854                  ));
 0855              }
 0856              else
 0857              {
 0858                  // Only soft delete non-shadow topics
 0859                  if ($is_soft)
 0860                  {
 0861                      /* @var $phpbb_content_visibility \phpbb\content_visibility */
 0862                      $phpbb_content_visibility = $phpbb_container->get('content.visibility');
 0863                      $return = $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), $soft_delete_reason);
 0864                      if (!empty($return))
 0865                      {
 0866                          $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SOFTDELETE_TOPIC', false, array(
 0867                              'forum_id' => $row['forum_id'],
 0868                              'topic_id' => $topic_id,
 0869                              $row['topic_title'],
 0870                              $row['topic_first_poster_name'],
 0871                              $soft_delete_reason
 0872                          ));
 0873                      }
 0874                  }
 0875                  else
 0876                  {
 0877                      $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_TOPIC', false, array(
 0878                          'forum_id' => $row['forum_id'],
 0879                          'topic_id' => $topic_id,
 0880                          $row['topic_title'],
 0881                          $row['topic_first_poster_name'],
 0882                          $soft_delete_reason
 0883                      ));
 0884                  }
 0885              }
 0886          }
 0887   
 0888          if (!$is_soft)
 0889          {
 0890              delete_topics('topic_id', $topic_ids);
 0891          }
 0892      }
 0893      else
 0894      {
 0895          global $template;
 0896   
 0897          $user->add_lang('posting');
 0898   
 0899          // If there are only shadow topics, we neither need a reason nor softdelete
 0900          $sql = 'SELECT topic_id
 0901              FROM ' . TOPICS_TABLE . '
 0902              WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
 0903                  AND topic_moved_id = 0';
 0904          $result = $db->sql_query_limit($sql, 1);
 0905          $only_shadow = !$db->sql_fetchfield('topic_id');
 0906          $db->sql_freeresult($result);
 0907   
 0908          $only_softdeleted = false;
 0909          if (!$only_shadow && $auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id))
 0910          {
 0911              // If there are only soft deleted topics, we display a message why the option is not available
 0912              $sql = 'SELECT topic_id
 0913                  FROM ' . TOPICS_TABLE . '
 0914                  WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
 0915                      AND topic_visibility <> ' . ITEM_DELETED;
 0916              $result = $db->sql_query_limit($sql, 1);
 0917              $only_softdeleted = !$db->sql_fetchfield('topic_id');
 0918              $db->sql_freeresult($result);
 0919          }
 0920   
 0921          $template->assign_vars(array(
 0922              'S_SHADOW_TOPICS'                    => $only_shadow,
 0923              'S_SOFTDELETED'                        => $only_softdeleted,
 0924              'S_TOPIC_MODE'                        => true,
 0925              'S_ALLOWED_DELETE'                    => $auth->acl_get('m_delete', $forum_id),
 0926              'S_ALLOWED_SOFTDELETE'                => $auth->acl_get('m_softdelete', $forum_id),
 0927              'DELETE_TOPIC_PERMANENTLY_EXPLAIN'    => $user->lang('DELETE_TOPIC_PERMANENTLY', sizeof($topic_ids)),
 0928          ));
 0929   
 0930          $l_confirm = (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS';
 0931          if ($only_softdeleted)
 0932          {
 0933              $l_confirm .= '_PERMANENTLY';
 0934              $s_hidden_fields['delete_permanent'] = '1';
 0935          }
 0936          else if ($only_shadow || !$auth->acl_get('m_softdelete', $forum_id))
 0937          {
 0938              $s_hidden_fields['delete_permanent'] = '1';
 0939          }
 0940   
 0941          confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');
 0942      }
 0943   
 0944      $topic_id = $request->variable('t', 0);
 0945      if (!$request->is_set('quickmod', \phpbb\request\request_interface::REQUEST))
 0946      {
 0947          $redirect = $request->variable('redirect', "index.$phpEx");
 0948          $redirect = reapply_sid($redirect);
 0949          $redirect_message = 'PAGE';
 0950      }
 0951      else if ($is_soft && $topic_id)
 0952      {
 0953          $redirect = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id);
 0954          $redirect_message = 'TOPIC';
 0955      }
 0956      else
 0957      {
 0958          $redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
 0959          $redirect_message = 'FORUM';
 0960      }
 0961   
 0962      if (!$success_msg)
 0963      {
 0964          redirect($redirect);
 0965      }
 0966      else
 0967      {
 0968          meta_refresh(3, $redirect);
 0969          trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_' . $redirect_message], '<a href="' . $redirect . '">', '</a>'));
 0970      }
 0971  }
 0972   
 0973  /**
 0974  * Delete Posts
 0975  */
 0976  function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_post')
 0977  {
 0978      global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log;
 0979   
 0980      $check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete';
 0981      if (!phpbb_check_ids($post_ids, POSTS_TABLE, 'post_id', array($check_permission)))
 0982      {
 0983          return;
 0984      }
 0985   
 0986      $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
 0987      $forum_id = $request->variable('f', 0);
 0988   
 0989      $s_hidden_fields = array(
 0990          'post_id_list'    => $post_ids,
 0991          'f'                => $forum_id,
 0992          'action'        => $action,
 0993          'redirect'        => $redirect,
 0994      );
 0995      $success_msg = '';
 0996   
 0997      if (confirm_box(true) && $is_soft)
 0998      {
 0999          $post_info = phpbb_get_post_data($post_ids);
 1000   
 1001          $topic_info = $approve_log = array();
 1002   
 1003          // Group the posts by topic_id
 1004          foreach ($post_info as $post_id => $post_data)
 1005          {
 1006              if ($post_data['post_visibility'] != ITEM_APPROVED)
 1007              {
 1008                  continue;
 1009              }
 1010              $topic_id = (int) $post_data['topic_id'];
 1011   
 1012              $topic_info[$topic_id]['posts'][] = (int) $post_id;
 1013              $topic_info[$topic_id]['forum_id'] = (int) $post_data['forum_id'];
 1014   
 1015              if ($post_id == $post_data['topic_first_post_id'])
 1016              {
 1017                  $topic_info[$topic_id]['first_post'] = true;
 1018              }
 1019   
 1020              if ($post_id == $post_data['topic_last_post_id'])
 1021              {
 1022                  $topic_info[$topic_id]['last_post'] = true;
 1023              }
 1024   
 1025              $approve_log[] = array(
 1026                  'forum_id'        => $post_data['forum_id'],
 1027                  'topic_id'        => $post_data['topic_id'],
 1028                  'post_id'        => $post_id,
 1029                  'post_subject'    => $post_data['post_subject'],
 1030                  'poster_id'        => $post_data['poster_id'],
 1031                  'post_username'    => $post_data['post_username'],
 1032                  'username'        => $post_data['username'],
 1033              );
 1034          }
 1035   
 1036          /* @var $phpbb_content_visibility \phpbb\content_visibility */
 1037          $phpbb_content_visibility = $phpbb_container->get('content.visibility');
 1038          foreach ($topic_info as $topic_id => $topic_data)
 1039          {
 1040              $phpbb_content_visibility->set_post_visibility(ITEM_DELETED, $topic_data['posts'], $topic_id, $topic_data['forum_id'], $user->data['user_id'], time(), $soft_delete_reason, isset($topic_data['first_post']), isset($topic_data['last_post']));
 1041          }
 1042          $affected_topics = sizeof($topic_info);
 1043          // None of the topics is really deleted, so a redirect won't hurt much.
 1044          $deleted_topics = 0;
 1045   
 1046          $success_msg = (sizeof($post_info) == 1) ? $user->lang['POST_DELETED_SUCCESS'] : $user->lang['POSTS_DELETED_SUCCESS'];
 1047   
 1048          foreach ($approve_log as $row)
 1049          {
 1050              $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username'];
 1051              $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SOFTDELETE_POST', false, array(
 1052                  'forum_id' => $row['forum_id'],
 1053                  'topic_id' => $row['topic_id'],
 1054                  'post_id'  => $row['post_id'],
 1055                  $row['post_subject'],
 1056                  $post_username,
 1057                  $soft_delete_reason
 1058              ));
 1059          }
 1060   
 1061          $topic_id = $request->variable('t', 0);
 1062   
 1063          // Return links
 1064          $return_link = array();
 1065          if ($affected_topics == 1 && $topic_id)
 1066          {
 1067              $return_link[] = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id") . '">', '</a>');
 1068          }
 1069          $return_link[] = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>');
 1070   
 1071      }
 1072      else if (confirm_box(true))
 1073      {
 1074          if (!function_exists('delete_posts'))
 1075          {
 1076              include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
 1077          }
 1078   
 1079          // Count the number of topics that are affected
 1080          // I did not use COUNT(DISTINCT ...) because I remember having problems
 1081          // with it on older versions of MySQL -- Ashe
 1082   
 1083          $sql = 'SELECT DISTINCT topic_id
 1084              FROM ' . POSTS_TABLE . '
 1085              WHERE ' . $db->sql_in_set('post_id', $post_ids);
 1086          $result = $db->sql_query($sql);
 1087   
 1088          $topic_id_list = array();
 1089          while ($row = $db->sql_fetchrow($result))
 1090          {
 1091              $topic_id_list[] = $row['topic_id'];
 1092          }
 1093          $affected_topics = sizeof($topic_id_list);
 1094          $db->sql_freeresult($result);
 1095   
 1096          $post_data = phpbb_get_post_data($post_ids);
 1097   
 1098          foreach ($post_data as $id => $row)
 1099          {
 1100              $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username'];
 1101              $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_POST', false, array(
 1102                  'forum_id' => $row['forum_id'],
 1103                  'topic_id' => $row['topic_id'],
 1104                  'post_id'  => $row['post_id'],
 1105                  $row['post_subject'],
 1106                  $post_username,
 1107                  $soft_delete_reason
 1108              ));
 1109          }
 1110   
 1111          // Now delete the posts, topics and forums are automatically resync'ed
 1112          delete_posts('post_id', $post_ids);
 1113   
 1114          $sql = 'SELECT COUNT(topic_id) AS topics_left
 1115              FROM ' . TOPICS_TABLE . '
 1116              WHERE ' . $db->sql_in_set('topic_id', $topic_id_list);
 1117          $result = $db->sql_query_limit($sql, 1);
 1118   
 1119          $deleted_topics = ($row = $db->sql_fetchrow($result)) ? ($affected_topics - $row['topics_left']) : $affected_topics;
 1120          $db->sql_freeresult($result);
 1121   
 1122          $topic_id = $request->variable('t', 0);
 1123   
 1124          // Return links
 1125          $return_link = array();
 1126          if ($affected_topics == 1 && !$deleted_topics && $topic_id)
 1127          {
 1128              $return_link[] = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id") . '">', '</a>');
 1129          }
 1130          $return_link[] = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>');
 1131   
 1132          if (sizeof($post_ids) == 1)
 1133          {
 1134              if ($deleted_topics)
 1135              {
 1136                  // We deleted the only post of a topic, which in turn has
 1137                  // been removed from the database
 1138                  $success_msg = $user->lang['TOPIC_DELETED_SUCCESS'];
 1139              }
 1140              else
 1141              {
 1142                  $success_msg = $user->lang['POST_DELETED_SUCCESS'];
 1143              }
 1144          }
 1145          else
 1146          {
 1147              if ($deleted_topics)
 1148              {
 1149                  // Some of topics disappeared
 1150                  $success_msg = $user->lang['POSTS_DELETED_SUCCESS'] . '<br /><br />' . $user->lang['EMPTY_TOPICS_REMOVED_WARNING'];
 1151              }
 1152              else
 1153              {
 1154                  $success_msg = $user->lang['POSTS_DELETED_SUCCESS'];
 1155              }
 1156          }
 1157      }
 1158      else
 1159      {
 1160          global $template;
 1161   
 1162          $user->add_lang('posting');
 1163   
 1164          $only_softdeleted = false;
 1165          if ($auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id))
 1166          {
 1167              // If there are only soft deleted posts, we display a message why the option is not available
 1168              $sql = 'SELECT post_id
 1169                  FROM ' . POSTS_TABLE . '
 1170                  WHERE ' . $db->sql_in_set('post_id', $post_ids) . '
 1171                      AND post_visibility <> ' . ITEM_DELETED;
 1172              $result = $db->sql_query_limit($sql, 1);
 1173              $only_softdeleted = !$db->sql_fetchfield('post_id');
 1174              $db->sql_freeresult($result);
 1175          }
 1176   
 1177          $template->assign_vars(array(
 1178              'S_SOFTDELETED'                        => $only_softdeleted,
 1179              'S_ALLOWED_DELETE'                    => $auth->acl_get('m_delete', $forum_id),
 1180              'S_ALLOWED_SOFTDELETE'                => $auth->acl_get('m_softdelete', $forum_id),
 1181              'DELETE_POST_PERMANENTLY_EXPLAIN'    => $user->lang('DELETE_POST_PERMANENTLY', sizeof($post_ids)),
 1182          ));
 1183   
 1184          $l_confirm = (sizeof($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS';
 1185          if ($only_softdeleted)
 1186          {
 1187              $l_confirm .= '_PERMANENTLY';
 1188              $s_hidden_fields['delete_permanent'] = '1';
 1189          }
 1190          else if (!$auth->acl_get('m_softdelete', $forum_id))
 1191          {
 1192              $s_hidden_fields['delete_permanent'] = '1';
 1193          }
 1194   
 1195          confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');
 1196      }
 1197   
 1198      $redirect = $request->variable('redirect', "index.$phpEx");
 1199      $redirect = reapply_sid($redirect);
 1200   
 1201      if (!$success_msg)
 1202      {
 1203          redirect($redirect);
 1204      }
 1205      else
 1206      {
 1207          if ($affected_topics != 1 || $deleted_topics || !$topic_id)
 1208          {
 1209              $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "f=$forum_id&i=main&mode=forum_view", false);
 1210          }
 1211   
 1212          meta_refresh(3, $redirect);
 1213          trigger_error($success_msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>') . '<br /><br />' . implode('<br /><br />', $return_link));
 1214      }
 1215  }
 1216   
 1217  /**
 1218  * Fork Topic
 1219  */
 1220  function mcp_fork_topic($topic_ids)
 1221  {
 1222      global $auth, $user, $db, $template, $config;
 1223      global $phpEx, $phpbb_root_path, $phpbb_log, $request, $phpbb_dispatcher;
 1224   
 1225      if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_')))
 1226      {
 1227          return;
 1228      }
 1229   
 1230      $to_forum_id = $request->variable('to_forum_id', 0);
 1231      $forum_id = $request->variable('f', 0);
 1232      $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
 1233      $additional_msg = $success_msg = '';
 1234      $counter = array();
 1235   
 1236      $s_hidden_fields = build_hidden_fields(array(
 1237          'topic_id_list'    => $topic_ids,
 1238          'f'                => $forum_id,
 1239          'action'        => 'fork',
 1240          'redirect'        => $redirect)
 1241      );
 1242   
 1243      if ($to_forum_id)
 1244      {
 1245          $forum_data = phpbb_get_forum_data($to_forum_id, 'f_post');
 1246   
 1247          if (!sizeof($topic_ids))
 1248          {
 1249              $additional_msg = $user->lang['NO_TOPIC_SELECTED'];
 1250          }
 1251          else if (!sizeof($forum_data))
 1252          {
 1253              $additional_msg = $user->lang['FORUM_NOT_EXIST'];
 1254          }
 1255          else
 1256          {
 1257              $forum_data = $forum_data[$to_forum_id];
 1258   
 1259              if ($forum_data['forum_type'] != FORUM_POST)
 1260              {
 1261                  $additional_msg = $user->lang['FORUM_NOT_POSTABLE'];
 1262              }
 1263              else if (!$auth->acl_get('f_post', $to_forum_id))
 1264              {
 1265                  $additional_msg = $user->lang['USER_CANNOT_POST'];
 1266              }
 1267          }
 1268      }
 1269      else if (isset($_POST['confirm']))
 1270      {
 1271          $additional_msg = $user->lang['FORUM_NOT_EXIST'];
 1272      }
 1273   
 1274      if ($additional_msg)
 1275      {
 1276          $request->overwrite('confirm', null, \phpbb\request\request_interface::POST);
 1277          $request->overwrite('confirm_key', null);
 1278      }
 1279   
 1280      if (confirm_box(true))
 1281      {
 1282          $topic_data = phpbb_get_topic_data($topic_ids, 'f_post');
 1283   
 1284          $total_topics = $total_topics_unapproved = $total_topics_softdeleted = 0;
 1285          $total_posts = $total_posts_unapproved = $total_posts_softdeleted = 0;
 1286          $new_topic_id_list = array();
 1287   
 1288          foreach ($topic_data as $topic_id => $topic_row)
 1289          {
 1290              if (!isset($search_type) && $topic_row['enable_indexing'])
 1291              {
 1292                  // Select the search method and do some additional checks to ensure it can actually be utilised
 1293                  $search_type = $config['search_type'];
 1294   
 1295                  if (!class_exists($search_type))
 1296                  {
 1297                      trigger_error('NO_SUCH_SEARCH_MODULE');
 1298                  }
 1299   
 1300                  $error = false;
 1301                  $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
 1302                  $search_mode = 'post';
 1303   
 1304                  if ($error)
 1305                  {
 1306                      trigger_error($error);
 1307                  }
 1308              }
 1309              else if (!isset($search_type) && !$topic_row['enable_indexing'])
 1310              {
 1311                  $search_type = false;
 1312              }
 1313   
 1314              $sql_ary = array(
 1315                  'forum_id'                    => (int) $to_forum_id,
 1316                  'icon_id'                    => (int) $topic_row['icon_id'],
 1317                  'topic_attachment'            => (int) $topic_row['topic_attachment'],
 1318                  'topic_visibility'            => (int) $topic_row['topic_visibility'],
 1319                  'topic_reported'            => 0,
 1320                  'topic_title'                => (string) $topic_row['topic_title'],
 1321                  'topic_poster'                => (int) $topic_row['topic_poster'],
 1322                  'topic_time'                => (int) $topic_row['topic_time'],
 1323                  'topic_posts_approved'        => (int) $topic_row['topic_posts_approved'],
 1324                  'topic_posts_unapproved'    => (int) $topic_row['topic_posts_unapproved'],
 1325                  'topic_posts_softdeleted'    => (int) $topic_row['topic_posts_softdeleted'],
 1326                  'topic_status'                => (int) $topic_row['topic_status'],
 1327                  'topic_type'                => (int) $topic_row['topic_type'],
 1328                  'topic_first_poster_name'    => (string) $topic_row['topic_first_poster_name'],
 1329                  'topic_last_poster_id'        => (int) $topic_row['topic_last_poster_id'],
 1330                  'topic_last_poster_name'    => (string) $topic_row['topic_last_poster_name'],
 1331                  'topic_last_post_time'        => (int) $topic_row['topic_last_post_time'],
 1332                  'topic_last_view_time'        => (int) $topic_row['topic_last_view_time'],
 1333                  'topic_bumped'                => (int) $topic_row['topic_bumped'],
 1334                  'topic_bumper'                => (int) $topic_row['topic_bumper'],
 1335                  'poll_title'                => (string) $topic_row['poll_title'],
 1336                  'poll_start'                => (int) $topic_row['poll_start'],
 1337                  'poll_length'                => (int) $topic_row['poll_length'],
 1338                  'poll_max_options'            => (int) $topic_row['poll_max_options'],
 1339                  'poll_vote_change'            => (int) $topic_row['poll_vote_change'],
 1340              );
 1341   
 1342              /**
 1343              * Perform actions before forked topic is created.
 1344              *
 1345              * @event core.mcp_main_modify_fork_sql
 1346              * @var    array    sql_ary    SQL array to be used by $db->sql_build_array
 1347              * @since 3.1.11-RC1
 1348              */
 1349              $vars = array(
 1350                  'sql_ary',
 1351              );
 1352              extract($phpbb_dispatcher->trigger_event('core.mcp_main_modify_fork_sql', compact($vars)));
 1353   
 1354              $db->sql_query('INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
 1355              $new_topic_id = $db->sql_nextid();
 1356              $new_topic_id_list[$topic_id] = $new_topic_id;
 1357   
 1358              switch ($topic_row['topic_visibility'])
 1359              {
 1360                  case ITEM_APPROVED:
 1361                      $total_topics++;
 1362                  break;
 1363                  case ITEM_UNAPPROVED:
 1364                  case ITEM_REAPPROVE:
 1365                      $total_topics_unapproved++;
 1366                  break;
 1367                  case ITEM_DELETED:
 1368                      $total_topics_softdeleted++;
 1369                  break;
 1370              }
 1371   
 1372              if ($topic_row['poll_start'])
 1373              {
 1374                  $sql = 'SELECT *
 1375                      FROM ' . POLL_OPTIONS_TABLE . "
 1376                      WHERE topic_id = $topic_id";
 1377                  $result = $db->sql_query($sql);
 1378   
 1379                  while ($row = $db->sql_fetchrow($result))
 1380                  {
 1381                      $sql_ary = array(
 1382                          'poll_option_id'    => (int) $row['poll_option_id'],
 1383                          'topic_id'            => (int) $new_topic_id,
 1384                          'poll_option_text'    => (string) $row['poll_option_text'],
 1385                          'poll_option_total'    => 0
 1386                      );
 1387   
 1388                      $db->sql_query('INSERT INTO ' . POLL_OPTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
 1389                  }
 1390                  $db->sql_freeresult($result);
 1391              }
 1392   
 1393              $sql = 'SELECT *
 1394                  FROM ' . POSTS_TABLE . "
 1395                  WHERE topic_id = $topic_id
 1396                  ORDER BY post_time ASC, post_id ASC";
 1397              $result = $db->sql_query($sql);
 1398   
 1399              $post_rows = array();
 1400              while ($row = $db->sql_fetchrow($result))
 1401              {
 1402                  $post_rows[] = $row;
 1403              }
 1404              $db->sql_freeresult($result);
 1405   
 1406              if (!sizeof($post_rows))
 1407              {
 1408                  continue;
 1409              }
 1410   
 1411              foreach ($post_rows as $row)
 1412              {
 1413                  $sql_ary = array(
 1414                      'topic_id'            => (int) $new_topic_id,
 1415                      'forum_id'            => (int) $to_forum_id,
 1416                      'poster_id'            => (int) $row['poster_id'],
 1417                      'icon_id'            => (int) $row['icon_id'],
 1418                      'poster_ip'            => (string) $row['poster_ip'],
 1419                      'post_time'            => (int) $row['post_time'],
 1420                      'post_visibility'    => (int) $row['post_visibility'],
 1421                      'post_reported'        => 0,
 1422                      'enable_bbcode'        => (int) $row['enable_bbcode'],
 1423                      'enable_smilies'    => (int) $row['enable_smilies'],
 1424                      'enable_magic_url'    => (int) $row['enable_magic_url'],
 1425                      'enable_sig'        => (int) $row['enable_sig'],
 1426                      'post_username'        => (string) $row['post_username'],
 1427                      'post_subject'        => (string) $row['post_subject'],
 1428                      'post_text'            => (string) $row['post_text'],
 1429                      'post_edit_reason'    => (string) $row['post_edit_reason'],
 1430                      'post_edit_user'    => (int) $row['post_edit_user'],
 1431                      'post_checksum'        => (string) $row['post_checksum'],
 1432                      'post_attachment'    => (int) $row['post_attachment'],
 1433                      'bbcode_bitfield'    => $row['bbcode_bitfield'],
 1434                      'bbcode_uid'        => (string) $row['bbcode_uid'],
 1435                      'post_edit_time'    => (int) $row['post_edit_time'],
 1436                      'post_edit_count'    => (int) $row['post_edit_count'],
 1437                      'post_edit_locked'    => (int) $row['post_edit_locked'],
 1438                      'post_postcount'    => $row['post_postcount'],
 1439                  );
 1440                  // Adjust post count only if the post can be incremented to the user counter
 1441                  if ($row['post_postcount'])
 1442                  {
 1443                      if (isset($counter[$row['poster_id']]))
 1444                      {
 1445                          ++$counter[$row['poster_id']];
 1446                      }
 1447                      else
 1448                      {
 1449                          $counter[$row['poster_id']] = 1;
 1450                      }
 1451                  }
 1452                  $db->sql_query('INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
 1453                  $new_post_id = $db->sql_nextid();
 1454   
 1455                  switch ($row['post_visibility'])
 1456                  {
 1457                      case ITEM_APPROVED:
 1458                          $total_posts++;
 1459                      break;
 1460                      case ITEM_UNAPPROVED:
 1461                      case ITEM_REAPPROVE:
 1462                          $total_posts_unapproved++;
 1463                      break;
 1464                      case ITEM_DELETED:
 1465                          $total_posts_softdeleted++;
 1466                      break;
 1467                  }
 1468   
 1469                  // Copy whether the topic is dotted
 1470                  markread('post', $to_forum_id, $new_topic_id, 0, $row['poster_id']);
 1471   
 1472                  if (!empty($search_type))
 1473                  {
 1474                      $search->index($search_mode, $new_post_id, $sql_ary['post_text'], $sql_ary['post_subject'], $sql_ary['poster_id'], ($topic_row['topic_type'] == POST_GLOBAL) ? 0 : $to_forum_id);
 1475                      $search_mode = 'reply'; // After one we index replies
 1476                  }
 1477   
 1478                  // Copy Attachments
 1479                  if ($row['post_attachment'])
 1480                  {
 1481                      $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . "
 1482                          WHERE post_msg_id = {$row['post_id']}
 1483                              AND topic_id = $topic_id
 1484                              AND in_message = 0";
 1485                      $result = $db->sql_query($sql);
 1486   
 1487                      $sql_ary = array();
 1488                      while ($attach_row = $db->sql_fetchrow($result))
 1489                      {
 1490                          $sql_ary[] = array(
 1491                              'post_msg_id'        => (int) $new_post_id,
 1492                              'topic_id'            => (int) $new_topic_id,
 1493                              'in_message'        => 0,
 1494                              'is_orphan'            => (int) $attach_row['is_orphan'],
 1495                              'poster_id'            => (int) $attach_row['poster_id'],
 1496                              'physical_filename'    => (string) utf8_basename($attach_row['physical_filename']),
 1497                              'real_filename'        => (string) utf8_basename($attach_row['real_filename']),
 1498                              'download_count'    => (int) $attach_row['download_count'],
 1499                              'attach_comment'    => (string) $attach_row['attach_comment'],
 1500                              'extension'            => (string) $attach_row['extension'],
 1501                              'mimetype'            => (string) $attach_row['mimetype'],
 1502                              'filesize'            => (int) $attach_row['filesize'],
 1503                              'filetime'            => (int) $attach_row['filetime'],
 1504                              'thumbnail'            => (int) $attach_row['thumbnail']
 1505                          );
 1506                      }
 1507                      $db->sql_freeresult($result);
 1508   
 1509                      if (sizeof($sql_ary))
 1510                      {
 1511                          $db->sql_multi_insert(ATTACHMENTS_TABLE, $sql_ary);
 1512                      }
 1513                  }
 1514              }
 1515   
 1516              // Copy topic subscriptions to new topic
 1517              $sql = 'SELECT user_id, notify_status
 1518                  FROM ' . TOPICS_WATCH_TABLE . '
 1519                  WHERE topic_id = ' . $topic_id;
 1520              $result = $db->sql_query($sql);
 1521   
 1522              $sql_ary = array();
 1523              while ($row = $db->sql_fetchrow($result))
 1524              {
 1525                  $sql_ary[] = array(
 1526                      'topic_id'        => (int) $new_topic_id,
 1527                      'user_id'        => (int) $row['user_id'],
 1528                      'notify_status'    => (int) $row['notify_status'],
 1529                  );
 1530              }
 1531              $db->sql_freeresult($result);
 1532   
 1533              if (sizeof($sql_ary))
 1534              {
 1535                  $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary);
 1536              }
 1537   
 1538              // Copy bookmarks to new topic
 1539              $sql = 'SELECT user_id
 1540                  FROM ' . BOOKMARKS_TABLE . '
 1541                  WHERE topic_id = ' . $topic_id;
 1542              $result = $db->sql_query($sql);
 1543   
 1544              $sql_ary = array();
 1545              while ($row = $db->sql_fetchrow($result))
 1546              {
 1547                  $sql_ary[] = array(
 1548                      'topic_id'        => (int) $new_topic_id,
 1549                      'user_id'        => (int) $row['user_id'],
 1550                  );
 1551              }
 1552              $db->sql_freeresult($result);
 1553   
 1554              if (sizeof($sql_ary))
 1555              {
 1556                  $db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary);
 1557              }
 1558          }
 1559   
 1560          // Sync new topics, parent forums and board stats
 1561          $sql = 'UPDATE ' . FORUMS_TABLE . '
 1562              SET forum_posts_approved = forum_posts_approved + ' . $total_posts . ',
 1563                  forum_posts_unapproved = forum_posts_unapproved + ' . $total_posts_unapproved . ',
 1564                  forum_posts_softdeleted = forum_posts_softdeleted + ' . $total_posts_softdeleted . ',
 1565                  forum_topics_approved = forum_topics_approved + ' . $total_topics . ',
 1566                  forum_topics_unapproved = forum_topics_unapproved + ' . $total_topics_unapproved . ',
 1567                  forum_topics_softdeleted = forum_topics_softdeleted + ' . $total_topics_softdeleted . '
 1568              WHERE forum_id = ' . $to_forum_id;
 1569          $db->sql_query($sql);
 1570   
 1571          if (!empty($counter))
 1572          {
 1573              // Do only one query per user and not a query per post.
 1574              foreach ($counter as $user_id => $count)
 1575              {
 1576                  $sql = 'UPDATE ' . USERS_TABLE . '
 1577                      SET user_posts = user_posts + ' . (int) $count . '
 1578                      WHERE user_id = ' . (int) $user_id;
 1579                  $db->sql_query($sql);
 1580              }
 1581          }
 1582   
 1583          sync('topic', 'topic_id', $new_topic_id_list);
 1584          sync('forum', 'forum_id', $to_forum_id);
 1585   
 1586          $config->increment('num_topics', sizeof($new_topic_id_list), false);
 1587          $config->increment('num_posts', $total_posts, false);
 1588   
 1589          foreach ($new_topic_id_list as $topic_id => $new_topic_id)
 1590          {
 1591              $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_FORK', false, array(
 1592                  'forum_id' => $to_forum_id,
 1593                  'topic_id' => $new_topic_id,
 1594                  $topic_row['forum_name']
 1595              ));
 1596          }
 1597   
 1598          $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS';
 1599      }
 1600      else
 1601      {
 1602          $template->assign_vars(array(
 1603              'S_FORUM_SELECT'        => make_forum_select($to_forum_id, false, false, true, true, true),
 1604              'S_CAN_LEAVE_SHADOW'    => false,
 1605              'ADDITIONAL_MSG'        => $additional_msg)
 1606          );
 1607   
 1608          confirm_box(false, 'FORK_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html');
 1609      }
 1610   
 1611      $redirect = $request->variable('redirect', "index.$phpEx");
 1612      $redirect = reapply_sid($redirect);
 1613   
 1614      if (!$success_msg)
 1615      {
 1616          redirect($redirect);
 1617      }
 1618      else
 1619      {
 1620          $redirect_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
 1621          meta_refresh(3, $redirect_url);
 1622          $return_link = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect_url . '">', '</a>');
 1623   
 1624          if ($forum_id != $to_forum_id)
 1625          {
 1626              $return_link .= '<br /><br />' . sprintf($user->lang['RETURN_NEW_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $to_forum_id) . '">', '</a>');
 1627          }
 1628   
 1629          trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link);
 1630      }
 1631  }
 1632