[ Index ] |
PHP Cross Reference of phpBB-3.3.14-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, $phpbb_dispatcher; 885 886 $forum_id = $request->variable('f', 0); 887 $check_permission = ($is_soft) ? ['m_softdelete'] : ['m_delete']; 888 /** 889 * This event allows you to modify the current user's checked permissions when deleting a topic 890 * 891 * @event core.mcp_delete_topic_modify_permissions 892 * @var array topic_ids The array of topic IDs to be deleted 893 * @var int forum_id The current forum ID 894 * @var bool is_soft Boolean designating whether we're soft deleting or not 895 * @var string soft_delete_reason The reason we're soft deleting 896 * @var string action The current delete action 897 * @var array check_permission The array with a permission to check for, can be set to false to not check them 898 * @since 3.3.3-RC1 899 */ 900 $vars = array( 901 'topic_ids', 902 'forum_id', 903 'is_soft', 904 'soft_delete_reason', 905 'action', 906 'check_permission', 907 ); 908 extract($phpbb_dispatcher->trigger_event('core.mcp_delete_topic_modify_permissions', compact($vars))); 909 910 if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', $check_permission)) 911 { 912 return; 913 } 914 915 $redirect = $request->variable('redirect', build_url(array('action', 'quickmod'))); 916 917 $s_hidden_fields = array( 918 'topic_id_list' => $topic_ids, 919 'f' => $forum_id, 920 'action' => $action, 921 'redirect' => $redirect, 922 ); 923 $success_msg = ''; 924 925 if (confirm_box(true)) 926 { 927 $success_msg = (count($topic_ids) == 1) ? 'TOPIC_DELETED_SUCCESS' : 'TOPICS_DELETED_SUCCESS'; 928 929 $data = phpbb_get_topic_data($topic_ids); 930 931 foreach ($data as $topic_id => $row) 932 { 933 if ($row['topic_moved_id']) 934 { 935 $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_SHADOW_TOPIC', false, array( 936 'forum_id' => $row['forum_id'], 937 'topic_id' => $topic_id, 938 $row['topic_title'] 939 )); 940 } 941 else 942 { 943 // Only soft delete non-shadow topics 944 if ($is_soft) 945 { 946 /* @var $phpbb_content_visibility \phpbb\content_visibility */ 947 $phpbb_content_visibility = $phpbb_container->get('content.visibility'); 948 $return = $phpbb_content_visibility->set_topic_visibility(ITEM_DELETED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), $soft_delete_reason); 949 if (!empty($return)) 950 { 951 $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SOFTDELETE_TOPIC', false, array( 952 'forum_id' => $row['forum_id'], 953 'topic_id' => $topic_id, 954 $row['topic_title'], 955 $row['topic_first_poster_name'], 956 $soft_delete_reason 957 )); 958 } 959 } 960 else 961 { 962 $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_TOPIC', false, array( 963 'forum_id' => $row['forum_id'], 964 'topic_id' => $topic_id, 965 $row['topic_title'], 966 $row['topic_first_poster_name'], 967 $soft_delete_reason 968 )); 969 } 970 } 971 } 972 973 if (!$is_soft) 974 { 975 delete_topics('topic_id', $topic_ids); 976 } 977 } 978 else 979 { 980 global $template; 981 982 $user->add_lang('posting'); 983 984 // If there are only shadow topics, we neither need a reason nor softdelete 985 $sql = 'SELECT topic_id 986 FROM ' . TOPICS_TABLE . ' 987 WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' 988 AND topic_moved_id = 0'; 989 $result = $db->sql_query_limit($sql, 1); 990 $only_shadow = !$db->sql_fetchfield('topic_id'); 991 $db->sql_freeresult($result); 992 993 $only_softdeleted = false; 994 if (!$only_shadow && $auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id)) 995 { 996 // If there are only soft deleted topics, we display a message why the option is not available 997 $sql = 'SELECT topic_id 998 FROM ' . TOPICS_TABLE . ' 999 WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' 1000 AND topic_visibility <> ' . ITEM_DELETED; 1001 $result = $db->sql_query_limit($sql, 1); 1002 $only_softdeleted = !$db->sql_fetchfield('topic_id'); 1003 $db->sql_freeresult($result); 1004 } 1005 1006 $template->assign_vars(array( 1007 'S_SHADOW_TOPICS' => $only_shadow, 1008 'S_SOFTDELETED' => $only_softdeleted, 1009 'S_TOPIC_MODE' => true, 1010 'S_ALLOWED_DELETE' => $auth->acl_get('m_delete', $forum_id), 1011 'S_ALLOWED_SOFTDELETE' => $auth->acl_get('m_softdelete', $forum_id), 1012 'DELETE_TOPIC_PERMANENTLY_EXPLAIN' => $user->lang('DELETE_TOPIC_PERMANENTLY', count($topic_ids)), 1013 )); 1014 1015 $count = count($topic_ids); 1016 $l_confirm = $count === 1 ? 'DELETE_TOPIC' : 'DELETE_TOPICS'; 1017 if ($only_softdeleted) 1018 { 1019 $l_confirm = array($l_confirm . '_PERMANENTLY', $count); 1020 $s_hidden_fields['delete_permanent'] = '1'; 1021 } 1022 else if ($only_shadow || !$auth->acl_get('m_softdelete', $forum_id)) 1023 { 1024 $s_hidden_fields['delete_permanent'] = '1'; 1025 } 1026 1027 /** 1028 * This event allows you to modify the hidden form fields when deleting topics 1029 * 1030 * @event core.mcp_delete_topic_modify_hidden_fields 1031 * @var string l_confirm The confirmation text language variable (DELETE_TOPIC(S), DELETE_TOPIC(S)_PERMANENTLY) 1032 * @var array s_hidden_fields The array holding the hidden form fields 1033 * @var array topic_ids The array of topic IDs to be deleted 1034 * @var int forum_id The current forum ID 1035 * @var bool only_softdeleted If the topic_ids are all soft deleted, this is true 1036 * @var bool only_shadow If the topic_ids are all shadow topics, this is true 1037 * @since 3.3.3-RC1 1038 */ 1039 $vars = array( 1040 'l_confirm', 1041 's_hidden_fields', 1042 'topic_ids', 1043 'forum_id', 1044 'only_softdeleted', 1045 'only_shadow', 1046 ); 1047 extract($phpbb_dispatcher->trigger_event('core.mcp_delete_topic_modify_hidden_fields', compact($vars))); 1048 1049 confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html'); 1050 } 1051 1052 $topic_id = $request->variable('t', 0); 1053 if (!$request->is_set('quickmod', \phpbb\request\request_interface::REQUEST)) 1054 { 1055 $redirect = $request->variable('redirect', "index.$phpEx"); 1056 $redirect = reapply_sid($redirect); 1057 $redirect_message = 'PAGE'; 1058 } 1059 else if ($is_soft && $topic_id) 1060 { 1061 $redirect = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id); 1062 $redirect_message = 'TOPIC'; 1063 } 1064 else 1065 { 1066 $redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id); 1067 $redirect_message = 'FORUM'; 1068 } 1069 1070 if (!$success_msg) 1071 { 1072 redirect($redirect); 1073 } 1074 else 1075 { 1076 meta_refresh(3, $redirect); 1077 trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_' . $redirect_message], '<a href="' . $redirect . '">', '</a>')); 1078 } 1079 } 1080 1081 /** 1082 * Delete Posts 1083 */ 1084 function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_post') 1085 { 1086 global $auth, $user, $db, $phpEx, $phpbb_root_path, $request, $phpbb_container, $phpbb_log; 1087 1088 $check_permission = ($is_soft) ? 'm_softdelete' : 'm_delete'; 1089 if (!phpbb_check_ids($post_ids, POSTS_TABLE, 'post_id', array($check_permission))) 1090 { 1091 return; 1092 } 1093 1094 $redirect = $request->variable('redirect', build_url(array('action', 'quickmod'))); 1095 $forum_id = $request->variable('f', 0); 1096 $topic_id = 0; 1097 1098 $s_hidden_fields = array( 1099 'post_id_list' => $post_ids, 1100 'f' => $forum_id, 1101 'action' => $action, 1102 'redirect' => $redirect, 1103 ); 1104 $success_msg = ''; 1105 1106 if (confirm_box(true) && $is_soft) 1107 { 1108 $post_info = phpbb_get_post_data($post_ids); 1109 1110 $topic_info = $approve_log = array(); 1111 1112 // Group the posts by topic_id 1113 foreach ($post_info as $post_id => $post_data) 1114 { 1115 if ($post_data['post_visibility'] != ITEM_APPROVED) 1116 { 1117 continue; 1118 } 1119 $topic_id = (int) $post_data['topic_id']; 1120 1121 $topic_info[$topic_id]['posts'][] = (int) $post_id; 1122 $topic_info[$topic_id]['forum_id'] = (int) $post_data['forum_id']; 1123 1124 if ($post_id == $post_data['topic_first_post_id']) 1125 { 1126 $topic_info[$topic_id]['first_post'] = true; 1127 } 1128 1129 if ($post_id == $post_data['topic_last_post_id']) 1130 { 1131 $topic_info[$topic_id]['last_post'] = true; 1132 } 1133 1134 $approve_log[] = array( 1135 'forum_id' => $post_data['forum_id'], 1136 'topic_id' => $post_data['topic_id'], 1137 'post_id' => $post_id, 1138 'post_subject' => $post_data['post_subject'], 1139 'poster_id' => $post_data['poster_id'], 1140 'post_username' => $post_data['post_username'], 1141 'username' => $post_data['username'], 1142 ); 1143 } 1144 1145 /* @var $phpbb_content_visibility \phpbb\content_visibility */ 1146 $phpbb_content_visibility = $phpbb_container->get('content.visibility'); 1147 foreach ($topic_info as $topic_id => $topic_data) 1148 { 1149 $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'])); 1150 } 1151 $affected_topics = count($topic_info); 1152 // None of the topics is really deleted, so a redirect won't hurt much. 1153 $deleted_topics = 0; 1154 1155 $success_msg = (count($post_info) == 1) ? $user->lang['POST_DELETED_SUCCESS'] : $user->lang['POSTS_DELETED_SUCCESS']; 1156 1157 foreach ($approve_log as $row) 1158 { 1159 $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username']; 1160 $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_SOFTDELETE_POST', false, array( 1161 'forum_id' => $row['forum_id'], 1162 'topic_id' => $row['topic_id'], 1163 'post_id' => $row['post_id'], 1164 $row['post_subject'], 1165 $post_username, 1166 $soft_delete_reason 1167 )); 1168 } 1169 1170 // Return links 1171 $return_link = array(); 1172 if ($affected_topics == 1 && $topic_id) 1173 { 1174 $return_link[] = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t=$topic_id") . '">', '</a>'); 1175 } 1176 $return_link[] = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>'); 1177 1178 } 1179 else if (confirm_box(true)) 1180 { 1181 if (!function_exists('delete_posts')) 1182 { 1183 include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); 1184 } 1185 1186 // Count the number of topics that are affected 1187 // I did not use COUNT(DISTINCT ...) because I remember having problems 1188 // with it on older versions of MySQL -- Ashe 1189 1190 $sql = 'SELECT DISTINCT topic_id 1191 FROM ' . POSTS_TABLE . ' 1192 WHERE ' . $db->sql_in_set('post_id', $post_ids); 1193 $result = $db->sql_query($sql); 1194 1195 $topic_id_list = array(); 1196 while ($row = $db->sql_fetchrow($result)) 1197 { 1198 $topic_id_list[] = $topic_id = $row['topic_id']; 1199 } 1200 $affected_topics = count($topic_id_list); 1201 $db->sql_freeresult($result); 1202 1203 $post_data = phpbb_get_post_data($post_ids); 1204 1205 foreach ($post_data as $id => $row) 1206 { 1207 $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username']; 1208 $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_DELETE_POST', false, array( 1209 'forum_id' => $row['forum_id'], 1210 'topic_id' => $row['topic_id'], 1211 'post_id' => $row['post_id'], 1212 $row['post_subject'], 1213 $post_username, 1214 $soft_delete_reason 1215 )); 1216 } 1217 1218 // Now delete the posts, topics and forums are automatically resync'ed 1219 delete_posts('post_id', $post_ids); 1220 1221 $sql = 'SELECT COUNT(topic_id) AS topics_left 1222 FROM ' . TOPICS_TABLE . ' 1223 WHERE ' . $db->sql_in_set('topic_id', $topic_id_list); 1224 $result = $db->sql_query_limit($sql, 1); 1225 1226 $deleted_topics = ($row = $db->sql_fetchrow($result)) ? ($affected_topics - $row['topics_left']) : $affected_topics; 1227 $db->sql_freeresult($result); 1228 1229 // Return links 1230 $return_link = array(); 1231 if ($affected_topics == 1 && !$deleted_topics && $topic_id) 1232 { 1233 $return_link[] = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t=$topic_id") . '">', '</a>'); 1234 } 1235 $return_link[] = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>'); 1236 1237 if (count($post_ids) == 1) 1238 { 1239 if ($deleted_topics) 1240 { 1241 // We deleted the only post of a topic, which in turn has 1242 // been removed from the database 1243 $success_msg = $user->lang['TOPIC_DELETED_SUCCESS']; 1244 } 1245 else 1246 { 1247 // Remove any post id anchor 1248 if (($anchor_pos = strrpos($redirect, '#p')) !== false) 1249 { 1250 $redirect = substr($redirect, 0, $anchor_pos); 1251 } 1252 1253 $success_msg = $user->lang['POST_DELETED_SUCCESS']; 1254 } 1255 } 1256 else 1257 { 1258 if ($deleted_topics) 1259 { 1260 // Some of topics disappeared 1261 $success_msg = $user->lang['POSTS_DELETED_SUCCESS'] . '<br /><br />' . $user->lang['EMPTY_TOPICS_REMOVED_WARNING']; 1262 } 1263 else 1264 { 1265 $success_msg = $user->lang['POSTS_DELETED_SUCCESS']; 1266 } 1267 } 1268 } 1269 else 1270 { 1271 global $template; 1272 1273 $user->add_lang('posting'); 1274 1275 $only_softdeleted = false; 1276 if ($auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id)) 1277 { 1278 // If there are only soft deleted posts, we display a message why the option is not available 1279 $sql = 'SELECT post_id 1280 FROM ' . POSTS_TABLE . ' 1281 WHERE ' . $db->sql_in_set('post_id', $post_ids) . ' 1282 AND post_visibility <> ' . ITEM_DELETED; 1283 $result = $db->sql_query_limit($sql, 1); 1284 $only_softdeleted = !$db->sql_fetchfield('post_id'); 1285 $db->sql_freeresult($result); 1286 } 1287 1288 $template->assign_vars(array( 1289 'S_SOFTDELETED' => $only_softdeleted, 1290 'S_ALLOWED_DELETE' => $auth->acl_get('m_delete', $forum_id), 1291 'S_ALLOWED_SOFTDELETE' => $auth->acl_get('m_softdelete', $forum_id), 1292 'DELETE_POST_PERMANENTLY_EXPLAIN' => $user->lang('DELETE_POST_PERMANENTLY', count($post_ids)), 1293 )); 1294 1295 $count = count($post_ids); 1296 $l_confirm = $count === 1 ? 'DELETE_POST' : 'DELETE_POSTS'; 1297 if ($only_softdeleted) 1298 { 1299 $l_confirm = array($l_confirm . '_PERMANENTLY', $count); 1300 $s_hidden_fields['delete_permanent'] = '1'; 1301 } 1302 else if (!$auth->acl_get('m_softdelete', $forum_id)) 1303 { 1304 $s_hidden_fields['delete_permanent'] = '1'; 1305 } 1306 1307 confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html'); 1308 } 1309 1310 $redirect = reapply_sid($redirect); 1311 1312 if (!$success_msg) 1313 { 1314 redirect($redirect); 1315 } 1316 else 1317 { 1318 if ($affected_topics != 1 || $deleted_topics || !$topic_id) 1319 { 1320 $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "f=$forum_id&i=main&mode=forum_view", false); 1321 } 1322 1323 meta_refresh(3, $redirect); 1324 trigger_error($success_msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>') . '<br /><br />' . implode('<br /><br />', $return_link)); 1325 } 1326 } 1327 1328 /** 1329 * Fork Topic 1330 */ 1331 function mcp_fork_topic($topic_ids) 1332 { 1333 global $auth, $user, $db, $template, $config; 1334 global $phpEx, $phpbb_root_path, $phpbb_log, $request, $phpbb_dispatcher; 1335 1336 if (!phpbb_check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) 1337 { 1338 return; 1339 } 1340 1341 $to_forum_id = $request->variable('to_forum_id', 0); 1342 $forum_id = $request->variable('f', 0); 1343 $redirect = $request->variable('redirect', build_url(array('action', 'quickmod'))); 1344 $additional_msg = $success_msg = ''; 1345 $counter = array(); 1346 1347 $s_hidden_fields = build_hidden_fields(array( 1348 'topic_id_list' => $topic_ids, 1349 'f' => $forum_id, 1350 'action' => 'fork', 1351 'redirect' => $redirect) 1352 ); 1353 1354 if ($to_forum_id) 1355 { 1356 $forum_data = phpbb_get_forum_data($to_forum_id, 'f_post'); 1357 1358 if (!count($topic_ids)) 1359 { 1360 $additional_msg = $user->lang['NO_TOPIC_SELECTED']; 1361 } 1362 else if (!count($forum_data)) 1363 { 1364 $additional_msg = $user->lang['FORUM_NOT_EXIST']; 1365 } 1366 else 1367 { 1368 $forum_data = $forum_data[$to_forum_id]; 1369 1370 if ($forum_data['forum_type'] != FORUM_POST) 1371 { 1372 $additional_msg = $user->lang['FORUM_NOT_POSTABLE']; 1373 } 1374 else if (!$auth->acl_get('f_post', $to_forum_id)) 1375 { 1376 $additional_msg = $user->lang['USER_CANNOT_POST']; 1377 } 1378 } 1379 } 1380 else if (isset($_POST['confirm'])) 1381 { 1382 $additional_msg = $user->lang['FORUM_NOT_EXIST']; 1383 } 1384 1385 if ($additional_msg) 1386 { 1387 $request->overwrite('confirm', null, \phpbb\request\request_interface::POST); 1388 $request->overwrite('confirm_key', null); 1389 } 1390 1391 if (confirm_box(true)) 1392 { 1393 $topic_data = phpbb_get_topic_data($topic_ids, 'f_post'); 1394 1395 $total_topics = $total_topics_unapproved = $total_topics_softdeleted = 0; 1396 $total_posts = $total_posts_unapproved = $total_posts_softdeleted = 0; 1397 $new_topic_id_list = array(); 1398 1399 foreach ($topic_data as $topic_id => $topic_row) 1400 { 1401 if (!isset($search_type) && $topic_row['enable_indexing']) 1402 { 1403 // Select the search method and do some additional checks to ensure it can actually be utilised 1404 $search_type = $config['search_type']; 1405 1406 if (!class_exists($search_type)) 1407 { 1408 trigger_error('NO_SUCH_SEARCH_MODULE'); 1409 } 1410 1411 $error = false; 1412 $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); 1413 $search_mode = 'post'; 1414 1415 if ($error) 1416 { 1417 trigger_error($error); 1418 } 1419 } 1420 else if (!isset($search_type) && !$topic_row['enable_indexing']) 1421 { 1422 $search_type = false; 1423 } 1424 1425 $sql_ary = array( 1426 'forum_id' => (int) $to_forum_id, 1427 'icon_id' => (int) $topic_row['icon_id'], 1428 'topic_attachment' => (int) $topic_row['topic_attachment'], 1429 'topic_visibility' => (int) $topic_row['topic_visibility'], 1430 'topic_reported' => 0, 1431 'topic_title' => (string) $topic_row['topic_title'], 1432 'topic_poster' => (int) $topic_row['topic_poster'], 1433 'topic_time' => (int) $topic_row['topic_time'], 1434 'topic_posts_approved' => (int) $topic_row['topic_posts_approved'], 1435 'topic_posts_unapproved' => (int) $topic_row['topic_posts_unapproved'], 1436 'topic_posts_softdeleted' => (int) $topic_row['topic_posts_softdeleted'], 1437 'topic_status' => (int) $topic_row['topic_status'], 1438 'topic_type' => (int) $topic_row['topic_type'], 1439 'topic_first_poster_name' => (string) $topic_row['topic_first_poster_name'], 1440 'topic_last_poster_id' => (int) $topic_row['topic_last_poster_id'], 1441 'topic_last_poster_name' => (string) $topic_row['topic_last_poster_name'], 1442 'topic_last_post_time' => (int) $topic_row['topic_last_post_time'], 1443 'topic_last_view_time' => (int) $topic_row['topic_last_view_time'], 1444 'topic_bumped' => (int) $topic_row['topic_bumped'], 1445 'topic_bumper' => (int) $topic_row['topic_bumper'], 1446 'poll_title' => (string) $topic_row['poll_title'], 1447 'poll_start' => (int) $topic_row['poll_start'], 1448 'poll_length' => (int) $topic_row['poll_length'], 1449 'poll_max_options' => (int) $topic_row['poll_max_options'], 1450 'poll_vote_change' => (int) $topic_row['poll_vote_change'], 1451 ); 1452 1453 /** 1454 * Perform actions before forked topic is created. 1455 * 1456 * @event core.mcp_main_modify_fork_sql 1457 * @var array sql_ary SQL array to be used by $db->sql_build_array 1458 * @var array topic_row Topic data 1459 * @since 3.1.11-RC1 1460 * @changed 3.1.11-RC1 Added variable: topic_row 1461 */ 1462 $vars = array( 1463 'sql_ary', 1464 'topic_row', 1465 ); 1466 extract($phpbb_dispatcher->trigger_event('core.mcp_main_modify_fork_sql', compact($vars))); 1467 1468 $db->sql_query('INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); 1469 $new_topic_id = $db->sql_nextid(); 1470 $new_topic_id_list[$topic_id] = $new_topic_id; 1471 1472 switch ($topic_row['topic_visibility']) 1473 { 1474 case ITEM_APPROVED: 1475 $total_topics++; 1476 break; 1477 case ITEM_UNAPPROVED: 1478 case ITEM_REAPPROVE: 1479 $total_topics_unapproved++; 1480 break; 1481 case ITEM_DELETED: 1482 $total_topics_softdeleted++; 1483 break; 1484 } 1485 1486 if ($topic_row['poll_start']) 1487 { 1488 $sql = 'SELECT * 1489 FROM ' . POLL_OPTIONS_TABLE . " 1490 WHERE topic_id = $topic_id"; 1491 $result = $db->sql_query($sql); 1492 1493 while ($row = $db->sql_fetchrow($result)) 1494 { 1495 $sql_ary = array( 1496 'poll_option_id' => (int) $row['poll_option_id'], 1497 'topic_id' => (int) $new_topic_id, 1498 'poll_option_text' => (string) $row['poll_option_text'], 1499 'poll_option_total' => 0 1500 ); 1501 1502 $db->sql_query('INSERT INTO ' . POLL_OPTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); 1503 } 1504 $db->sql_freeresult($result); 1505 } 1506 1507 $sql = 'SELECT * 1508 FROM ' . POSTS_TABLE . " 1509 WHERE topic_id = $topic_id 1510 ORDER BY post_time ASC, post_id ASC"; 1511 $result = $db->sql_query($sql); 1512 1513 $post_rows = array(); 1514 while ($row = $db->sql_fetchrow($result)) 1515 { 1516 $post_rows[] = $row; 1517 } 1518 $db->sql_freeresult($result); 1519 1520 if (!count($post_rows)) 1521 { 1522 continue; 1523 } 1524 1525 foreach ($post_rows as $row) 1526 { 1527 $sql_ary = array( 1528 'topic_id' => (int) $new_topic_id, 1529 'forum_id' => (int) $to_forum_id, 1530 'poster_id' => (int) $row['poster_id'], 1531 'icon_id' => (int) $row['icon_id'], 1532 'poster_ip' => (string) $row['poster_ip'], 1533 'post_time' => (int) $row['post_time'], 1534 'post_visibility' => (int) $row['post_visibility'], 1535 'post_reported' => 0, 1536 'enable_bbcode' => (int) $row['enable_bbcode'], 1537 'enable_smilies' => (int) $row['enable_smilies'], 1538 'enable_magic_url' => (int) $row['enable_magic_url'], 1539 'enable_sig' => (int) $row['enable_sig'], 1540 'post_username' => (string) $row['post_username'], 1541 'post_subject' => (string) $row['post_subject'], 1542 'post_text' => (string) $row['post_text'], 1543 'post_edit_reason' => (string) $row['post_edit_reason'], 1544 'post_edit_user' => (int) $row['post_edit_user'], 1545 'post_checksum' => (string) $row['post_checksum'], 1546 'post_attachment' => (int) $row['post_attachment'], 1547 'bbcode_bitfield' => $row['bbcode_bitfield'], 1548 'bbcode_uid' => (string) $row['bbcode_uid'], 1549 'post_edit_time' => (int) $row['post_edit_time'], 1550 'post_edit_count' => (int) $row['post_edit_count'], 1551 'post_edit_locked' => (int) $row['post_edit_locked'], 1552 'post_postcount' => $row['post_postcount'], 1553 ); 1554 // Adjust post count only if the post can be incremented to the user counter 1555 if ($row['post_postcount']) 1556 { 1557 if (isset($counter[$row['poster_id']])) 1558 { 1559 ++$counter[$row['poster_id']]; 1560 } 1561 else 1562 { 1563 $counter[$row['poster_id']] = 1; 1564 } 1565 } 1566 1567 /** 1568 * Modify the forked post's sql array before it's inserted into the database. 1569 * 1570 * @event core.mcp_main_modify_fork_post_sql 1571 * @var int new_topic_id The newly created topic ID 1572 * @var int to_forum_id The forum ID where the forked topic has been moved to 1573 * @var array sql_ary SQL Array with the post's data 1574 * @var array row Post data 1575 * @var array counter Array with post counts 1576 * @since 3.3.5-RC1 1577 */ 1578 $vars = [ 1579 'new_topic_id', 1580 'to_forum_id', 1581 'sql_ary', 1582 'row', 1583 'counter', 1584 ]; 1585 extract($phpbb_dispatcher->trigger_event('core.mcp_main_modify_fork_post_sql', compact($vars))); 1586 $db->sql_query('INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); 1587 $new_post_id = $db->sql_nextid(); 1588 1589 /** 1590 * Perform actions after forked topic is created. 1591 * 1592 * @event core.mcp_main_fork_sql_after 1593 * @var int new_topic_id The newly created topic ID 1594 * @var int to_forum_id The forum ID where the forked topic has been moved to 1595 * @var int new_post_id The newly created post ID 1596 * @var array row Post data 1597 * @since 3.2.4-RC1 1598 */ 1599 $vars = array( 1600 'new_topic_id', 1601 'to_forum_id', 1602 'new_post_id', 1603 'row', 1604 ); 1605 extract($phpbb_dispatcher->trigger_event('core.mcp_main_fork_sql_after', compact($vars))); 1606 1607 switch ($row['post_visibility']) 1608 { 1609 case ITEM_APPROVED: 1610 $total_posts++; 1611 break; 1612 case ITEM_UNAPPROVED: 1613 case ITEM_REAPPROVE: 1614 $total_posts_unapproved++; 1615 break; 1616 case ITEM_DELETED: 1617 $total_posts_softdeleted++; 1618 break; 1619 } 1620 1621 // Copy whether the topic is dotted 1622 markread('post', $to_forum_id, $new_topic_id, 0, $row['poster_id']); 1623 1624 if (!empty($search_type)) 1625 { 1626 $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); 1627 $search_mode = 'reply'; // After one we index replies 1628 } 1629 1630 // Copy Attachments 1631 if ($row['post_attachment']) 1632 { 1633 $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . ' 1634 WHERE post_msg_id = ' . (int) $row['post_id'] . ' 1635 AND topic_id = ' . (int) $topic_id . ' 1636 AND in_message = 0 1637 ORDER BY attach_id ASC'; 1638 $result = $db->sql_query($sql); 1639 1640 $sql_ary = array(); 1641 while ($attach_row = $db->sql_fetchrow($result)) 1642 { 1643 $sql_ary[] = array( 1644 'post_msg_id' => (int) $new_post_id, 1645 'topic_id' => (int) $new_topic_id, 1646 'in_message' => 0, 1647 'is_orphan' => (int) $attach_row['is_orphan'], 1648 'poster_id' => (int) $attach_row['poster_id'], 1649 'physical_filename' => (string) utf8_basename($attach_row['physical_filename']), 1650 'real_filename' => (string) utf8_basename($attach_row['real_filename']), 1651 'download_count' => (int) $attach_row['download_count'], 1652 'attach_comment' => (string) $attach_row['attach_comment'], 1653 'extension' => (string) $attach_row['extension'], 1654 'mimetype' => (string) $attach_row['mimetype'], 1655 'filesize' => (int) $attach_row['filesize'], 1656 'filetime' => (int) $attach_row['filetime'], 1657 'thumbnail' => (int) $attach_row['thumbnail'] 1658 ); 1659 } 1660 $db->sql_freeresult($result); 1661 1662 if (count($sql_ary)) 1663 { 1664 $db->sql_multi_insert(ATTACHMENTS_TABLE, $sql_ary); 1665 } 1666 } 1667 } 1668 1669 // Copy topic subscriptions to new topic 1670 $sql = 'SELECT user_id, notify_status 1671 FROM ' . TOPICS_WATCH_TABLE . ' 1672 WHERE topic_id = ' . $topic_id; 1673 $result = $db->sql_query($sql); 1674 1675 $sql_ary = array(); 1676 while ($row = $db->sql_fetchrow($result)) 1677 { 1678 $sql_ary[] = array( 1679 'topic_id' => (int) $new_topic_id, 1680 'user_id' => (int) $row['user_id'], 1681 'notify_status' => (int) $row['notify_status'], 1682 ); 1683 } 1684 $db->sql_freeresult($result); 1685 1686 if (count($sql_ary)) 1687 { 1688 $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary); 1689 } 1690 1691 // Copy bookmarks to new topic 1692 $sql = 'SELECT user_id 1693 FROM ' . BOOKMARKS_TABLE . ' 1694 WHERE topic_id = ' . $topic_id; 1695 $result = $db->sql_query($sql); 1696 1697 $sql_ary = array(); 1698 while ($row = $db->sql_fetchrow($result)) 1699 { 1700 $sql_ary[] = array( 1701 'topic_id' => (int) $new_topic_id, 1702 'user_id' => (int) $row['user_id'], 1703 ); 1704 } 1705 $db->sql_freeresult($result); 1706 1707 if (count($sql_ary)) 1708 { 1709 $db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary); 1710 } 1711 } 1712 1713 // Sync new topics, parent forums and board stats 1714 $sql = 'UPDATE ' . FORUMS_TABLE . ' 1715 SET forum_posts_approved = forum_posts_approved + ' . $total_posts . ', 1716 forum_posts_unapproved = forum_posts_unapproved + ' . $total_posts_unapproved . ', 1717 forum_posts_softdeleted = forum_posts_softdeleted + ' . $total_posts_softdeleted . ', 1718 forum_topics_approved = forum_topics_approved + ' . $total_topics . ', 1719 forum_topics_unapproved = forum_topics_unapproved + ' . $total_topics_unapproved . ', 1720 forum_topics_softdeleted = forum_topics_softdeleted + ' . $total_topics_softdeleted . ' 1721 WHERE forum_id = ' . $to_forum_id; 1722 $db->sql_query($sql); 1723 1724 if (!empty($counter)) 1725 { 1726 // Do only one query per user and not a query per post. 1727 foreach ($counter as $user_id => $count) 1728 { 1729 $sql = 'UPDATE ' . USERS_TABLE . ' 1730 SET user_posts = user_posts + ' . (int) $count . ' 1731 WHERE user_id = ' . (int) $user_id; 1732 $db->sql_query($sql); 1733 } 1734 } 1735 1736 sync('topic', 'topic_id', $new_topic_id_list); 1737 sync('forum', 'forum_id', $to_forum_id); 1738 1739 $config->increment('num_topics', count($new_topic_id_list), false); 1740 $config->increment('num_posts', $total_posts, false); 1741 1742 foreach ($new_topic_id_list as $topic_id => $new_topic_id) 1743 { 1744 $phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_FORK', false, array( 1745 'forum_id' => $to_forum_id, 1746 'topic_id' => $new_topic_id, 1747 $topic_row['forum_name'] 1748 )); 1749 } 1750 1751 $success_msg = (count($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS'; 1752 } 1753 else 1754 { 1755 $template->assign_vars(array( 1756 'S_FORUM_SELECT' => make_forum_select($to_forum_id, false, false, true, true, true), 1757 'S_CAN_LEAVE_SHADOW' => false, 1758 'ADDITIONAL_MSG' => $additional_msg) 1759 ); 1760 1761 confirm_box(false, 'FORK_TOPIC' . ((count($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); 1762 } 1763 1764 $redirect = $request->variable('redirect', "index.$phpEx"); 1765 $redirect = reapply_sid($redirect); 1766 1767 if (!$success_msg) 1768 { 1769 redirect($redirect); 1770 } 1771 else 1772 { 1773 $redirect_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id); 1774 meta_refresh(3, $redirect_url); 1775 $return_link = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect_url . '">', '</a>'); 1776 1777 if ($forum_id != $to_forum_id) 1778 { 1779 $return_link .= '<br /><br />' . sprintf($user->lang['RETURN_NEW_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $to_forum_id) . '">', '</a>'); 1780 } 1781 1782 trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link); 1783 } 1784 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |