[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/includes/mcp/ -> mcp_main.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  /**
  15  * @ignore
  16  */
  17  if (!defined('IN_PHPBB'))
  18  {
  19      exit;
  20  }
  21  
  22  /**
  23  * mcp_main
  24  * Handling mcp actions
  25  */
  26  class mcp_main
  27  {
  28      var $p_master;
  29      var $u_action;
  30  
  31  	function mcp_main(&$p_master)
  32      {
  33          $this->p_master = &$p_master;
  34      }
  35  
  36  	function main($id, $mode)
  37      {
  38          global $auth, $db, $user, $template, $action;
  39          global $config, $phpbb_root_path, $phpEx, $request;
  40          global $phpbb_dispatcher;
  41  
  42          $quickmod = ($mode == 'quickmod') ? true : false;
  43  
  44          switch ($action)
  45          {
  46              case 'lock':
  47              case 'unlock':
  48                  $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));
  49  
  50                  if (!sizeof($topic_ids))
  51                  {
  52                      trigger_error('NO_TOPIC_SELECTED');
  53                  }
  54  
  55                  lock_unlock($action, $topic_ids);
  56              break;
  57  
  58              case 'lock_post':
  59              case 'unlock_post':
  60  
  61                  $post_ids = (!$quickmod) ? request_var('post_id_list', array(0)) : array(request_var('p', 0));
  62  
  63                  if (!sizeof($post_ids))
  64                  {
  65                      trigger_error('NO_POST_SELECTED');
  66                  }
  67  
  68                  lock_unlock($action, $post_ids);
  69              break;
  70  
  71              case 'make_announce':
  72              case 'make_sticky':
  73              case 'make_global':
  74              case 'make_normal':
  75  
  76                  $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));
  77  
  78                  if (!sizeof($topic_ids))
  79                  {
  80                      trigger_error('NO_TOPIC_SELECTED');
  81                  }
  82  
  83                  change_topic_type($action, $topic_ids);
  84              break;
  85  
  86              case 'move':
  87                  $user->add_lang('viewtopic');
  88  
  89                  $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));
  90  
  91                  if (!sizeof($topic_ids))
  92                  {
  93                      trigger_error('NO_TOPIC_SELECTED');
  94                  }
  95  
  96                  mcp_move_topic($topic_ids);
  97              break;
  98  
  99              case 'fork':
 100                  $user->add_lang('viewtopic');
 101  
 102                  $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0));
 103  
 104                  if (!sizeof($topic_ids))
 105                  {
 106                      trigger_error('NO_TOPIC_SELECTED');
 107                  }
 108  
 109                  mcp_fork_topic($topic_ids);
 110              break;
 111  
 112              case 'delete_topic':
 113                  $user->add_lang('viewtopic');
 114  
 115                  // f parameter is not reliable for permission usage, however we just use it to decide
 116                  // which permission we will check later on. So if it is manipulated, we will still catch it later on.
 117                  $forum_id = $request->variable('f', 0);
 118                  $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
 119                  $soft_delete = (($request->is_set_post('confirm') && !$request->is_set_post('delete_permanent')) || !$auth->acl_get('m_delete', $forum_id)) ? true : false;
 120  
 121                  if (!sizeof($topic_ids))
 122                  {
 123                      trigger_error('NO_TOPIC_SELECTED');
 124                  }
 125  
 126                  mcp_delete_topic($topic_ids, $soft_delete, $request->variable('delete_reason', '', true));
 127              break;
 128  
 129              case 'delete_post':
 130                  $user->add_lang('posting');
 131  
 132                  // f parameter is not reliable for permission usage, however we just use it to decide
 133                  // which permission we will check later on. So if it is manipulated, we will still catch it later on.
 134                  $forum_id = $request->variable('f', 0);
 135                  $post_ids = (!$quickmod) ? $request->variable('post_id_list', array(0)) : array($request->variable('p', 0));
 136                  $soft_delete = (($request->is_set_post('confirm') && !$request->is_set_post('delete_permanent')) || !$auth->acl_get('m_delete', $forum_id)) ? true : false;
 137  
 138                  if (!sizeof($post_ids))
 139                  {
 140                      trigger_error('NO_POST_SELECTED');
 141                  }
 142  
 143                  mcp_delete_post($post_ids, $soft_delete, $request->variable('delete_reason', '', true));
 144              break;
 145  
 146              case 'restore_topic':
 147                  $user->add_lang('posting');
 148  
 149                  $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0));
 150  
 151                  if (!sizeof($topic_ids))
 152                  {
 153                      trigger_error('NO_TOPIC_SELECTED');
 154                  }
 155  
 156                  mcp_restore_topic($topic_ids);
 157              break;
 158  
 159              default:
 160                  /**
 161                  * This event allows you to handle custom quickmod options
 162                  *
 163                  * @event core.modify_quickmod_actions
 164                  * @var    string    action        Topic quick moderation action name
 165                  * @var    bool    quickmod    Flag indicating whether MCP is in quick moderation mode
 166                  * @since 3.1.0-a4
 167                  * @changed 3.1.0-RC4 Added variables: action, quickmod
 168                  */
 169                  $vars = array('action', 'quickmod');
 170                  extract($phpbb_dispatcher->trigger_event('core.modify_quickmod_actions', compact($vars)));
 171              break;
 172          }
 173  
 174          switch ($mode)
 175          {
 176              case 'front':
 177                  include($phpbb_root_path . 'includes/mcp/mcp_front.' . $phpEx);
 178  
 179                  $user->add_lang('acp/common');
 180  
 181                  mcp_front_view($id, $mode, $action);
 182  
 183                  $this->tpl_name = 'mcp_front';
 184                  $this->page_title = 'MCP_MAIN';
 185              break;
 186  
 187              case 'forum_view':
 188                  include($phpbb_root_path . 'includes/mcp/mcp_forum.' . $phpEx);
 189  
 190                  $user->add_lang('viewforum');
 191  
 192                  $forum_id = request_var('f', 0);
 193  
 194                  $forum_info = phpbb_get_forum_data($forum_id, 'm_', true);
 195  
 196                  if (!sizeof($forum_info))
 197                  {
 198                      $this->main('main', 'front');
 199                      return;
 200                  }
 201  
 202                  $forum_info = $forum_info[$forum_id];
 203  
 204                  mcp_forum_view($id, $mode, $action, $forum_info);
 205  
 206                  $this->tpl_name = 'mcp_forum';
 207                  $this->page_title = 'MCP_MAIN_FORUM_VIEW';
 208              break;
 209  
 210              case 'topic_view':
 211                  include($phpbb_root_path . 'includes/mcp/mcp_topic.' . $phpEx);
 212  
 213                  mcp_topic_view($id, $mode, $action);
 214  
 215                  $this->tpl_name = 'mcp_topic';
 216                  $this->page_title = 'MCP_MAIN_TOPIC_VIEW';
 217              break;
 218  
 219              case 'post_details':
 220                  include($phpbb_root_path . 'includes/mcp/mcp_post.' . $phpEx);
 221  
 222                  mcp_post_details($id, $mode, $action);
 223  
 224                  $this->tpl_name = ($action == 'whois') ? 'mcp_whois' : 'mcp_post';
 225                  $this->page_title = 'MCP_MAIN_POST_DETAILS';
 226              break;
 227  
 228              default:
 229                  if ($quickmod)
 230                  {
 231                      switch ($action)
 232                      {
 233                          case 'lock':
 234                          case 'unlock':
 235                          case 'make_announce':
 236                          case 'make_sticky':
 237                          case 'make_global':
 238                          case 'make_normal':
 239                          case 'make_onindex':
 240                          case 'move':
 241                          case 'fork':
 242                          case 'delete_topic':
 243                              trigger_error('TOPIC_NOT_EXIST');
 244                          break;
 245  
 246                          case 'lock_post':
 247                          case 'unlock_post':
 248                          case 'delete_post':
 249                              trigger_error('POST_NOT_EXIST');
 250                          break;
 251                      }
 252                  }
 253  
 254                  trigger_error('NO_MODE', E_USER_ERROR);
 255              break;
 256          }
 257      }
 258  }
 259  
 260  /**
 261  * Lock/Unlock Topic/Post
 262  */
 263  function lock_unlock($action, $ids)
 264  {
 265      global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_dispatcher;
 266  
 267      if ($action == 'lock' || $action == 'unlock')
 268      {
 269          $table = TOPICS_TABLE;
 270          $sql_id = 'topic_id';
 271          $set_id = 'topic_status';
 272          $l_prefix = 'TOPIC';
 273      }
 274      else
 275      {
 276          $table = POSTS_TABLE;
 277          $sql_id = 'post_id';
 278          $set_id = 'post_edit_locked';
 279          $l_prefix = 'POST';
 280      }
 281  
 282      $orig_ids = $ids;
 283  
 284      if (!phpbb_check_ids($ids, $table, $sql_id, array('m_lock')))
 285      {
 286          // Make sure that for f_user_lock only the lock action is triggered.
 287          if ($action != 'lock')
 288          {
 289              return;
 290          }
 291  
 292          $ids = $orig_ids;
 293  
 294          if (!phpbb_check_ids($ids, $table, $sql_id, array('f_user_lock')))
 295          {
 296              return;
 297          }
 298      }
 299      unset($orig_ids);
 300  
 301      $redirect = request_var('redirect', build_url(array('action', 'quickmod')));
 302      $redirect = reapply_sid($redirect);
 303  
 304      $s_hidden_fields = build_hidden_fields(array(
 305          $sql_id . '_list'    => $ids,
 306          'action'            => $action,
 307          'redirect'            => $redirect)
 308      );
 309      $success_msg = '';
 310  
 311      if (confirm_box(true))
 312      {
 313          $sql = "UPDATE $table
 314              SET $set_id = " . (($action == 'lock' || $action == 'lock_post') ? ITEM_LOCKED : ITEM_UNLOCKED) . '
 315              WHERE ' . $db->sql_in_set($sql_id, $ids);
 316          $db->sql_query($sql);
 317  
 318          $data = ($action == 'lock' || $action == 'unlock') ? phpbb_get_topic_data($ids) : phpbb_get_post_data($ids);
 319  
 320          foreach ($data as $id => $row)
 321          {
 322              add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_' . strtoupper($action), $row['topic_title']);
 323          }
 324  
 325          /**
 326           * Perform additional actions after locking/unlocking posts/topics
 327           *
 328           * @event core.mcp_lock_unlock_after
 329           * @var    string    action                Variable containing the action we perform on the posts/topics ('lock', 'unlock', 'lock_post' or 'unlock_post')
 330           * @var    array    ids                    Array containing the post/topic IDs that have been locked/unlocked
 331           * @var    array    data                Array containing posts/topics data
 332           * @since 3.1.7-RC1
 333           */
 334          $vars = array(
 335              'action',
 336              'ids',
 337              'data',
 338          );
 339          extract($phpbb_dispatcher->trigger_event('core.mcp_lock_unlock_after', compact($vars)));
 340  
 341          $success_msg = $l_prefix . ((sizeof($ids) == 1) ? '' : 'S') . '_' . (($action == 'lock' || $action == 'lock_post') ? 'LOCKED' : 'UNLOCKED') . '_SUCCESS';
 342  
 343          meta_refresh(2, $redirect);
 344          $message = $user->lang[$success_msg];
 345  
 346          if (!$request->is_ajax())
 347          {
 348              $message .= '<br /><br />' . $user->lang('RETURN_PAGE', '<a href="' . $redirect . '">', '</a>');
 349          }
 350          trigger_error($message);
 351      }
 352      else
 353      {
 354          confirm_box(false, strtoupper($action) . '_' . $l_prefix . ((sizeof($ids) == 1) ? '' : 'S'), $s_hidden_fields);
 355      }
 356  
 357      redirect($redirect);
 358  }
 359  
 360  /**
 361  * Change Topic Type
 362  */
 363  function change_topic_type($action, $topic_ids)
 364  {
 365      global $auth, $user, $db, $phpEx, $phpbb_root_path, $request;
 366  
 367      switch ($action)
 368      {
 369          case 'make_announce':
 370              $new_topic_type = POST_ANNOUNCE;
 371              $check_acl = 'f_announce';
 372              $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_ANNOUNCEMENT' : 'MCP_MAKE_ANNOUNCEMENTS';
 373          break;
 374  
 375          case 'make_global':
 376              $new_topic_type = POST_GLOBAL;
 377              $check_acl = 'f_announce';
 378              $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_GLOBAL' : 'MCP_MAKE_GLOBALS';
 379          break;
 380  
 381          case 'make_sticky':
 382              $new_topic_type = POST_STICKY;
 383              $check_acl = 'f_sticky';
 384              $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_STICKY' : 'MCP_MAKE_STICKIES';
 385          break;
 386  
 387          default:
 388              $new_topic_type = POST_NORMAL;
 389              $check_acl = false;
 390              $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_NORMAL' : 'MCP_MAKE_NORMALS';
 391          break;
 392      }
 393  
 394      $forum_id = phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', $check_acl, true);
 395  
 396      if ($forum_id === false)
 397      {
 398          return;
 399      }
 400  
 401      $redirect = request_var('redirect', build_url(array('action', 'quickmod')));
 402      $redirect = reapply_sid($redirect);
 403  
 404      $s_hidden_fields = array(
 405          'topic_id_list'    => $topic_ids,
 406          'f'                => $forum_id,
 407          'action'        => $action,
 408          'redirect'        => $redirect,
 409      );
 410      $success_msg = '';
 411  
 412      if (confirm_box(true))
 413      {
 414          $sql = 'UPDATE ' . TOPICS_TABLE . "
 415              SET topic_type = $new_topic_type
 416              WHERE " . $db->sql_in_set('topic_id', $topic_ids);
 417          $db->sql_query($sql);
 418  
 419          if (($new_topic_type == POST_GLOBAL) && sizeof($topic_ids))
 420          {
 421              // Delete topic shadows for global announcements
 422              $sql = 'DELETE FROM ' . TOPICS_TABLE . '
 423                  WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids);
 424              $db->sql_query($sql);
 425  
 426              $sql = 'UPDATE ' . TOPICS_TABLE . "
 427                  SET topic_type = $new_topic_type
 428                      WHERE " . $db->sql_in_set('topic_id', $topic_ids);
 429              $db->sql_query($sql);
 430          }
 431  
 432          $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_TYPE_CHANGED' : 'TOPICS_TYPE_CHANGED';
 433  
 434          if (sizeof($topic_ids))
 435          {
 436              $data = phpbb_get_topic_data($topic_ids);
 437  
 438              foreach ($data as $topic_id => $row)
 439              {
 440                  add_log('mod', $forum_id, $topic_id, 'LOG_TOPIC_TYPE_CHANGED', $row['topic_title']);
 441              }
 442          }
 443  
 444          meta_refresh(2, $redirect);
 445          $message = $user->lang[$success_msg];
 446  
 447          if (!$request->is_ajax())
 448          {
 449              $message .= '<br /><br />' . $user->lang('RETURN_PAGE', '<a href="' . $redirect . '">', '</a>');
 450          }
 451          trigger_error($message);
 452      }
 453      else
 454      {
 455          confirm_box(false, $l_new_type, build_hidden_fields($s_hidden_fields));
 456      }
 457  
 458      redirect($redirect);
 459  }
 460  
 461  /**
 462  * Move Topic
 463  */
 464  function mcp_move_topic($topic_ids)
 465  {
 466      global $auth, $user, $db, $template, $phpbb_log, $request, $phpbb_dispatcher;
 467      global $phpEx, $phpbb_root_path;
 468  
 469      // Here we limit the operation to one forum only
 470      $forum_id = phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_move'), true);
 471  
 472      if ($forum_id === false)
 473      {
 474          return;
 475      }
 476  
 477      $to_forum_id = request_var('to_forum_id', 0);
 478      $redirect = request_var('redirect', build_url(array('action', 'quickmod')));
 479      $additional_msg = $success_msg = '';
 480  
 481      $s_hidden_fields = build_hidden_fields(array(
 482          'topic_id_list'    => $topic_ids,
 483          'f'                => $forum_id,
 484          'action'        => 'move',
 485          'redirect'        => $redirect)
 486      );
 487  
 488      if ($to_forum_id)
 489      {
 490          $forum_data = phpbb_get_forum_data($to_forum_id, 'f_post');
 491  
 492          if (!sizeof($forum_data))
 493          {
 494              $additional_msg = $user->lang['FORUM_NOT_EXIST'];
 495          }
 496          else
 497          {
 498              $forum_data = $forum_data[$to_forum_id];
 499  
 500              if ($forum_data['forum_type'] != FORUM_POST)
 501              {
 502                  $additional_msg = $user->lang['FORUM_NOT_POSTABLE'];
 503              }
 504              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)))
 505              {
 506                  $additional_msg = $user->lang['USER_CANNOT_POST'];
 507              }
 508              else if ($forum_id == $to_forum_id)
 509              {
 510                  $additional_msg = $user->lang['CANNOT_MOVE_SAME_FORUM'];
 511              }
 512          }
 513      }
 514      else if (isset($_POST['confirm']))
 515      {
 516          $additional_msg = $user->lang['FORUM_NOT_EXIST'];
 517      }
 518  
 519      if (!$to_forum_id || $additional_msg)
 520      {
 521          $request->overwrite('confirm', null, \phpbb\request\request_interface::POST);
 522          $request->overwrite('confirm_key', null);
 523      }
 524  
 525      if (confirm_box(true))
 526      {
 527          $topic_data = phpbb_get_topic_data($topic_ids);
 528          $leave_shadow = (isset($_POST['move_leave_shadow'])) ? true : false;
 529  
 530          $forum_sync_data = array();
 531  
 532          $forum_sync_data[$forum_id] = current($topic_data);
 533          $forum_sync_data[$to_forum_id] = $forum_data;
 534  
 535          $topics_moved = $topics_moved_unapproved = $topics_moved_softdeleted = 0;
 536          $posts_moved = $posts_moved_unapproved = $posts_moved_softdeleted = 0;
 537  
 538          foreach ($topic_data as $topic_id => $topic_info)
 539          {
 540              if ($topic_info['topic_visibility'] == ITEM_APPROVED)
 541              {
 542                  $topics_moved++;
 543              }
 544              else if ($topic_info['topic_visibility'] == ITEM_UNAPPROVED || $topic_info['topic_visibility'] == ITEM_REAPPROVE)
 545              {
 546                  $topics_moved_unapproved++;
 547              }
 548              else if ($topic_info['topic_visibility'] == ITEM_DELETED)
 549              {
 550                  $topics_moved_softdeleted++;
 551              }
 552  
 553              $posts_moved += $topic_info['topic_posts_approved'];
 554              $posts_moved_unapproved += $topic_info['topic_posts_unapproved'];
 555              $posts_moved_softdeleted += $topic_info['topic_posts_softdeleted'];
 556          }
 557  
 558          $db->sql_transaction('begin');
 559  
 560          // Move topics, but do not resync yet
 561          move_topics($topic_ids, $to_forum_id, false);
 562  
 563          if ($request->is_set_post('move_lock_topics') && $auth->acl_get('m_lock', $to_forum_id))
 564          {
 565              $sql = 'UPDATE ' . TOPICS_TABLE . '
 566                  SET topic_status = ' . ITEM_LOCKED . '
 567                  WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
 568              $db->sql_query($sql);
 569          }
 570  
 571          $shadow_topics = 0;
 572          $forum_ids = array($to_forum_id);
 573          foreach ($topic_data as $topic_id => $row)
 574          {
 575              // Get the list of forums to resync
 576              $forum_ids[] = $row['forum_id'];
 577  
 578              // We add the $to_forum_id twice, because 'forum_id' is updated
 579              // when the topic is moved again later.
 580              $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MOVE', false, array(
 581                  'forum_id'        => (int) $to_forum_id,
 582                  'topic_id'        => (int) $topic_id,
 583                  $row['forum_name'],
 584                  $forum_data['forum_name'],
 585                  (int) $row['forum_id'],
 586                  (int) $forum_data['forum_id'],
 587              ));
 588  
 589              // Leave a redirection if required and only if the topic is visible to users
 590              if ($leave_shadow && $row['topic_visibility'] == ITEM_APPROVED && $row['topic_type'] != POST_GLOBAL)
 591              {
 592                  $shadow = array(
 593                      'forum_id'                =>    (int) $row['forum_id'],
 594                      'icon_id'                =>    (int) $row['icon_id'],
 595                      'topic_attachment'        =>    (int) $row['topic_attachment'],
 596                      'topic_visibility'        =>    ITEM_APPROVED, // a shadow topic is always approved
 597                      'topic_reported'        =>    0, // a shadow topic is never reported
 598                      'topic_title'            =>    (string) $row['topic_title'],
 599                      'topic_poster'            =>    (int) $row['topic_poster'],
 600                      'topic_time'            =>    (int) $row['topic_time'],
 601                      'topic_time_limit'        =>    (int) $row['topic_time_limit'],
 602                      'topic_views'            =>    (int) $row['topic_views'],
 603                      'topic_posts_approved'    =>    (int) $row['topic_posts_approved'],
 604                      'topic_posts_unapproved'=>    (int) $row['topic_posts_unapproved'],
 605                      'topic_posts_softdeleted'=>    (int) $row['topic_posts_softdeleted'],
 606                      'topic_status'            =>    ITEM_MOVED,
 607                      'topic_type'            =>    POST_NORMAL,
 608                      'topic_first_post_id'    =>    (int) $row['topic_first_post_id'],
 609                      'topic_first_poster_colour'=>(string) $row['topic_first_poster_colour'],
 610                      'topic_first_poster_name'=>    (string) $row['topic_first_poster_name'],
 611                      'topic_last_post_id'    =>    (int) $row['topic_last_post_id'],
 612                      'topic_last_poster_id'    =>    (int) $row['topic_last_poster_id'],
 613                      'topic_last_poster_colour'=>(string) $row['topic_last_poster_colour'],
 614                      'topic_last_poster_name'=>    (string) $row['topic_last_poster_name'],
 615                      'topic_last_post_subject'=>    (string) $row['topic_last_post_subject'],
 616                      'topic_last_post_time'    =>    (int) $row['topic_last_post_time'],
 617                      'topic_last_view_time'    =>    (int) $row['topic_last_view_time'],
 618                      'topic_moved_id'        =>    (int) $row['topic_id'],
 619                      'topic_bumped'            =>    (int) $row['topic_bumped'],
 620                      'topic_bumper'            =>    (int) $row['topic_bumper'],
 621                      'poll_title'            =>    (string) $row['poll_title'],
 622                      'poll_start'            =>    (int) $row['poll_start'],
 623                      'poll_length'            =>    (int) $row['poll_length'],
 624                      'poll_max_options'        =>    (int) $row['poll_max_options'],
 625                      'poll_last_vote'        =>    (int) $row['poll_last_vote']
 626                  );
 627  
 628                  /**
 629                  * Perform actions before shadow topic is created.
 630                  *
 631                  * @event core.mcp_main_modify_shadow_sql
 632                  * @var    array    shadow    SQL array to be used by $db->sql_build_array
 633                  * @var    array    row        Topic data
 634                  * @since 3.1.11-RC1
 635                  * @changed 3.1.11-RC1 Added variable: row
 636                  */
 637                  $vars = array(
 638                      'shadow',
 639                      'row',
 640                  );
 641                  extract($phpbb_dispatcher->trigger_event('core.mcp_main_modify_shadow_sql', compact($vars)));
 642  
 643                  $db->sql_query('INSERT INTO ' . TOPICS_TABLE . $db->sql_build_array('INSERT', $shadow));
 644  
 645                  // Shadow topics only count on new "topics" and not posts... a shadow topic alone has 0 posts
 646                  $shadow_topics++;
 647              }
 648          }
 649          unset($topic_data);
 650  
 651          $sync_sql = array();
 652          if ($posts_moved)
 653          {
 654              $sync_sql[$to_forum_id][] = 'forum_posts_approved = forum_posts_approved + ' . (int) $posts_moved;
 655              $sync_sql[$forum_id][] = 'forum_posts_approved = forum_posts_approved - ' . (int) $posts_moved;
 656          }
 657          if ($posts_moved_unapproved)
 658          {
 659              $sync_sql[$to_forum_id][] = 'forum_posts_unapproved = forum_posts_unapproved + ' . (int) $posts_moved_unapproved;
 660              $sync_sql[$forum_id][] = 'forum_posts_unapproved = forum_posts_unapproved - ' . (int) $posts_moved_unapproved;
 661          }
 662          if ($posts_moved_softdeleted)
 663          {
 664              $sync_sql[$to_forum_id][] = 'forum_posts_softdeleted = forum_posts_softdeleted + ' . (int) $posts_moved_softdeleted;
 665              $sync_sql[$forum_id][] = 'forum_posts_softdeleted = forum_posts_softdeleted - ' . (int) $posts_moved_softdeleted;
 666          }
 667  
 668          if ($topics_moved)
 669          {
 670              $sync_sql[$to_forum_id][] = 'forum_topics_approved = forum_topics_approved + ' . (int) $topics_moved;
 671              if ($topics_moved - $shadow_topics > 0)
 672              {
 673                  $sync_sql[$forum_id][] = 'forum_topics_approved = forum_topics_approved - ' . (int) ($topics_moved - $shadow_topics);
 674              }
 675          }
 676          if ($topics_moved_unapproved)
 677          {
 678              $sync_sql[$to_forum_id][] = 'forum_topics_unapproved = forum_topics_unapproved + ' . (int) $topics_moved_unapproved;
 679              $sync_sql[$forum_id][] = 'forum_topics_unapproved = forum_topics_unapproved - ' . (int) $topics_moved_unapproved;
 680          }
 681          if ($topics_moved_softdeleted)
 682          {
 683              $sync_sql[$to_forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted + ' . (int) $topics_moved_softdeleted;
 684              $sync_sql[$forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted - ' . (int) $topics_moved_softdeleted;
 685          }
 686  
 687          $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_MOVED_SUCCESS' : 'TOPICS_MOVED_SUCCESS';
 688  
 689          foreach ($sync_sql as $forum_id_key => $array)
 690          {
 691              $sql = 'UPDATE ' . FORUMS_TABLE . '
 692                  SET ' . implode(', ', $array) . '
 693                  WHERE forum_id = ' . $forum_id_key;
 694              $db->sql_query($sql);
 695          }
 696  
 697          $db->sql_transaction('commit');
 698  
 699          sync('forum', 'forum_id', array($forum_id, $to_forum_id));
 700      }
 701      else
 702      {
 703          $template->assign_vars(array(
 704              'S_FORUM_SELECT'        => make_forum_select($to_forum_id, $forum_id, false, true, true, true),
 705              'S_CAN_LEAVE_SHADOW'    => true,
 706              'S_CAN_LOCK_TOPIC'        => ($auth->acl_get('m_lock', $to_forum_id)) ? true : false,
 707              'ADDITIONAL_MSG'        => $additional_msg)
 708          );
 709  
 710          confirm_box(false, 'MOVE_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html');
 711      }
 712  
 713      $redirect = request_var('redirect', "index.$phpEx");
 714      $redirect = reapply_sid($redirect);
 715  
 716      if (!$success_msg)
 717      {
 718          redirect($redirect);
 719      }
 720      else
 721      {
 722          meta_refresh(3, $redirect);
 723  
 724          $message = $user->lang[$success_msg];
 725          $message .= '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>');
 726          $message .= '<br /><br />' . sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id") . '">', '</a>');
 727          $message .= '<br /><br />' . sprintf($user->lang['RETURN_NEW_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$to_forum_id") . '">', '</a>');
 728  
 729          trigger_error($message);
 730      }
 731  }
 732  
 733  /**
 734  * Restore Topics
 735  */
 736  function mcp_restore_topic($topic_ids)
 737  {
 738      global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container;
 739  
 740      if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_approve')))
 741      {
 742          return;
 743      }
 744  
 745      $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
 746      $forum_id = $request->variable('f', 0);
 747  
 748      $s_hidden_fields = build_hidden_fields(array(
 749          'topic_id_list'    => $topic_ids,
 750          'f'                => $forum_id,
 751          'action'        => 'restore_topic',
 752          'redirect'        => $redirect,
 753      ));
 754      $success_msg = '';
 755  
 756      if (confirm_box(true))
 757      {
 758          $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_RESTORED_SUCCESS' : 'TOPICS_RESTORED_SUCCESS';
 759  
 760          $data = phpbb_get_topic_data($topic_ids);
 761  
 762          $phpbb_content_visibility = $phpbb_container->get('content.visibility');
 763          foreach ($data as $topic_id => $row)
 764          {
 765              $return = $phpbb_content_visibility->set_topic_visibility(ITEM_APPROVED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), '');
 766              if (!empty($return))
 767              {
 768                  add_log('mod', $row['forum_id'], $topic_id, 'LOG_RESTORE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']);
 769              }
 770          }
 771      }
 772      else
 773      {
 774          confirm_box(false, (sizeof($topic_ids) == 1) ? 'RESTORE_TOPIC' : 'RESTORE_TOPICS', $s_hidden_fields);
 775      }
 776  
 777      $topic_id = $request->variable('t', 0);
 778      if (!$request->is_set('quickmod', \phpbb\request\request_interface::REQUEST))
 779      {
 780          $redirect = $request->variable('redirect', "index.$phpEx");
 781          $redirect = reapply_sid($redirect);
 782          $redirect_message = 'PAGE';
 783      }
 784      else if ($topic_id)
 785      {
 786          $redirect = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id);
 787          $redirect_message = 'TOPIC';
 788      }
 789      else
 790      {
 791          $redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
 792          $redirect_message = 'FORUM';
 793      }
 794  
 795      if (!$success_msg)
 796      {
 797          redirect($redirect);
 798      }
 799      else
 800      {
 801          meta_refresh(3, $redirect);
 802          trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_' . $redirect_message], '<a href="' . $redirect . '">', '</a>'));
 803      }
 804  }
 805  
 806  /**
 807  * Delete Topics
 808  */
 809  function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_topic')
 810  {
 811      global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container;
 812  
 813      $check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete';
 814      if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array($check_permission)))
 815      {
 816          return;
 817      }
 818  
 819      $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
 820      $forum_id = $request->variable('f', 0);
 821  
 822      $s_hidden_fields = array(
 823          'topic_id_list'    => $topic_ids,
 824          'f'                => $forum_id,
 825          'action'        => $action,
 826          'redirect'        => $redirect,
 827      );
 828      $success_msg = '';
 829  
 830      if (confirm_box(true))
 831      {
 832          $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_DELETED_SUCCESS' : 'TOPICS_DELETED_SUCCESS';
 833  
 834          $data = phpbb_get_topic_data($topic_ids);
 835  
 836          foreach ($data as $topic_id => $row)
 837          {
 838              if ($row['topic_moved_id'])
 839              {
 840                  add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_SHADOW_TOPIC', $row['topic_title']);
 841              }
 842              else
 843              {
 844                  // Only soft delete non-shadow topics
 845                  if ($is_soft)
 846                  {
 847                      $phpbb_content_visibility = $phpbb_container->get('content.visibility');
 848                      $return = $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), $soft_delete_reason);
 849                      if (!empty($return))
 850                      {
 851                          add_log('mod', $row['forum_id'], $topic_id, 'LOG_SOFTDELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name'], $soft_delete_reason);
 852                      }
 853                  }
 854                  else
 855                  {
 856                      add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name'], $soft_delete_reason);
 857                  }
 858              }
 859          }
 860  
 861          if (!$is_soft)
 862          {
 863              $return = delete_topics('topic_id', $topic_ids);
 864          }
 865      }
 866      else
 867      {
 868          global $template;
 869  
 870          $user->add_lang('posting');
 871  
 872          // If there are only shadow topics, we neither need a reason nor softdelete
 873          $sql = 'SELECT topic_id
 874              FROM ' . TOPICS_TABLE . '
 875              WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
 876                  AND topic_moved_id = 0';
 877          $result = $db->sql_query_limit($sql, 1);
 878          $only_shadow = !$db->sql_fetchfield('topic_id');
 879          $db->sql_freeresult($result);
 880  
 881          $only_softdeleted = false;
 882          if (!$only_shadow && $auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id))
 883          {
 884              // If there are only soft deleted topics, we display a message why the option is not available
 885              $sql = 'SELECT topic_id
 886                  FROM ' . TOPICS_TABLE . '
 887                  WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
 888                      AND topic_visibility <> ' . ITEM_DELETED;
 889              $result = $db->sql_query_limit($sql, 1);
 890              $only_softdeleted = !$db->sql_fetchfield('topic_id');
 891              $db->sql_freeresult($result);
 892          }
 893  
 894          $template->assign_vars(array(
 895              'S_SHADOW_TOPICS'                    => $only_shadow,
 896              'S_SOFTDELETED'                        => $only_softdeleted,
 897              'S_TOPIC_MODE'                        => true,
 898              'S_ALLOWED_DELETE'                    => $auth->acl_get('m_delete', $forum_id),
 899              'S_ALLOWED_SOFTDELETE'                => $auth->acl_get('m_softdelete', $forum_id),
 900              'DELETE_TOPIC_PERMANENTLY_EXPLAIN'    => $user->lang('DELETE_TOPIC_PERMANENTLY', sizeof($topic_ids)),
 901          ));
 902  
 903          $l_confirm = (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS';
 904          if ($only_softdeleted)
 905          {
 906              $l_confirm .= '_PERMANENTLY';
 907              $s_hidden_fields['delete_permanent'] = '1';
 908          }
 909          else if ($only_shadow || !$auth->acl_get('m_softdelete', $forum_id))
 910          {
 911              $s_hidden_fields['delete_permanent'] = '1';
 912          }
 913  
 914          confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');
 915      }
 916  
 917      $topic_id = $request->variable('t', 0);
 918      if (!$request->is_set('quickmod', \phpbb\request\request_interface::REQUEST))
 919      {
 920          $redirect = $request->variable('redirect', "index.$phpEx");
 921          $redirect = reapply_sid($redirect);
 922          $redirect_message = 'PAGE';
 923      }
 924      else if ($is_soft && $topic_id)
 925      {
 926          $redirect = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id);
 927          $redirect_message = 'TOPIC';
 928      }
 929      else
 930      {
 931          $redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
 932          $redirect_message = 'FORUM';
 933      }
 934  
 935      if (!$success_msg)
 936      {
 937          redirect($redirect);
 938      }
 939      else
 940      {
 941          meta_refresh(3, $redirect);
 942          trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_' . $redirect_message], '<a href="' . $redirect . '">', '</a>'));
 943      }
 944  }
 945  
 946  /**
 947  * Delete Posts
 948  */
 949  function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_post')
 950  {
 951      global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container;
 952  
 953      $check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete';
 954      if (!phpbb_check_ids($post_ids, POSTS_TABLE, 'post_id', array($check_permission)))
 955      {
 956          return;
 957      }
 958  
 959      $redirect = $request->variable('redirect', build_url(array('action', 'quickmod')));
 960      $forum_id = $request->variable('f', 0);
 961  
 962      $s_hidden_fields = array(
 963          'post_id_list'    => $post_ids,
 964          'f'                => $forum_id,
 965          'action'        => $action,
 966          'redirect'        => $redirect,
 967      );
 968      $success_msg = '';
 969  
 970      if (confirm_box(true) && $is_soft)
 971      {
 972          $post_info = phpbb_get_post_data($post_ids);
 973  
 974          $topic_info = $approve_log = array();
 975  
 976          // Group the posts by topic_id
 977          foreach ($post_info as $post_id => $post_data)
 978          {
 979              if ($post_data['post_visibility'] != ITEM_APPROVED)
 980              {
 981                  continue;
 982              }
 983              $topic_id = (int) $post_data['topic_id'];
 984  
 985              $topic_info[$topic_id]['posts'][] = (int) $post_id;
 986              $topic_info[$topic_id]['forum_id'] = (int) $post_data['forum_id'];
 987  
 988              if ($post_id == $post_data['topic_first_post_id'])
 989              {
 990                  $topic_info[$topic_id]['first_post'] = true;
 991              }
 992  
 993              if ($post_id == $post_data['topic_last_post_id'])
 994              {
 995                  $topic_info[$topic_id]['last_post'] = true;
 996              }
 997  
 998              $approve_log[] = array(
 999                  'forum_id'        => $post_data['forum_id'],
1000                  'topic_id'        => $post_data['topic_id'],
1001                  'post_subject'    => $post_data['post_subject'],
1002                  'poster_id'        => $post_data['poster_id'],
1003                  'post_username'    => $post_data['post_username'],
1004                  'username'        => $post_data['username'],
1005              );
1006          }
1007  
1008          $phpbb_content_visibility = $phpbb_container->get('content.visibility');
1009          foreach ($topic_info as $topic_id => $topic_data)
1010          {
1011              $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']));
1012          }
1013          $affected_topics = sizeof($topic_info);
1014          // None of the topics is really deleted, so a redirect won't hurt much.
1015          $deleted_topics = 0;
1016  
1017          $success_msg = (sizeof($post_info) == 1) ? $user->lang['POST_DELETED_SUCCESS'] : $user->lang['POSTS_DELETED_SUCCESS'];
1018  
1019          foreach ($approve_log as $row)
1020          {
1021              $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username'];
1022              add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_SOFTDELETE_POST', $row['post_subject'], $post_username, $soft_delete_reason);
1023          }
1024  
1025          $topic_id = $request->variable('t', 0);
1026  
1027          // Return links
1028          $return_link = array();
1029          if ($affected_topics == 1 && $topic_id)
1030          {
1031              $return_link[] = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id") . '">', '</a>');
1032          }
1033          $return_link[] = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>');
1034  
1035      }
1036      else if (confirm_box(true))
1037      {
1038          if (!function_exists('delete_posts'))
1039          {
1040              include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
1041          }
1042  
1043          // Count the number of topics that are affected
1044          // I did not use COUNT(DISTINCT ...) because I remember having problems
1045          // with it on older versions of MySQL -- Ashe
1046  
1047          $sql = 'SELECT DISTINCT topic_id
1048              FROM ' . POSTS_TABLE . '
1049              WHERE ' . $db->sql_in_set('post_id', $post_ids);
1050          $result = $db->sql_query($sql);
1051  
1052          $topic_id_list = array();
1053          while ($row = $db->sql_fetchrow($result))
1054          {
1055              $topic_id_list[] = $row['topic_id'];
1056          }
1057          $affected_topics = sizeof($topic_id_list);
1058          $db->sql_freeresult($result);
1059  
1060          $post_data = phpbb_get_post_data($post_ids);
1061  
1062          foreach ($post_data as $id => $row)
1063          {
1064              $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username'];
1065              add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_DELETE_POST', $row['post_subject'], $post_username, $soft_delete_reason);
1066          }
1067  
1068          // Now delete the posts, topics and forums are automatically resync'ed
1069          delete_posts('post_id', $post_ids);
1070  
1071          $sql = 'SELECT COUNT(topic_id) AS topics_left
1072              FROM ' . TOPICS_TABLE . '
1073              WHERE ' . $db->sql_in_set('topic_id', $topic_id_list);
1074          $result = $db->sql_query_limit($sql, 1);
1075  
1076          $deleted_topics = ($row = $db->sql_fetchrow($result)) ? ($affected_topics - $row['topics_left']) : $affected_topics;
1077          $db->sql_freeresult($result);
1078  
1079          $topic_id = $request->variable('t', 0);
1080  
1081          // Return links
1082          $return_link = array();
1083          if ($affected_topics == 1 && !$deleted_topics && $topic_id)
1084          {
1085              $return_link[] = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id") . '">', '</a>');
1086          }
1087          $return_link[] = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>');
1088  
1089          if (sizeof($post_ids) == 1)
1090          {
1091              if ($deleted_topics)
1092              {
1093                  // We deleted the only post of a topic, which in turn has
1094                  // been removed from the database
1095                  $success_msg = $user->lang['TOPIC_DELETED_SUCCESS'];
1096              }
1097              else
1098              {
1099                  $success_msg = $user->lang['POST_DELETED_SUCCESS'];
1100              }
1101          }
1102          else
1103          {
1104              if ($deleted_topics)
1105              {
1106                  // Some of topics disappeared
1107                  $success_msg = $user->lang['POSTS_DELETED_SUCCESS'] . '<br /><br />' . $user->lang['EMPTY_TOPICS_REMOVED_WARNING'];
1108              }
1109              else
1110              {
1111                  $success_msg = $user->lang['POSTS_DELETED_SUCCESS'];
1112              }
1113          }
1114      }
1115      else
1116      {
1117          global $template;
1118  
1119          $user->add_lang('posting');
1120  
1121          $only_softdeleted = false;
1122          if ($auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id))
1123          {
1124              // If there are only soft deleted posts, we display a message why the option is not available
1125              $sql = 'SELECT post_id
1126                  FROM ' . POSTS_TABLE . '
1127                  WHERE ' . $db->sql_in_set('post_id', $post_ids) . '
1128                      AND post_visibility <> ' . ITEM_DELETED;
1129              $result = $db->sql_query_limit($sql, 1);
1130              $only_softdeleted = !$db->sql_fetchfield('post_id');
1131              $db->sql_freeresult($result);
1132          }
1133  
1134          $template->assign_vars(array(
1135              'S_SOFTDELETED'                        => $only_softdeleted,
1136              'S_ALLOWED_DELETE'                    => $auth->acl_get('m_delete', $forum_id),
1137              'S_ALLOWED_SOFTDELETE'                => $auth->acl_get('m_softdelete', $forum_id),
1138              'DELETE_POST_PERMANENTLY_EXPLAIN'    => $user->lang('DELETE_POST_PERMANENTLY', sizeof($post_ids)),
1139          ));
1140  
1141          $l_confirm = (sizeof($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS';
1142          if ($only_softdeleted)
1143          {
1144              $l_confirm .= '_PERMANENTLY';
1145              $s_hidden_fields['delete_permanent'] = '1';
1146          }
1147          else if (!$auth->acl_get('m_softdelete', $forum_id))
1148          {
1149              $s_hidden_fields['delete_permanent'] = '1';
1150          }
1151  
1152          confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');
1153      }
1154  
1155      $redirect = $request->variable('redirect', "index.$phpEx");
1156      $redirect = reapply_sid($redirect);
1157  
1158      if (!$success_msg)
1159      {
1160          redirect($redirect);
1161      }
1162      else
1163      {
1164          if ($affected_topics != 1 || $deleted_topics || !$topic_id)
1165          {
1166              $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "f=$forum_id&i=main&mode=forum_view", false);
1167          }
1168  
1169          meta_refresh(3, $redirect);
1170          trigger_error($success_msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>') . '<br /><br />' . implode('<br /><br />', $return_link));
1171      }
1172  }
1173  
1174  /**
1175  * Fork Topic
1176  */
1177  function mcp_fork_topic($topic_ids)
1178  {
1179      global $auth, $user, $db, $template, $config;
1180      global $phpEx, $phpbb_root_path, $phpbb_dispatcher;
1181  
1182      if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_')))
1183      {
1184          return;
1185      }
1186  
1187      $to_forum_id = request_var('to_forum_id', 0);
1188      $forum_id = request_var('f', 0);
1189      $redirect = request_var('redirect', build_url(array('action', 'quickmod')));
1190      $additional_msg = $success_msg = '';
1191      $counter = array();
1192  
1193      $s_hidden_fields = build_hidden_fields(array(
1194          'topic_id_list'    => $topic_ids,
1195          'f'                => $forum_id,
1196          'action'        => 'fork',
1197          'redirect'        => $redirect)
1198      );
1199  
1200      if ($to_forum_id)
1201      {
1202          $forum_data = phpbb_get_forum_data($to_forum_id, 'f_post');
1203  
1204          if (!sizeof($topic_ids))
1205          {
1206              $additional_msg = $user->lang['NO_TOPIC_SELECTED'];
1207          }
1208          else if (!sizeof($forum_data))
1209          {
1210              $additional_msg = $user->lang['FORUM_NOT_EXIST'];
1211          }
1212          else
1213          {
1214              $forum_data = $forum_data[$to_forum_id];
1215  
1216              if ($forum_data['forum_type'] != FORUM_POST)
1217              {
1218                  $additional_msg = $user->lang['FORUM_NOT_POSTABLE'];
1219              }
1220              else if (!$auth->acl_get('f_post', $to_forum_id))
1221              {
1222                  $additional_msg = $user->lang['USER_CANNOT_POST'];
1223              }
1224          }
1225      }
1226      else if (isset($_POST['confirm']))
1227      {
1228          $additional_msg = $user->lang['FORUM_NOT_EXIST'];
1229      }
1230  
1231      if ($additional_msg)
1232      {
1233          $request->overwrite('confirm', null, \phpbb\request\request_interface::POST);
1234          $request->overwrite('confirm_key', null);
1235      }
1236  
1237      if (confirm_box(true))
1238      {
1239          $topic_data = phpbb_get_topic_data($topic_ids, 'f_post');
1240  
1241          $total_topics = $total_topics_unapproved = $total_topics_softdeleted = 0;
1242          $total_posts = $total_posts_unapproved = $total_posts_softdeleted = 0;
1243          $new_topic_id_list = array();
1244  
1245          foreach ($topic_data as $topic_id => $topic_row)
1246          {
1247              if (!isset($search_type) && $topic_row['enable_indexing'])
1248              {
1249                  // Select the search method and do some additional checks to ensure it can actually be utilised
1250                  $search_type = $config['search_type'];
1251  
1252                  if (!class_exists($search_type))
1253                  {
1254                      trigger_error('NO_SUCH_SEARCH_MODULE');
1255                  }
1256  
1257                  $error = false;
1258                  $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
1259                  $search_mode = 'post';
1260  
1261                  if ($error)
1262                  {
1263                      trigger_error($error);
1264                  }
1265              }
1266              else if (!isset($search_type) && !$topic_row['enable_indexing'])
1267              {
1268                  $search_type = false;
1269              }
1270  
1271              $sql_ary = array(
1272                  'forum_id'                    => (int) $to_forum_id,
1273                  'icon_id'                    => (int) $topic_row['icon_id'],
1274                  'topic_attachment'            => (int) $topic_row['topic_attachment'],
1275                  'topic_visibility'            => (int) $topic_row['topic_visibility'],
1276                  'topic_reported'            => 0,
1277                  'topic_title'                => (string) $topic_row['topic_title'],
1278                  'topic_poster'                => (int) $topic_row['topic_poster'],
1279                  'topic_time'                => (int) $topic_row['topic_time'],
1280                  'topic_posts_approved'        => (int) $topic_row['topic_posts_approved'],
1281                  'topic_posts_unapproved'    => (int) $topic_row['topic_posts_unapproved'],
1282                  'topic_posts_softdeleted'    => (int) $topic_row['topic_posts_softdeleted'],
1283                  'topic_status'                => (int) $topic_row['topic_status'],
1284                  'topic_type'                => (int) $topic_row['topic_type'],
1285                  'topic_first_poster_name'    => (string) $topic_row['topic_first_poster_name'],
1286                  'topic_last_poster_id'        => (int) $topic_row['topic_last_poster_id'],
1287                  'topic_last_poster_name'    => (string) $topic_row['topic_last_poster_name'],
1288                  'topic_last_post_time'        => (int) $topic_row['topic_last_post_time'],
1289                  'topic_last_view_time'        => (int) $topic_row['topic_last_view_time'],
1290                  'topic_bumped'                => (int) $topic_row['topic_bumped'],
1291                  'topic_bumper'                => (int) $topic_row['topic_bumper'],
1292                  'poll_title'                => (string) $topic_row['poll_title'],
1293                  'poll_start'                => (int) $topic_row['poll_start'],
1294                  'poll_length'                => (int) $topic_row['poll_length'],
1295                  'poll_max_options'            => (int) $topic_row['poll_max_options'],
1296                  'poll_vote_change'            => (int) $topic_row['poll_vote_change'],
1297              );
1298  
1299              /**
1300              * Perform actions before forked topic is created.
1301              *
1302              * @event core.mcp_main_modify_fork_sql
1303              * @var    array    sql_ary        SQL array to be used by $db->sql_build_array
1304              * @var    array    topic_row    Topic data
1305              * @since 3.1.11-RC1
1306              * @changed 3.1.11-RC1 Added variable: topic_row
1307              */
1308              $vars = array(
1309                  'sql_ary',
1310                  'topic_row',
1311              );
1312              extract($phpbb_dispatcher->trigger_event('core.mcp_main_modify_fork_sql', compact($vars)));
1313  
1314              $db->sql_query('INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
1315              $new_topic_id = $db->sql_nextid();
1316              $new_topic_id_list[$topic_id] = $new_topic_id;
1317  
1318              switch ($topic_row['topic_visibility'])
1319              {
1320                  case ITEM_APPROVED:
1321                      $total_topics++;
1322                  break;
1323                  case ITEM_UNAPPROVED:
1324                  case ITEM_REAPPROVE:
1325                      $total_topics_unapproved++;
1326                  break;
1327                  case ITEM_DELETED:
1328                      $total_topics_softdeleted++;
1329                  break;
1330              }
1331  
1332              if ($topic_row['poll_start'])
1333              {
1334                  $poll_rows = array();
1335  
1336                  $sql = 'SELECT *
1337                      FROM ' . POLL_OPTIONS_TABLE . "
1338                      WHERE topic_id = $topic_id";
1339                  $result = $db->sql_query($sql);
1340  
1341                  while ($row = $db->sql_fetchrow($result))
1342                  {
1343                      $sql_ary = array(
1344                          'poll_option_id'    => (int) $row['poll_option_id'],
1345                          'topic_id'            => (int) $new_topic_id,
1346                          'poll_option_text'    => (string) $row['poll_option_text'],
1347                          'poll_option_total'    => 0
1348                      );
1349  
1350                      $db->sql_query('INSERT INTO ' . POLL_OPTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
1351                  }
1352                  $db->sql_freeresult($result);
1353              }
1354  
1355              $sql = 'SELECT *
1356                  FROM ' . POSTS_TABLE . "
1357                  WHERE topic_id = $topic_id
1358                  ORDER BY post_time ASC, post_id ASC";
1359              $result = $db->sql_query($sql);
1360  
1361              $post_rows = array();
1362              while ($row = $db->sql_fetchrow($result))
1363              {
1364                  $post_rows[] = $row;
1365              }
1366              $db->sql_freeresult($result);
1367  
1368              if (!sizeof($post_rows))
1369              {
1370                  continue;
1371              }
1372  
1373              foreach ($post_rows as $row)
1374              {
1375                  $sql_ary = array(
1376                      'topic_id'            => (int) $new_topic_id,
1377                      'forum_id'            => (int) $to_forum_id,
1378                      'poster_id'            => (int) $row['poster_id'],
1379                      'icon_id'            => (int) $row['icon_id'],
1380                      'poster_ip'            => (string) $row['poster_ip'],
1381                      'post_time'            => (int) $row['post_time'],
1382                      'post_visibility'    => (int) $row['post_visibility'],
1383                      'post_reported'        => 0,
1384                      'enable_bbcode'        => (int) $row['enable_bbcode'],
1385                      'enable_smilies'    => (int) $row['enable_smilies'],
1386                      'enable_magic_url'    => (int) $row['enable_magic_url'],
1387                      'enable_sig'        => (int) $row['enable_sig'],
1388                      'post_username'        => (string) $row['post_username'],
1389                      'post_subject'        => (string) $row['post_subject'],
1390                      'post_text'            => (string) $row['post_text'],
1391                      'post_edit_reason'    => (string) $row['post_edit_reason'],
1392                      'post_edit_user'    => (int) $row['post_edit_user'],
1393                      'post_checksum'        => (string) $row['post_checksum'],
1394                      'post_attachment'    => (int) $row['post_attachment'],
1395                      'bbcode_bitfield'    => $row['bbcode_bitfield'],
1396                      'bbcode_uid'        => (string) $row['bbcode_uid'],
1397                      'post_edit_time'    => (int) $row['post_edit_time'],
1398                      'post_edit_count'    => (int) $row['post_edit_count'],
1399                      'post_edit_locked'    => (int) $row['post_edit_locked'],
1400                      'post_postcount'    => $row['post_postcount'],
1401                  );
1402                  // Adjust post count only if the post can be incremented to the user counter
1403                  if ($row['post_postcount'])
1404                  {
1405                      if (isset($counter[$row['poster_id']]))
1406                      {
1407                          ++$counter[$row['poster_id']];
1408                      }
1409                      else
1410                      {
1411                          $counter[$row['poster_id']] = 1;
1412                      }
1413                  }
1414                  $db->sql_query('INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
1415                  $new_post_id = $db->sql_nextid();
1416  
1417                  switch ($row['post_visibility'])
1418                  {
1419                      case ITEM_APPROVED:
1420                          $total_posts++;
1421                      break;
1422                      case ITEM_UNAPPROVED:
1423                      case ITEM_REAPPROVE:
1424                          $total_posts_unapproved++;
1425                      break;
1426                      case ITEM_DELETED:
1427                          $total_posts_softdeleted++;
1428                      break;
1429                  }
1430  
1431                  // Copy whether the topic is dotted
1432                  markread('post', $to_forum_id, $new_topic_id, 0, $row['poster_id']);
1433  
1434                  if (!empty($search_type))
1435                  {
1436                      $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);
1437                      $search_mode = 'reply'; // After one we index replies
1438                  }
1439  
1440                  // Copy Attachments
1441                  if ($row['post_attachment'])
1442                  {
1443                      $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . "
1444                          WHERE post_msg_id = {$row['post_id']}
1445                              AND topic_id = $topic_id
1446                              AND in_message = 0";
1447                      $result = $db->sql_query($sql);
1448  
1449                      $sql_ary = array();
1450                      while ($attach_row = $db->sql_fetchrow($result))
1451                      {
1452                          $sql_ary[] = array(
1453                              'post_msg_id'        => (int) $new_post_id,
1454                              'topic_id'            => (int) $new_topic_id,
1455                              'in_message'        => 0,
1456                              'is_orphan'            => (int) $attach_row['is_orphan'],
1457                              'poster_id'            => (int) $attach_row['poster_id'],
1458                              'physical_filename'    => (string) utf8_basename($attach_row['physical_filename']),
1459                              'real_filename'        => (string) utf8_basename($attach_row['real_filename']),
1460                              'download_count'    => (int) $attach_row['download_count'],
1461                              'attach_comment'    => (string) $attach_row['attach_comment'],
1462                              'extension'            => (string) $attach_row['extension'],
1463                              'mimetype'            => (string) $attach_row['mimetype'],
1464                              'filesize'            => (int) $attach_row['filesize'],
1465                              'filetime'            => (int) $attach_row['filetime'],
1466                              'thumbnail'            => (int) $attach_row['thumbnail']
1467                          );
1468                      }
1469                      $db->sql_freeresult($result);
1470  
1471                      if (sizeof($sql_ary))
1472                      {
1473                          $db->sql_multi_insert(ATTACHMENTS_TABLE, $sql_ary);
1474                      }
1475                  }
1476              }
1477  
1478              // Copy topic subscriptions to new topic
1479              $sql = 'SELECT user_id, notify_status
1480                  FROM ' . TOPICS_WATCH_TABLE . '
1481                  WHERE topic_id = ' . $topic_id;
1482              $result = $db->sql_query($sql);
1483  
1484              $sql_ary = array();
1485              while ($row = $db->sql_fetchrow($result))
1486              {
1487                  $sql_ary[] = array(
1488                      'topic_id'        => (int) $new_topic_id,
1489                      'user_id'        => (int) $row['user_id'],
1490                      'notify_status'    => (int) $row['notify_status'],
1491                  );
1492              }
1493              $db->sql_freeresult($result);
1494  
1495              if (sizeof($sql_ary))
1496              {
1497                  $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary);
1498              }
1499  
1500              // Copy bookmarks to new topic
1501              $sql = 'SELECT user_id
1502                  FROM ' . BOOKMARKS_TABLE . '
1503                  WHERE topic_id = ' . $topic_id;
1504              $result = $db->sql_query($sql);
1505  
1506              $sql_ary = array();
1507              while ($row = $db->sql_fetchrow($result))
1508              {
1509                  $sql_ary[] = array(
1510                      'topic_id'        => (int) $new_topic_id,
1511                      'user_id'        => (int) $row['user_id'],
1512                  );
1513              }
1514              $db->sql_freeresult($result);
1515  
1516              if (sizeof($sql_ary))
1517              {
1518                  $db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary);
1519              }
1520          }
1521  
1522          // Sync new topics, parent forums and board stats
1523          $sql = 'UPDATE ' . FORUMS_TABLE . '
1524              SET forum_posts_approved = forum_posts_approved + ' . $total_posts . ',
1525                  forum_posts_unapproved = forum_posts_unapproved + ' . $total_posts_unapproved . ',
1526                  forum_posts_softdeleted = forum_posts_softdeleted + ' . $total_posts_softdeleted . ',
1527                  forum_topics_approved = forum_topics_approved + ' . $total_topics . ',
1528                  forum_topics_unapproved = forum_topics_unapproved + ' . $total_topics_unapproved . ',
1529                  forum_topics_softdeleted = forum_topics_softdeleted + ' . $total_topics_softdeleted . '
1530              WHERE forum_id = ' . $to_forum_id;
1531          $db->sql_query($sql);
1532  
1533          if (!empty($counter))
1534          {
1535              // Do only one query per user and not a query per post.
1536              foreach ($counter as $user_id => $count)
1537              {
1538                  $sql = 'UPDATE ' . USERS_TABLE . '
1539                      SET user_posts = user_posts + ' . (int) $count . '
1540                      WHERE user_id = ' . (int) $user_id;
1541                  $db->sql_query($sql);
1542              }
1543          }
1544  
1545          sync('topic', 'topic_id', $new_topic_id_list);
1546          sync('forum', 'forum_id', $to_forum_id);
1547  
1548          set_config_count('num_topics', sizeof($new_topic_id_list), true);
1549          set_config_count('num_posts', $total_posts, true);
1550  
1551          foreach ($new_topic_id_list as $topic_id => $new_topic_id)
1552          {
1553              add_log('mod', $to_forum_id, $new_topic_id, 'LOG_FORK', $topic_row['forum_name']);
1554          }
1555  
1556          $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS';
1557      }
1558      else
1559      {
1560          $template->assign_vars(array(
1561              'S_FORUM_SELECT'        => make_forum_select($to_forum_id, false, false, true, true, true),
1562              'S_CAN_LEAVE_SHADOW'    => false,
1563              'ADDITIONAL_MSG'        => $additional_msg)
1564          );
1565  
1566          confirm_box(false, 'FORK_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html');
1567      }
1568  
1569      $redirect = request_var('redirect', "index.$phpEx");
1570      $redirect = reapply_sid($redirect);
1571  
1572      if (!$success_msg)
1573      {
1574          redirect($redirect);
1575      }
1576      else
1577      {
1578          $redirect_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id);
1579          meta_refresh(3, $redirect_url);
1580          $return_link = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect_url . '">', '</a>');
1581  
1582          if ($forum_id != $to_forum_id)
1583          {
1584              $return_link .= '<br /><br />' . sprintf($user->lang['RETURN_NEW_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $to_forum_id) . '">', '</a>');
1585          }
1586  
1587          trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link);
1588      }
1589  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1