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