| [ Index ] |
PHP Cross Reference of MyBB 1.6.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * MyBB 1.6 4 * Copyright 2010 MyBB Group, All Rights Reserved 5 * 6 * Website: http://mybb.com 7 * License: http://mybb.com/about/license 8 * 9 * $Id: class_moderation.php 5145 2010-07-30 21:30:51Z RyanGordon $ 10 */ 11 12 class Moderation 13 { 14 /** 15 * Close one or more threads 16 * 17 * @param array Thread IDs 18 * @return boolean true 19 */ 20 function close_threads($tids) 21 { 22 global $db, $plugins; 23 24 if(!is_array($tids)) 25 { 26 $tids = array($tids); 27 } 28 29 // Make sure we only have valid values 30 $tids = array_map('intval', $tids); 31 32 $plugins->run_hooks("class_moderation_close_threads", $tids); 33 34 $tid_list = implode(',', $tids); 35 36 $openthread = array( 37 "closed" => 1, 38 ); 39 $db->update_query("threads", $openthread, "tid IN ($tid_list) AND closed NOT LIKE 'moved|%'"); 40 41 return true; 42 } 43 44 /** 45 * Open one or more threads 46 * 47 * @param int Thread IDs 48 * @return boolean true 49 */ 50 51 function open_threads($tids) 52 { 53 global $db, $plugins; 54 55 if(!is_array($tids)) 56 { 57 $tids = array($tids); 58 } 59 60 // Make sure we only have valid values 61 $tids = array_map('intval', $tids); 62 63 $plugins->run_hooks("class_moderation_open_threads", $tids); 64 65 $tid_list = implode(',', $tids); 66 67 $closethread = array( 68 "closed" => 0, 69 ); 70 $db->update_query("threads", $closethread, "tid IN ($tid_list)"); 71 72 return true; 73 } 74 75 /** 76 * Stick one or more threads 77 * 78 * @param int Thread IDs 79 * @return boolean true 80 */ 81 function stick_threads($tids) 82 { 83 global $db, $plugins; 84 85 if(!is_array($tids)) 86 { 87 $tids = array($tids); 88 } 89 90 // Make sure we only have valid values 91 $tids = array_map('intval', $tids); 92 93 $plugins->run_hooks("class_moderation_stick_threads", $tids); 94 95 $tid_list = implode(',', $tids); 96 97 $stickthread = array( 98 "sticky" => 1, 99 ); 100 $db->update_query("threads", $stickthread, "tid IN ($tid_list)"); 101 102 return true; 103 } 104 105 /** 106 * Unstick one or more thread 107 * 108 * @param int Thread IDs 109 * @return boolean true 110 */ 111 function unstick_threads($tids) 112 { 113 global $db, $plugins; 114 115 if(!is_array($tids)) 116 { 117 $tids = array($tids); 118 } 119 120 // Make sure we only have valid values 121 $tids = array_map('intval', $tids); 122 123 $plugins->run_hooks("class_moderation_unstick_threads", $tids); 124 125 $tid_list = implode(',', $tids); 126 127 $unstickthread = array( 128 "sticky" => 0, 129 ); 130 $db->update_query("threads", $unstickthread, "tid IN ($tid_list)"); 131 132 return true; 133 } 134 135 /** 136 * Remove redirects that redirect to the specified thread 137 * 138 * @param int Thread ID of the thread 139 * @return boolean true 140 */ 141 function remove_redirects($tid) 142 { 143 global $db, $plugins; 144 145 $plugins->run_hooks("class_moderation_remove_redirects", $tid); 146 147 // Delete the redirects 148 $tid = intval($tid); 149 $db->delete_query("threads", "closed='moved|$tid'"); 150 151 return true; 152 } 153 154 /** 155 * Delete a thread 156 * 157 * @param int Thread ID of the thread 158 * @return boolean true 159 */ 160 function delete_thread($tid) 161 { 162 global $db, $cache, $plugins; 163 164 $tid = intval($tid); 165 $plugins->run_hooks("class_moderation_delete_thread_start", $tid); 166 167 $thread = get_thread($tid); 168 169 $userposts = array(); 170 171 // Find the pid, uid, visibility, and forum post count status 172 $query = $db->query(" 173 SELECT p.pid, p.uid, p.visible, f.usepostcounts 174 FROM ".TABLE_PREFIX."posts p 175 LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) 176 WHERE p.tid='{$tid}' 177 "); 178 $pids = array(); 179 $num_unapproved_posts = $num_approved_posts = 0; 180 while($post = $db->fetch_array($query)) 181 { 182 $pids[] = $post['pid']; 183 $usepostcounts = $post['usepostcounts']; 184 185 if(!function_exists("remove_attachments")) 186 { 187 require MYBB_ROOT."inc/functions_upload.php"; 188 } 189 190 // Remove attachments 191 remove_attachments($post['pid']); 192 193 // If the post is unapproved, count it! 194 if($post['visible'] == 0 || $thread['visible'] == 0) 195 { 196 $num_unapproved_posts++; 197 } 198 else 199 { 200 $num_approved_posts++; 201 202 // Count the post counts for each user to be subtracted 203 ++$userposts[$post['uid']]; 204 } 205 } 206 207 // Remove post count from users 208 if($usepostcounts != 0) 209 { 210 if(is_array($userposts)) 211 { 212 foreach($userposts as $uid => $subtract) 213 { 214 $db->update_query("users", array('postnum' => "postnum-{$subtract}"), "uid='".intval($uid)."'", 1, true); 215 } 216 } 217 } 218 // Delete posts and their attachments 219 if($pids) 220 { 221 $pids = implode(',', $pids); 222 $db->delete_query("posts", "pid IN ($pids)"); 223 $db->delete_query("attachments", "pid IN ($pids)"); 224 $db->delete_query("reportedposts", "pid IN ($pids)"); 225 } 226 227 // Implied counters for unapproved thread 228 if($thread['visible'] == 0) 229 { 230 $num_unapproved_posts += $num_approved_posts; 231 } 232 233 // Delete threads, redirects, subscriptions, polls, and poll votes 234 $db->delete_query("threads", "tid='$tid'"); 235 $db->delete_query("threads", "closed='moved|$tid'"); 236 $db->delete_query("threadsubscriptions", "tid='$tid'"); 237 $db->delete_query("polls", "tid='$tid'"); 238 $db->delete_query("pollvotes", "pid='".$thread['poll']."'"); 239 $db->delete_query("threadsread", "tid='$tid'"); 240 241 $updated_counters = array( 242 "posts" => "-{$num_approved_posts}", 243 "unapprovedposts" => "-{$num_unapproved_posts}" 244 ); 245 246 if($thread['visible'] == 1) 247 { 248 $updated_counters['threads'] = -1; 249 } 250 else 251 { 252 $updated_counters['unapprovedthreads'] = -1; 253 } 254 255 if(substr($thread['closed'], 0, 5) != "moved") 256 { 257 // Update forum count 258 update_forum_counters($thread['fid'], $updated_counters); 259 } 260 261 $plugins->run_hooks("class_moderation_delete_thread", $tid); 262 263 return true; 264 } 265 266 /** 267 * Delete a poll 268 * 269 * @param int Poll id 270 * @return boolean true 271 */ 272 function delete_poll($pid) 273 { 274 global $db, $plugins; 275 276 $pid = intval($pid); 277 278 $plugins->run_hooks("class_moderation_delete_poll", $pid); 279 280 $db->delete_query("polls", "pid='$pid'"); 281 $db->delete_query("pollvotes", "pid='$pid'"); 282 $pollarray = array( 283 'poll' => '0', 284 ); 285 $db->update_query("threads", $pollarray, "poll='$pid'"); 286 287 return true; 288 } 289 290 /** 291 * Approve one or more threads 292 * 293 * @param array Thread IDs 294 * @return boolean true 295 */ 296 function approve_threads($tids) 297 { 298 global $db, $cache, $plugins; 299 300 if(!is_array($tids)) 301 { 302 $tids = array($tids); 303 } 304 305 // Make sure we only have valid values 306 $tids = array_map('intval', $tids); 307 308 foreach($tids as $tid) 309 { 310 $thread = get_thread($tid); 311 if($thread['visible'] == 1 || !$thread['tid']) 312 { 313 continue; 314 } 315 $tid_list[] = $thread['tid']; 316 317 $forum = get_forum($thread['fid']); 318 319 $forum_counters[$forum['fid']]['num_threads']++; 320 $forum_counters[$forum['fid']]['num_posts'] += $thread['replies']+1; // Remove implied visible from count 321 322 if($forum['usepostcounts'] != 0) 323 { 324 // On approving thread restore user post counts 325 $query = $db->simple_select("posts", "COUNT(pid) as posts, uid", "tid='{$tid}' AND (visible='1' OR pid='{$thread['firstpost']}') AND uid > 0 GROUP BY uid"); 326 while($counter = $db->fetch_array($query)) 327 { 328 $db->update_query("users", array('postnum' => "postnum+{$counter['posts']}"), "uid='".$counter['uid']."'", 1, true); 329 } 330 } 331 $posts_to_approve[] = $thread['firstpost']; 332 } 333 334 if(is_array($tid_list)) 335 { 336 $tid_moved_list = ""; 337 $comma = ""; 338 foreach($tid_list as $tid) 339 { 340 $tid_moved_list .= "{$comma}'moved|{$tid}'"; 341 $comma = ","; 342 } 343 $tid_list = implode(',', $tid_list); 344 $approve = array( 345 "visible" => 1 346 ); 347 $db->update_query("threads", $approve, "tid IN ($tid_list) OR closed IN ({$tid_moved_list})"); 348 $db->update_query("posts", $approve, "pid IN (".implode(',', $posts_to_approve).")"); 349 350 $plugins->run_hooks("class_moderation_approve_threads", $tids); 351 352 if(is_array($forum_counters)) 353 { 354 foreach($forum_counters as $fid => $counters) 355 { 356 // Update stats 357 $update_array = array( 358 "threads" => "+{$counters['num_threads']}", 359 "unapprovedthreads" => "-{$counters['num_threads']}", 360 "posts" => "+{$counters['num_posts']}", 361 "unapprovedposts" => "-{$counters['num_posts']}" 362 ); 363 update_forum_counters($fid, $update_array); 364 } 365 } 366 } 367 return true; 368 } 369 370 /** 371 * Unapprove one or more threads 372 * 373 * @param array Thread IDs 374 * @return boolean true 375 */ 376 function unapprove_threads($tids) 377 { 378 global $db, $cache, $plugins; 379 380 if(!is_array($tids)) 381 { 382 $tids = array($tids); 383 } 384 385 // Make sure we only have valid values 386 $tids = array_map('intval', $tids); 387 388 $tid_list = implode(',', $tids); 389 $tid_moved_list = ""; 390 $comma = ""; 391 foreach($tids as $tid) 392 { 393 $tid_moved_list .= "{$comma}'moved|{$tid}'"; 394 $comma = ","; 395 } 396 397 foreach($tids as $tid) 398 { 399 $thread = get_thread($tid); 400 $forum = get_forum($thread['fid']); 401 402 if($thread['visible'] == 1) 403 { 404 $forum_counters[$forum['fid']]['num_threads']++; 405 $forum_counters[$forum['fid']]['num_posts'] += $thread['replies']+1; // Add implied invisible to count 406 407 // On unapproving thread update user post counts 408 if($forum['usepostcounts'] != 0) 409 { 410 $query = $db->simple_select("posts", "COUNT(pid) AS posts, uid", "tid='{$tid}' AND (visible='1' OR pid='{$thread['firstpost']}') AND uid > 0 GROUP BY uid"); 411 while($counter = $db->fetch_array($query)) 412 { 413 $db->update_query("users", array('postnum' => "postnum-{$counter['posts']}"), "uid='".$counter['uid']."'", 1, true); 414 } 415 } 416 } 417 $posts_to_unapprove[] = $thread['firstpost']; 418 } 419 420 $approve = array( 421 "visible" => 0 422 ); 423 $db->update_query("threads", $approve, "tid IN ($tid_list) OR closed IN ({$tid_moved_list})"); 424 $db->update_query("posts", $approve, "pid IN (".implode(',', $posts_to_unapprove).")"); 425 426 $plugins->run_hooks("class_moderation_unapprove_threads", $tids); 427 428 if(is_array($forum_counters)) 429 { 430 foreach($forum_counters as $fid => $counters) 431 { 432 // Update stats 433 $update_array = array( 434 "threads" => "-{$counters['num_threads']}", 435 "unapprovedthreads" => "+{$counters['num_threads']}", 436 "posts" => "-{$counters['num_posts']}", 437 "unapprovedposts" => "+{$counters['num_posts']}" 438 ); 439 update_forum_counters($fid, $update_array); 440 } 441 } 442 443 return true; 444 } 445 446 /** 447 * Delete a specific post 448 * 449 * @param int Post ID 450 * @return boolean true 451 */ 452 function delete_post($pid) 453 { 454 global $db, $cache, $plugins; 455 456 $plugins->run_hooks_by_ref("class_moderation_delete_post_start", $pid); 457 // Get pid, uid, fid, tid, visibility, forum post count status of post 458 $pid = intval($pid); 459 $query = $db->query(" 460 SELECT p.pid, p.uid, p.fid, p.tid, p.visible, f.usepostcounts, t.visible as threadvisible 461 FROM ".TABLE_PREFIX."posts p 462 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 463 LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) 464 WHERE p.pid='$pid' 465 "); 466 $post = $db->fetch_array($query); 467 // If post counts enabled in this forum and it hasn't already been unapproved, remove 1 468 if($post['usepostcounts'] != 0 && $post['visible'] != 0 && $post['threadvisible'] != 0) 469 { 470 $db->update_query("users", array("postnum" => "postnum-1"), "uid='{$post['uid']}'", 1, true); 471 } 472 473 if(!function_exists("remove_attachments")) 474 { 475 require MYBB_ROOT."inc/functions_upload.php"; 476 } 477 478 // Remove attachments 479 remove_attachments($pid); 480 481 // Delete the post 482 $db->delete_query("posts", "pid='$pid'"); 483 484 // Remove any reports attached to this post 485 $db->delete_query("reportedposts", "pid='$pid'"); 486 487 $num_unapproved_posts = $num_approved_posts = 0; 488 // Update unapproved post count 489 if($post['visible'] == 0 || $post['threadvisible'] == 0) 490 { 491 ++$num_unapproved_posts; 492 } 493 else 494 { 495 ++$num_approved_posts; 496 } 497 $plugins->run_hooks("class_moderation_delete_post", $post['pid']); 498 499 // Update stats 500 $update_array = array( 501 "replies" => "-{$num_approved_posts}", 502 "unapprovedposts" => "-{$num_unapproved_posts}" 503 ); 504 update_thread_counters($post['tid'], $update_array); 505 506 // Update stats 507 $update_array = array( 508 "posts" => "-{$num_approved_posts}", 509 "unapprovedposts" => "-{$num_unapproved_posts}" 510 ); 511 512 update_forum_counters($post['fid'], $update_array); 513 514 return true; 515 } 516 517 /** 518 * Merge posts within thread 519 * 520 * @param array Post IDs to be merged 521 * @param int Thread ID (Set to 0 if posts from multiple threads are 522 * selected) 523 * @return int ID of the post into which all other posts are merged 524 */ 525 function merge_posts($pids, $tid=0, $sep="new_line") 526 { 527 global $db, $plugins; 528 529 // Make sure we only have valid values 530 $pids = array_map('intval', $pids); 531 $tid = intval($tid); 532 533 $pidin = implode(',', $pids); 534 $attachment_count = 0; 535 536 $first = 1; 537 // Get the messages to be merged 538 $query = $db->query(" 539 SELECT p.pid, p.uid, p.fid, p.tid, p.visible, p.message, f.usepostcounts, t.visible AS threadvisible, t.replies AS threadreplies, t.firstpost AS threadfirstpost, t.unapprovedposts AS threadunapprovedposts 540 FROM ".TABLE_PREFIX."posts p 541 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 542 LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) 543 WHERE p.pid IN($pidin) 544 ORDER BY p.dateline ASC 545 "); 546 $num_unapproved_posts = $num_approved_posts = 0; 547 $message = ''; 548 while($post = $db->fetch_array($query)) 549 { 550 if($first == 1) 551 { // all posts will be merged into this one 552 $masterpid = $post['pid']; 553 $message = $post['message']; 554 $fid = $post['fid']; 555 $mastertid = $post['tid']; 556 $first = 0; 557 } 558 else 559 { 560 // these are the selected posts 561 if($sep == "new_line") 562 { 563 $message .= "\n\n {$post['message']}"; 564 } 565 else 566 { 567 $message .= "[hr]{$post['message']}"; 568 } 569 570 if($post['visible'] == 1 && $post['threadvisible'] == 1) 571 { 572 // Subtract 1 approved post from post's thread 573 if(!$thread_counters[$post['tid']]['replies']) 574 { 575 $thread_counters[$post['tid']]['replies'] = $post['threadreplies']; 576 } 577 --$thread_counters[$post['tid']]['replies']; 578 // Subtract 1 approved post from post's forum 579 if(!isset($forum_counters[$post['fid']]['num_posts'])) 580 { 581 $forum_counters[$post['fid']]['num_posts'] = 0; 582 } 583 --$forum_counters[$post['fid']]['num_posts']; 584 // Subtract 1 from user's post count 585 if($post['usepostcounts'] != 0) 586 { 587 // Update post count of the user of the merged posts 588 $db->update_query("users", array("postnum" => "postnum-1"), "uid='{$post['uid']}'", 1, true); 589 } 590 } 591 elseif($post['visible'] == 0) 592 { 593 // Subtract 1 unapproved post from post's thread 594 if(!$thread_counters[$post['tid']]['unapprovedposts']) 595 { 596 $thread_counters[$post['tid']]['unapprovedposts'] = $post['threadunapprovedposts']; 597 } 598 --$thread_counters[$post['tid']]['unapprovedposts']; 599 // Subtract 1 unapproved post from post's forum 600 if(!isset($forum_counters[$post['fid']]['unapprovedposts'])) 601 { 602 $forum_counters[$post['fid']]['unapprovedposts'] = 0; 603 } 604 --$forum_counters[$post['fid']]['unapprovedposts']; 605 } 606 } 607 } 608 609 // Get lastpost pid to check if we're merging a post that is on the lastpost info 610 $query = $db->simple_select("posts", "pid", "tid = '{$post['tid']}'", array('order_by' => 'dateline', 'order_dir' => 'desc', 'limit' => '1')); 611 $lastpostpid = $db->fetch_field($query, 'pid'); 612 613 $query2 = $db->simple_select("attachments", "COUNT(aid) as count", "pid IN({$pidin}) AND visible='1'"); 614 $attachment_count = $db->fetch_field($query2, "count"); 615 616 $db->update_query("threads", array("attachmentcount" => $attachment_count), "tid = '{$mastertid}'"); 617 618 // Update the message 619 $mergepost = array( 620 "message" => $db->escape_string($message), 621 ); 622 $db->update_query("posts", $mergepost, "pid = '{$masterpid}'"); 623 624 // Delete the extra posts 625 $db->delete_query("posts", "pid IN({$pidin}) AND pid != '{$masterpid}'"); 626 // Update pid for attachments 627 628 $mergepost2 = array( 629 "pid" => $masterpid, 630 ); 631 $db->update_query("attachments", $mergepost2, "pid IN({$pidin})"); 632 633 // If the first post of a thread is merged out, the thread should be deleted 634 $query = $db->simple_select("threads", "tid, fid, visible", "firstpost IN({$pidin}) AND firstpost != '{$masterpid}'"); 635 while($thread = $db->fetch_array($query)) 636 { 637 $this->delete_thread($thread['tid']); 638 // Subtract 1 thread from the forum's stats 639 if($thread['visible']) 640 { 641 if(!isset($forum_counters[$thread['fid']]['threads'])) 642 { 643 $forum_counters[$thread['fid']]['threads'] = 0; 644 } 645 --$forum_counters[$thread['fid']]['threads']; 646 } 647 else 648 { 649 if(!isset($forum_counters[$thread['fid']]['unapprovedthreads'])) 650 { 651 $forum_counters[$thread['fid']]['unapprovedthreads'] = 0; 652 } 653 --$forum_counters[$thread['fid']]['unapprovedthreads']; 654 } 655 } 656 657 $arguments = array("pids" => $pids, "tid" => $tid); 658 $plugins->run_hooks("class_moderation_merge_posts", $arguments); 659 660 if(is_array($thread_counters)) 661 { 662 foreach($thread_counters as $tid => $counters) 663 { 664 $db->update_query("threads", $counters, "tid='{$tid}'"); 665 666 update_thread_data($tid); 667 } 668 } 669 670 update_thread_data($mastertid); 671 672 update_forum_lastpost($fid); 673 674 if(is_array($forum_counters)) 675 { 676 foreach($forum_counters as $fid => $counters) 677 { 678 $updated_forum_stats = array( 679 'posts' => signed($counters['num_posts']), 680 'unapprovedposts' => signed($counters['unapprovedposts']), 681 'threads' => signed($counters['threads']), 682 ); 683 update_forum_counters($fid, $updated_forum_stats); 684 } 685 } 686 687 return $masterpid; 688 } 689 690 /** 691 * Move/copy thread 692 * 693 * @param int Thread to be moved 694 * @param int Destination forum 695 * @param string Method of movement (redirect, copy, move) 696 * @param int Expiry timestamp for redirect 697 * @return int Thread ID 698 */ 699 function move_thread($tid, $new_fid, $method="redirect", $redirect_expire=0) 700 { 701 global $db, $plugins; 702 703 // Get thread info 704 $tid = intval($tid); 705 $new_fid = intval($new_fid); 706 $redirect_expire = intval($redirect_expire); 707 708 $thread = get_thread($tid, true); 709 $newforum = get_forum($new_fid); 710 $fid = $thread['fid']; 711 $forum = get_forum($fid); 712 713 $num_threads = $num_unapproved_threads = $num_posts = $num_unapproved_threads = 0; 714 switch($method) 715 { 716 case "redirect": // move (and leave redirect) thread 717 $arguments = array("tid" => $tid, "new_fid" => $new_fid); 718 $plugins->run_hooks("class_moderation_move_thread_redirect", $arguments); 719 720 if($thread['visible'] == 1) 721 { 722 $num_threads++; 723 $num_posts = $thread['replies']+1; 724 } 725 else 726 { 727 $num_unapproved_threads++; 728 // Implied forum unapproved count for unapproved threads 729 $num_unapproved_posts = $thread['replies']+1; 730 } 731 732 $num_unapproved_posts += $thread['unapprovedposts']; 733 734 $db->delete_query("threads", "closed='moved|$tid' AND fid='$new_fid'"); 735 $changefid = array( 736 "fid" => $new_fid, 737 ); 738 $db->update_query("threads", $changefid, "tid='$tid'"); 739 $db->update_query("posts", $changefid, "tid='$tid'"); 740 741 // If the thread has a prefix and the destination forum doesn't accept that prefix, remove the prefix 742 if($thread['prefix'] != 0) 743 { 744 $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(CONCAT(',',forums,',') LIKE '%,$new_fid,%' OR forums='-1') AND pid='".$thread['prefix']."'"); 745 if($db->fetch_field($query, "num_prefixes") == 0) 746 { 747 $sqlarray = array( 748 "prefix" => 0, 749 ); 750 $db->update_query("threads", $sqlarray, "tid='$tid'"); 751 } 752 } 753 754 $threadarray = array( 755 "fid" => $thread['fid'], 756 "subject" => $db->escape_string($thread['subject']), 757 "icon" => $thread['icon'], 758 "uid" => $thread['uid'], 759 "username" => $db->escape_string($thread['username']), 760 "dateline" => $thread['dateline'], 761 "lastpost" => $thread['lastpost'], 762 "lastposteruid" => $thread['lastposteruid'], 763 "lastposter" => $db->escape_string($thread['lastposter']), 764 "views" => 0, 765 "replies" => 0, 766 "closed" => "moved|$tid", 767 "sticky" => $thread['sticky'], 768 "visible" => $thread['visible'], 769 "notes" => '' 770 ); 771 $redirect_tid = $db->insert_query("threads", $threadarray); 772 if($redirect_expire) 773 { 774 $this->expire_thread($redirect_tid, $redirect_expire); 775 } 776 777 // If we're moving back to a forum where we left a redirect, delete the rediect 778 $query = $db->simple_select("threads", "tid", "closed LIKE 'moved|".intval($tid)."' AND fid='".intval($new_fid)."'"); 779 while($movedthread = $db->fetch_array($query)) 780 { 781 $db->delete_query("threads", "tid='".intval($movedthread['tid'])."'", 1); 782 } 783 break; 784 case "copy":// copy thread 785 786 $threadarray = array( 787 "fid" => $new_fid, 788 "subject" => $db->escape_string($thread['subject']), 789 "icon" => $thread['icon'], 790 "uid" => $thread['uid'], 791 "username" => $db->escape_string($thread['username']), 792 "dateline" => $thread['dateline'], 793 "firstpost" => 0, 794 "lastpost" => $thread['lastpost'], 795 "lastposteruid" => $thread['lastposteruid'], 796 "lastposter" => $db->escape_string($thread['lastposter']), 797 "views" => $thread['views'], 798 "replies" => $thread['replies'], 799 "closed" => $thread['closed'], 800 "sticky" => $thread['sticky'], 801 "visible" => $thread['visible'], 802 "unapprovedposts" => $thread['unapprovedposts'], 803 "attachmentcount" => $thread['attachmentcount'], 804 "prefix" => $thread['prefix'], 805 "notes" => '' 806 ); 807 808 if($thread['visible'] == 1) 809 { 810 ++$num_threads; 811 $num_posts = $thread['replies']+1; 812 813 // Fetch count of unapproved posts in this thread 814 $query = $db->simple_select("posts", "COUNT(pid) AS unapproved", "tid='{$thread['tid']}' AND visible=0"); 815 $num_unapproved_posts = $db->fetch_field($query, "unapproved"); 816 817 } 818 else 819 { 820 $num_unapproved_threads++; 821 $num_unapproved_posts = $thread['replies']+1; 822 } 823 824 $arguments = array("tid" => $tid, "new_fid" => $new_fid); 825 $plugins->run_hooks("class_moderation_copy_thread", $arguments); 826 827 // If the thread has a prefix and the destination forum doesn't accept that prefix, don't copy the prefix 828 if($threadarray['prefix'] != 0) 829 { 830 $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(CONCAT(',',forums,',') LIKE '%,$new_fid,%' OR forums='-1') AND pid='".$thread['prefix']."'"); 831 if($db->fetch_field($query, "num_prefixes") == 0) 832 { 833 $threadarray['prefix'] = 0; 834 } 835 } 836 837 $newtid = $db->insert_query("threads", $threadarray); 838 839 if($thread['poll'] != 0) 840 { 841 $query = $db->simple_select("polls", "*", "tid = '{$thread['tid']}'"); 842 $poll = $db->fetch_array($query); 843 844 $poll_array = array( 845 'tid' => $newtid, 846 'question' => $db->escape_string($poll['question']), 847 'dateline' => $poll['dateline'], 848 'options' => $db->escape_string($poll['options']), 849 'votes' => $poll['votes'], 850 'numoptions' => $poll['numoptions'], 851 'numvotes' => $poll['numvotes'], 852 'timeout' => $poll['timeout'], 853 'closed' => $poll['closed'], 854 'multiple' => $poll['multiple'], 855 'public' => $poll['public'] 856 ); 857 $new_pid = $db->insert_query("polls", $poll_array); 858 859 $query = $db->simple_select("pollvotes", "*", "pid = '{$poll['pid']}'"); 860 while($pollvote = $db->fetch_array($query)) 861 { 862 $pollvote_array = array( 863 'pid' => $new_pid, 864 'uid' => $pollvote['uid'], 865 'voteoption' => $pollvote['voteoption'], 866 'dateline' => $pollvote['dateline'], 867 ); 868 $db->insert_query("pollvotes", $pollvote_array); 869 } 870 871 $db->update_query("threads", array('poll' => $new_pid), "tid='{$newtid}'"); 872 } 873 874 $query = $db->simple_select("posts", "*", "tid = '{$thread['tid']}'"); 875 while($post = $db->fetch_array($query)) 876 { 877 $post_array = array( 878 'tid' => $newtid, 879 'fid' => $new_fid, 880 'subject' => $db->escape_string($post['subject']), 881 'icon' => $post['icon'], 882 'uid' => $post['uid'], 883 'username' => $db->escape_string($post['username']), 884 'dateline' => $post['dateline'], 885 'ipaddress' => $post['ipaddress'], 886 'includesig' => $post['includesig'], 887 'smilieoff' => $post['smilieoff'], 888 'edituid' => $post['edituid'], 889 'edittime' => $post['edittime'], 890 'visible' => $post['visible'], 891 'message' => $db->escape_string($post['message']), 892 ); 893 $pid = $db->insert_query("posts", $post_array); 894 895 // Properly set our new firstpost in our new thread 896 if($thread['firstpost'] == $post['pid']) 897 { 898 $db->update_query("threads", array('firstpost' => $pid), "tid='{$newtid}'"); 899 } 900 901 // Insert attachments for this post 902 $query2 = $db->simple_select("attachments", "*", "pid = '{$post['pid']}'"); 903 while($attachment = $db->fetch_array($query2)) 904 { 905 $attachment_array = array( 906 'pid' => $pid, 907 'posthash' => $db->escape_string($attachment['posthash']), 908 'uid' => $attachment['uid'], 909 'filename' => $db->escape_string($attachment['filename']), 910 'filetype' => $attachment['filetype'], 911 'filesize' => $attachment['filesize'], 912 'attachname' => $attachment['attachname'], 913 'downloads' => $attachment['downloads'], 914 'visible' => $attachment['visible'], 915 'thumbnail' => $attachment['thumbnail'] 916 ); 917 $new_aid = $db->insert_query("attachments", $attachment_array); 918 919 $post['message'] = str_replace("[attachment={$attachment['aid']}]", "[attachment={$new_aid}]", $post['message']); 920 } 921 922 if(strpos($post['message'], "[attachment=") !== false) 923 { 924 $db->update_query("posts", array('message' => $db->escape_string($post['message'])), "pid='{$pid}'"); 925 } 926 } 927 928 update_thread_data($newtid); 929 930 $the_thread = $newtid; 931 break; 932 default: 933 case "move": // plain move thread 934 $arguments = array("tid" => $tid, "new_fid" => $new_fid); 935 $plugins->run_hooks("class_moderation_move_simple", $arguments); 936 937 if($thread['visible'] == 1) 938 { 939 $num_threads++; 940 $num_posts = $thread['replies']+1; 941 } 942 else 943 { 944 $num_unapproved_threads++; 945 // Implied forum unapproved count for unapproved threads 946 $num_unapproved_posts = $thread['replies']+1; 947 } 948 949 $num_unapproved_posts = $thread['unapprovedposts']; 950 951 $sqlarray = array( 952 "fid" => $new_fid, 953 ); 954 $db->update_query("threads", $sqlarray, "tid='$tid'"); 955 $db->update_query("posts", $sqlarray, "tid='$tid'"); 956 957 // If the thread has a prefix and the destination forum doesn't accept that prefix, remove the prefix 958 if($thread['prefix'] != 0) 959 { 960 $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(CONCAT(',',forums,',') LIKE '%,$new_fid,%' OR forums='-1') AND pid='".$thread['prefix']."'"); 961 if($db->fetch_field($query, "num_prefixes") == 0) 962 { 963 $sqlarray = array( 964 "prefix" => 0, 965 ); 966 $db->update_query("threads", $sqlarray, "tid='$tid'"); 967 } 968 } 969 970 // If we're moving back to a forum where we left a redirect, delete the rediect 971 $query = $db->simple_select("threads", "tid", "closed LIKE 'moved|".intval($tid)."' AND fid='".intval($new_fid)."'"); 972 while($movedthread = $db->fetch_array($query)) 973 { 974 $db->delete_query("threads", "tid='".intval($movedthread['tid'])."'", 1); 975 } 976 break; 977 } 978 979 // Do post count changes if changing between countable and non-countable forums 980 $query = $db->query(" 981 SELECT COUNT(p.pid) AS posts, u.uid, p.visible 982 FROM ".TABLE_PREFIX."posts p 983 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) 984 WHERE tid='$tid' 985 GROUP BY u.uid, p.visible 986 ORDER BY posts DESC 987 "); 988 while($posters = $db->fetch_array($query)) 989 { 990 $pcount = ""; 991 if($forum['usepostcounts'] == 1 && $newforum['usepostcounts'] == 0 && $posters['visible'] == 1) 992 { 993 $pcount = "-{$posters['posts']}"; 994 } 995 else if($forum['usepostcounts'] == 0 && $newforum['userpostcounts'] == 1 && $posters['visible'] == 1) 996 { 997 $pcount = "+{$posters['posts']}"; 998 } 999 1000 if(!empty($pcount)) 1001 { 1002 $db->update_query("users", array("postnum" => "postnum{$pcount}"), "uid='{$posters['uid']}'", 1, true); 1003 } 1004 } 1005 1006 // Update forum counts 1007 $update_array = array( 1008 "threads" => "+{$num_threads}", 1009 "unapprovedthreads" => "+{$num_unapproved_threads}", 1010 "posts" => "+{$num_posts}", 1011 "unapprovedposts" => "+{$num_unapproved_posts}" 1012 ); 1013 update_forum_counters($new_fid, $update_array); 1014 1015 if($method != "copy") 1016 { 1017 $update_array = array( 1018 "threads" => "-{$num_threads}", 1019 "unapprovedthreads" => "-{$num_unapproved_threads}", 1020 "posts" => "-{$num_posts}", 1021 "unapprovedposts" => "-{$num_unapproved_posts}" 1022 ); 1023 update_forum_counters($fid, $update_array); 1024 } 1025 1026 if(isset($newtid)) 1027 { 1028 return $newtid; 1029 } 1030 else 1031 { 1032 // Remove thread subscriptions for the users who no longer have permission to view the thread 1033 $this->remove_thread_subscriptions($tid, false, $new_fid); 1034 1035 return $tid; 1036 } 1037 } 1038 1039 /** 1040 * Merge one thread into another 1041 * 1042 * @param int Thread that will be merged into destination 1043 * @param int Destination thread 1044 * @param string New thread subject 1045 * @return boolean true 1046 */ 1047 function merge_threads($mergetid, $tid, $subject) 1048 { 1049 global $db, $mybb, $mergethread, $thread, $plugins; 1050 1051 $mergetid = intval($mergetid); 1052 $tid = intval($tid); 1053 1054 if(!isset($mergethread['tid']) || $mergethread['tid'] != $mergetid) 1055 { 1056 $query = $db->simple_select("threads", "*", "tid='{$mergetid}'"); 1057 $mergethread = $db->fetch_array($query); 1058 } 1059 if(!isset($thread['tid']) || $thread['tid'] != $tid) 1060 { 1061 $query = $db->simple_select("threads", "*", "tid='{$tid}'"); 1062 $thread = $db->fetch_array($query); 1063 } 1064 1065 $pollsql = ''; 1066 if($mergethread['poll']) 1067 { 1068 $pollsql['poll'] = $mergethread['poll']; 1069 $sqlarray = array( 1070 "tid" => $tid, 1071 ); 1072 $db->update_query("polls", $sqlarray, "tid='".intval($mergethread['tid'])."'"); 1073 } 1074 else 1075 { 1076 $query = $db->simple_select("threads", "*", "poll='{$mergethread['poll']}' AND tid != '{$mergetid}'"); 1077 $pollcheck = $db->fetch_array($query); 1078 if(!$pollcheck['poll']) 1079 { 1080 $db->delete_query("polls", "pid='{$mergethread['poll']}'"); 1081 $db->delete_query("pollvotes", "pid='{$mergethread['poll']}'"); 1082 } 1083 } 1084 1085 $subject = $db->escape_string($subject); 1086 1087 $sqlarray = array( 1088 "tid" => $tid, 1089 "fid" => $thread['fid'], 1090 "replyto" => 0, 1091 "visible" => $mergethread['visible'], 1092 ); 1093 $db->update_query("posts", $sqlarray, "tid='{$mergetid}'"); 1094 1095 $pollsql['subject'] = $subject; 1096 $db->update_query("threads", $pollsql, "tid='{$tid}'"); 1097 $sqlarray = array( 1098 "closed" => "moved|{$tid}", 1099 ); 1100 $db->update_query("threads", $sqlarray, "closed='moved|{$mergetid}'"); 1101 $sqlarray = array( 1102 "tid" => $tid, 1103 ); 1104 $db->update_query("threadsubscriptions", $sqlarray, "tid='{$mergetid}'"); 1105 update_first_post($tid); 1106 1107 $arguments = array("mergetid" => $mergetid, "tid" => $tid, "subject" => $subject); 1108 $plugins->run_hooks("class_moderation_merge_threads", $arguments); 1109 1110 $this->delete_thread($mergetid); 1111 1112 // In some cases the thread we may be merging with may cause us to have a new firstpost if it is an older thread 1113 // Therefore resync the visible field to make sure they're the same if they're not 1114 $query = $db->simple_select("posts", "pid, visible", "tid='{$tid}'", array('order_by' => 'dateline', 'order_dir' => 'asc', 'limit' => 1)); 1115 $new_firstpost = $db->fetch_array($query); 1116 if($thread['visible'] != $new_firstpost['visible']) 1117 { 1118 $db->update_query("posts", array('visible' => $thread['visible']), "pid='{$new_firstpost['pid']}'"); 1119 $mergethread['visible'] = $thread['visible']; 1120 } 1121 1122 $updated_stats = array( 1123 "replies" => '+'.($mergethread['replies']+1), 1124 "attachmentcount" => "+{$mergethread['attachmentcount']}", 1125 "unapprovedposts" => "+{$mergethread['unapprovedposts']}" 1126 ); 1127 update_thread_counters($tid, $updated_stats); 1128 1129 // Thread is not in current forum 1130 if($mergethread['fid'] != $thread['fid']) 1131 { 1132 // If new thread is unapproved, implied counter comes in to effect 1133 if($thread['visible'] == 0 || $mergethread['visible'] == 0) 1134 { 1135 $updated_stats = array( 1136 "unapprovedposts" => '+'.($mergethread['replies']+1+$mergethread['unapprovedposts']) 1137 ); 1138 } 1139 else 1140 { 1141 $updated_stats = array( 1142 "posts" => '+'.($mergethread['replies']+1), 1143 "unapprovedposts" => "+{$mergethread['unapprovedposts']}" 1144 ); 1145 } 1146 update_forum_counters($thread['fid'], $updated_stats); 1147 1148 // If old thread is unapproved, implied counter comes in to effect 1149 if($mergethread['visible'] == 0) 1150 { 1151 $updated_stats = array( 1152 "unapprovedposts" => '-'.($mergethread['replies']+1+$mergethread['unapprovedposts']) 1153 ); 1154 } 1155 else 1156 { 1157 $updated_stats = array( 1158 "posts" => '-'.($mergethread['replies']+1), 1159 "unapprovedposts" => "-{$mergethread['unapprovedposts']}" 1160 ); 1161 } 1162 update_forum_counters($mergethread['fid'], $updated_stats); 1163 } 1164 // If we're in the same forum we need to at least update the last post information 1165 else 1166 { 1167 update_forum_lastpost($thread['fid']); 1168 } 1169 return true; 1170 } 1171 1172 /** 1173 * Split posts into a new/existing thread 1174 * 1175 * @param array PIDs of posts to split 1176 * @param int Original thread ID (this is only used as a base for the new 1177 * thread; it can be set to 0 when the posts specified are coming from more 1178 * than 1 thread) 1179 * @param int Destination forum 1180 * @param string New thread subject 1181 * @param int TID if moving into existing thread 1182 * @return int New thread ID 1183 */ 1184 function split_posts($pids, $tid, $moveto, $newsubject, $destination_tid=0) 1185 { 1186 global $db, $thread, $plugins; 1187 1188 $tid = intval($tid); 1189 $moveto = intval($moveto); 1190 $newtid = intval($destination_tid); 1191 1192 // Get forum infos 1193 $query = $db->simple_select("forums", "fid, usepostcounts, posts, threads, unapprovedposts, unapprovedthreads"); 1194 while($forum = $db->fetch_array($query)) 1195 { 1196 $forum_cache[$forum['fid']] = $forum; 1197 } 1198 1199 // Make sure we only have valid values 1200 $pids = array_map('intval', $pids); 1201 1202 $pids_list = implode(',', $pids); 1203 1204 // Get the icon for the first split post 1205 $query = $db->simple_select("posts", "icon", "pid=".intval($pids[0])); 1206 $icon = $db->fetch_array($query); 1207 1208 if($destination_tid == 0) 1209 { 1210 // Splitting into a new thread 1211 $thread = get_thread($tid); 1212 // Create the new thread 1213 $newsubject = $db->escape_string($newsubject); 1214 $query = array( 1215 "fid" => $moveto, 1216 "subject" => $newsubject, 1217 "icon" => intval($icon['icon']), 1218 "uid" => intval($thread['uid']), 1219 "username" => $db->escape_string($thread['username']), 1220 "dateline" => intval($thread['dateline']), 1221 "lastpost" => intval($thread['lastpost']), 1222 "lastposter" => $db->escape_string($thread['lastposter']), 1223 "replies" => count($pids)-1, 1224 "visible" => 1, 1225 "notes" => '' 1226 ); 1227 $newtid = $db->insert_query("threads", $query); 1228 1229 $forum_counters[$moveto]['threads'] = $forum_cache[$moveto]['threads']; 1230 ++$forum_counters[$moveto]['threads']; 1231 } 1232 1233 // Get attachment counts for each post 1234 /*$query = $db->simple_select("attachments", "COUNT(aid) as count, pid", "pid IN ($pids_list)"); 1235 $query = $db->query(" 1236 SELECT COUNT(aid) as count, p.pid, 1237 "); 1238 $attachment_sum = 0; 1239 while($attachment = $db->fetch_array($query)) 1240 { 1241 $attachments[$attachment['pid']] = $attachment['count']; 1242 $attachment_sum += $attachment['count']; 1243 } 1244 $thread_counters[$newtid]['attachmentcount'] = '+'.$attachment_sum;*/ 1245 1246 // Get selected posts before moving forums to keep old fid 1247 //$original_posts_query = $db->simple_select("posts", "fid, visible, pid", "pid IN ($pids_list)"); 1248 $original_posts_query = $db->query(" 1249 SELECT p.pid, p.tid, p.fid, p.visible, p.uid, t.visible as threadvisible, t.replies as threadreplies, t.unapprovedposts as threadunapprovedposts, t.attachmentcount as threadattachmentcount, COUNT(a.aid) as postattachmentcount 1250 FROM ".TABLE_PREFIX."posts p 1251 LEFT JOIN ".TABLE_PREFIX."threads t ON (p.tid=t.tid) 1252 LEFT JOIN ".TABLE_PREFIX."attachments a ON (a.pid=p.pid) 1253 WHERE p.pid IN ($pids_list) 1254 GROUP BY p.pid, p.tid, p.fid, p.visible, p.uid, t.visible, t.replies, t.unapprovedposts,t.attachmentcount 1255 "); 1256 1257 // Move the selected posts over 1258 $sqlarray = array( 1259 "tid" => $newtid, 1260 "fid" => $moveto, 1261 "replyto" => 0 1262 ); 1263 $db->update_query("posts", $sqlarray, "pid IN ($pids_list)"); 1264 1265 // Get posts being merged 1266 while($post = $db->fetch_array($original_posts_query)) 1267 { 1268 if($post['visible'] == 1) 1269 { 1270 // Modify users' post counts 1271 if($forum_cache[$post['fid']]['usepostcounts'] == 1 && $forum_cache[$moveto]['usepostcounts'] == 0) 1272 { 1273 // Moving into a forum that doesn't count post counts 1274 if(!isset($user_counters[$post['uid']])) 1275 { 1276 $user_counters[$post['uid']] = 0; 1277 } 1278 --$user_counters[$post['uid']]; 1279 } 1280 elseif($forum_cache[$post['fid']]['usepostcounts'] == 0 && $forum_cache[$moveto]['usepostcounts'] == 1) 1281 { 1282 // Moving into a forum that does count post counts 1283 if(!isset($user_counters[$post['uid']])) 1284 { 1285 $user_counters[$post['uid']] = 0; 1286 } 1287 ++$user_counters[$post['uid']]; 1288 } 1289 1290 // Subtract 1 from the old thread's replies 1291 if(!isset($thread_counters[$post['tid']]['replies'])) 1292 { 1293 $thread_counters[$post['tid']]['replies'] = $post['threadreplies']; 1294 } 1295 --$thread_counters[$post['tid']]['replies']; 1296 1297 // Add 1 to the new thread's replies 1298 ++$thread_counters[$newtid]['replies']; 1299 1300 if($moveto != $post['fid']) 1301 { 1302 // Only need to change forum info if the old forum is different from new forum 1303 // Subtract 1 from the old forum's posts 1304 if(!isset($forum_counters[$post['fid']]['posts'])) 1305 { 1306 $forum_counters[$post['fid']]['posts'] = $forum_cache[$post['fid']]['posts']; 1307 } 1308 --$forum_counters[$post['fid']]['posts']; 1309 // Add 1 to the new forum's posts 1310 if(!isset($forum_counters[$moveto]['posts'])) 1311 { 1312 $forum_counters[$moveto]['posts'] = $forum_cache[$moveto]['posts']; 1313 } 1314 ++$forum_counters[$moveto]['posts']; 1315 } 1316 1317 } 1318 elseif($post['visible'] == 0) 1319 { 1320 // Unapproved post 1321 // Subtract 1 from the old thread's unapproved posts 1322 if(!isset($thread_counters[$post['tid']]['unapprovedposts'])) 1323 { 1324 $thread_counters[$post['tid']]['unapprovedposts'] = $post['threadunapprovedposts']; 1325 } 1326 --$thread_counters[$post['tid']]['unapprovedposts']; 1327 1328 // Add 1 to the new thread's unapproved posts 1329 ++$thread_counters[$newtid]['unapprovedposts']; 1330 1331 if($moveto != $post['fid']) 1332 { 1333 // Only need to change forum info if the old forum is different from new forum 1334 // Subtract 1 from the old forum's unapproved posts 1335 if(!isset($forum_counters[$post['fid']]['unapprovedposts'])) 1336 { 1337 $forum_counters[$post['fid']]['unapprovedposts'] = $forum_cache[$post['fid']]['unapprovedposts']; 1338 } 1339 --$forum_counters[$post['fid']]['posts']; 1340 // Add 1 to the new forum's unapproved posts 1341 if(!isset($forum_counters[$moveto]['unapprovedposts'])) 1342 { 1343 $forum_counters[$moveto]['unapprovedposts'] = $forum_cache[$moveto]['unapprovedposts']; 1344 } 1345 ++$forum_counters[$moveto]['unapprovedposts']; 1346 } 1347 } 1348 1349 // Subtract attachment counts from old thread and add to new thread (which are counted regardless of post or attachment unapproval at time of coding) 1350 if(!isset($thread_counters[$post['tid']]['attachmentcount'])) 1351 { 1352 $thread_counters[$post['tid']]['attachmentcount'] = $post['threadattachmentcount']; 1353 } 1354 $thread_counters[$post['tid']]['attachmentcount'] -= $post['postattachmentcount']; 1355 $thread_counters[$newtid]['attachmentcount'] += $post['postattachmentcount']; 1356 } 1357 if($destination_tid == 0 && $thread_counters[$newtid]['replies'] > 0) 1358 { 1359 // If splitting into a new thread, subtract one from the thread's reply count to compensate for the original post 1360 --$thread_counters[$newtid]['replies']; 1361 } 1362 1363 $arguments = array("pids" => $pids, "tid" => $tid, "moveto" => $moveto, "newsubject" => $newsubject, "destination_tid" => $destination_tid); 1364 $plugins->run_hooks("class_moderation_split_posts", $arguments); 1365 1366 // Update user post counts 1367 if(is_array($user_counters)) 1368 { 1369 foreach($user_counters as $uid => $change) 1370 { 1371 if($change >= 0) 1372 { 1373 $change = '+'.$change; // add the addition operator for query 1374 } 1375 $db->update_query("users", array("postnum" => "postnum{$change}"), "uid='{$uid}'", 1, true); 1376 } 1377 } 1378 1379 // Update thread counters 1380 if(is_array($thread_counters)) 1381 { 1382 foreach($thread_counters as $tid => $counters) 1383 { 1384 if($tid == $newtid) 1385 { 1386 // Update the subject of the first post in the new thread 1387 $query = $db->simple_select("posts", "pid", "tid='$newtid'", array('order_by' => 'dateline', 'limit' => 1)); 1388 $newthread = $db->fetch_array($query); 1389 $sqlarray = array( 1390 "subject" => $newsubject, 1391 "replyto" => 0 1392 ); 1393 $db->update_query("posts", $sqlarray, "pid='{$newthread['pid']}'"); 1394 } 1395 else 1396 { 1397 // Update the subject of the first post in the old thread 1398 $query = $db->query(" 1399 SELECT p.pid, t.subject 1400 FROM ".TABLE_PREFIX."posts p 1401 LEFT JOIN ".TABLE_PREFIX."threads t ON (p.tid=t.tid) 1402 WHERE p.tid='{$tid}' 1403 ORDER BY p.dateline ASC 1404 LIMIT 1 1405 "); 1406 $oldthread = $db->fetch_array($query); 1407 $sqlarray = array( 1408 "subject" => $db->escape_string($oldthread['subject']), 1409 "replyto" => 0 1410 ); 1411 $db->update_query("posts", $sqlarray, "pid='{$oldthread['pid']}'"); 1412 } 1413 1414 $db->update_query("threads", $counters, "tid='{$tid}'"); 1415 1416 update_thread_data($tid); 1417 1418 // Update first post columns 1419 update_first_post($tid); 1420 } 1421 } 1422 update_thread_data($newtid); 1423 1424 update_first_post($newtid); 1425 1426 // Update forum counters 1427 if(is_array($forum_counters)) 1428 { 1429 foreach($forum_counters as $fid => $counters) 1430 { 1431 update_forum_counters($fid, $counters); 1432 } 1433 } 1434 1435 return $newtid; 1436 } 1437 1438 /** 1439 * Move multiple threads to new forum 1440 * 1441 * @param array Thread IDs 1442 * @param int Destination forum 1443 * @return boolean true 1444 */ 1445 function move_threads($tids, $moveto) 1446 { 1447 global $db, $plugins; 1448 1449 // Make sure we only have valid values 1450 $tids = array_map('intval', $tids); 1451 1452 $tid_list = implode(',', $tids); 1453 1454 $moveto = intval($moveto); 1455 1456 $newforum = get_forum($moveto); 1457 1458 $total_posts = $total_unapproved_posts = $total_threads = $total_unapproved_threads = 0; 1459 $query = $db->simple_select("threads", "fid, visible, replies, unapprovedposts, tid", "tid IN ($tid_list)"); 1460 while($thread = $db->fetch_array($query)) 1461 { 1462 $forum = get_forum($thread['fid']); 1463 1464 $total_posts += $thread['replies']+1; 1465 $total_unapproved_posts += $thread['unapprovedposts']; 1466 1467 $forum_counters[$thread['fid']]['posts'] += $thread['replies']+1; 1468 $forum_counters[$thread['fid']]['unapprovedposts'] += $thread['unapprovedposts']; 1469 1470 if($thread['visible'] == 1) 1471 { 1472 $forum_counters[$thread['fid']]['threads']++; 1473 ++$total_threads; 1474 } 1475 else 1476 { 1477 $forum_counters[$thread['fid']]['unapprovedthreads']++; 1478 $forum_counters[$thread['fid']]['unapprovedposts'] += $thread['replies']; // Implied unapproved posts counter for unapproved threads 1479 ++$total_unapproved_threads; 1480 } 1481 1482 $query1 = $db->query(" 1483 SELECT COUNT(p.pid) AS posts, u.uid 1484 FROM ".TABLE_PREFIX."posts p 1485 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) 1486 WHERE tid='{$thread['tid']}' 1487 GROUP BY u.uid 1488 ORDER BY posts DESC 1489 "); 1490 while($posters = $db->fetch_array($query1)) 1491 { 1492 $pcount = ""; 1493 if($newforum['usepostcounts'] != 0 && $forum['usepostcounts'] == 0 && $posters['visible'] != 0) 1494 { 1495 $pcount = "+{$posters['posts']}"; 1496 } 1497 else if($newforum['usepostcounts'] == 0 && $forum['usepostcounts'] != 0 && $posters['visible'] != 0) 1498 { 1499 $pcount = "-{$posters['posts']}"; 1500 } 1501 1502 if(!empty($pcount)) 1503 { 1504 $db->update_query("users", array("postnum" => "postnum{$pcount}"), "uid='{$posters['uid']}'", 1, true); 1505 } 1506 } 1507 } 1508 1509 $sqlarray = array( 1510 "fid" => $moveto, 1511 ); 1512 $db->update_query("threads", $sqlarray, "tid IN ($tid_list)"); 1513 $db->update_query("posts", $sqlarray, "tid IN ($tid_list)"); 1514 1515 // If any of the thread has a prefix and the destination forum doesn't accept that prefix, remove the prefix 1516 $query = $db->simple_select("threads", "tid, prefix", "tid IN ($tid_list) AND prefix != 0"); 1517 while($thread = $db->fetch_array($query)) 1518 { 1519 $query = $db->simple_select("threadprefixes", "COUNT(*) as num_prefixes", "(CONCAT(',',forums,',') LIKE '%,$new_fid,%' OR forums='-1') AND pid='".$thread['prefix']."'"); 1520 if($db->fetch_field($query, "num_prefixes") == 0) 1521 { 1522 $sqlarray = array( 1523 "prefix" => 0, 1524 ); 1525 $db->update_query("threads", $sqlarray, "tid = '{$thread['tid']}'"); 1526 } 1527 } 1528 1529 $arguments = array("tids" => $tids, "moveto" => $moveto); 1530 $plugins->run_hooks("class_moderation_move_threads", $arguments); 1531 1532 if(is_array($forum_counters)) 1533 { 1534 foreach($forum_counters as $fid => $counter) 1535 { 1536 $updated_count = array( 1537 "posts" => "-{$counter['posts']}", 1538 "unapprovedposts" => "-{$counter['unapprovedposts']}" 1539 ); 1540 if($counter['threads']) 1541 { 1542 $updated_count['threads'] = "-{$counter['threads']}"; 1543 } 1544 if($counter['unapprovedthreads']) 1545 { 1546 $updated_count['unapprovedthreads'] = "-{$counter['unapprovedthreads']}"; 1547 } 1548 update_forum_counters($fid, $updated_count); 1549 } 1550 } 1551 1552 $updated_count = array( 1553 "threads" => "+{$total_threads}", 1554 "unapprovedthreads" => "+{$total_unapproved_threads}", 1555 "posts" => "+{$total_posts}", 1556 "unapprovedposts" => "+{$total_unapproved_posts}" 1557 ); 1558 1559 update_forum_counters($moveto, $updated_count); 1560 1561 // Remove thread subscriptions for the users who no longer have permission to view the thread 1562 $this->remove_thread_subscriptions($tid_list, false, $moveto); 1563 1564 return true; 1565 } 1566 1567 /** 1568 * Approve multiple posts 1569 * 1570 * @param array PIDs 1571 * @return boolean true 1572 */ 1573 function approve_posts($pids) 1574 { 1575 global $db, $cache; 1576 1577 $num_posts = 0; 1578 1579 // Make sure we only have valid values 1580 $pids = array_map('intval', $pids); 1581 1582 $pid_list = implode(',', $pids); 1583 $pids = $threads_to_update = array(); 1584 1585 // Make visible 1586 $approve = array( 1587 "visible" => 1, 1588 ); 1589 1590 // We have three cases we deal with in these code segments: 1591 // 1) We're approving specific unapproved posts 1592 // 1.1) if the thread is approved 1593 // 1.2) if the thread is unapproved 1594 // 2) We're approving the firstpost of the thread, therefore approving the thread itself 1595 // 3) We're doing both 1 and 2 1596 $query = $db->query(" 1597 SELECT p.tid 1598 FROM ".TABLE_PREFIX."posts p 1599 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 1600 WHERE p.pid IN ($pid_list) AND p.visible = '0' AND t.firstpost = p.pid AND t.visible = 0 1601 "); 1602 while($post = $db->fetch_array($query)) 1603 { 1604 // This is the first post in the thread so we're approving the whole thread. 1605 $threads_to_update[] = $post['tid']; 1606 } 1607 1608 if(!empty($threads_to_update)) 1609 { 1610 $this->approve_threads($threads_to_update); 1611 } 1612 1613 $query = $db->query(" 1614 SELECT p.pid, p.tid, f.fid, f.usepostcounts, p.uid, t.visible AS threadvisible 1615 FROM ".TABLE_PREFIX."posts p 1616 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 1617 LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) 1618 WHERE p.pid IN ($pid_list) AND p.visible = '0' AND t.firstpost != p.pid 1619 "); 1620 while($post = $db->fetch_array($query)) 1621 { 1622 $pids[] = $post['pid']; 1623 1624 ++$thread_counters[$post['tid']]['unapprovedposts']; 1625 ++$thread_counters[$post['tid']]['replies']; 1626 1627 // If the thread of this post is unapproved then we've already taken into account this counter as implied. 1628 // Updating it again would cause it to double count 1629 if($post['threadvisible'] != 0) 1630 { 1631 ++$forum_counters[$post['fid']]['num_posts']; 1632 } 1633 1634 // If post counts enabled in this forum and the thread is approved, add 1 1635 if($post['usepostcounts'] != 0 && $post['threadvisible'] == 1) 1636 { 1637 $db->update_query("users", array("postnum" => "postnum+1"), "uid='{$post['uid']}'", 1, true); 1638 } 1639 } 1640 1641 if(empty($pids) && empty($threads_to_update)) 1642 { 1643 return false; 1644 } 1645 1646 if(!empty($pids)) 1647 { 1648 $where = "pid IN (".implode(',', $pids).")"; 1649 $db->update_query("posts", $approve, $where); 1650 } 1651 1652 if(is_array($thread_counters)) 1653 { 1654 foreach($thread_counters as $tid => $counters) 1655 { 1656 $counters_update = array( 1657 "unapprovedposts" => "-".$counters['unapprovedposts'], 1658 "replies" => "+".$counters['replies'] 1659 ); 1660 update_thread_counters($tid, $counters_update); 1661 1662 update_thread_data($tid); 1663 } 1664 } 1665 1666 if(is_array($forum_counters)) 1667 { 1668 foreach($forum_counters as $fid => $counters) 1669 { 1670 $updated_forum_stats = array( 1671 "posts" => "+{$counters['num_posts']}", 1672 "unapprovedposts" => "-{$counters['num_posts']}", 1673 "threads" => "+{$counters['num_threads']}", 1674 "unapprovedthreads" => "-{$counters['num_threads']}" 1675 ); 1676 update_forum_counters($fid, $updated_forum_stats); 1677 } 1678 } 1679 1680 return true; 1681 } 1682 1683 /** 1684 * Unapprove multiple posts 1685 * 1686 * @param array PIDs 1687 * @return boolean true 1688 */ 1689 function unapprove_posts($pids) 1690 { 1691 global $db, $cache; 1692 1693 // Make sure we only have valid values 1694 $pids = array_map('intval', $pids); 1695 1696 $pid_list = implode(',', $pids); 1697 $pids = $threads_to_update = array(); 1698 1699 // Make invisible 1700 $approve = array( 1701 "visible" => 0, 1702 ); 1703 1704 // We have three cases we deal with in these code segments: 1705 // 1) We're unapproving specific approved posts 1706 // 1.1) if the thread is approved 1707 // 1.2) if the thread is unapproved 1708 // 2) We're unapproving the firstpost of the thread, therefore unapproving the thread itself 1709 // 3) We're doing both 1 and 2 1710 $query = $db->query(" 1711 SELECT p.tid 1712 FROM ".TABLE_PREFIX."posts p 1713 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 1714 WHERE p.pid IN ($pid_list) AND p.visible = '1' AND t.firstpost = p.pid AND t.visible = 1 1715 "); 1716 while($post = $db->fetch_array($query)) 1717 { 1718 // This is the first post in the thread so we're unapproving the whole thread. 1719 $threads_to_update[] = $post['tid']; 1720 } 1721 1722 if(!empty($threads_to_update)) 1723 { 1724 $this->unapprove_threads($threads_to_update); 1725 } 1726 1727 $thread_counters = array(); 1728 $forum_counters = array(); 1729 1730 $query = $db->query(" 1731 SELECT p.pid, p.tid, f.fid, f.usepostcounts, p.uid, t.visible AS threadvisible 1732 FROM ".TABLE_PREFIX."posts p 1733 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 1734 LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) 1735 WHERE p.pid IN ($pid_list) AND p.visible = '1' AND t.firstpost != p.pid 1736 "); 1737 while($post = $db->fetch_array($query)) 1738 { 1739 $pids[] = $post['pid']; 1740 1741 ++$thread_counters[$post['tid']]['unapprovedposts']; 1742 ++$thread_counters[$post['tid']]['replies']; 1743 1744 // If the thread of this post is unapproved then we've already taken into account this counter as implied. 1745 // Updating it again would cause it to double count 1746 if($post['threadvisible'] != 0) 1747 { 1748 ++$forum_counters[$post['fid']]['num_posts']; 1749 } 1750 1751 // If post counts enabled in this forum and the thread is approved, subtract 1 1752 if($post['usepostcounts'] != 0 && $post['threadvisible'] == 1) 1753 { 1754 $db->update_query("users", array("postnum" => "postnum-1"), "uid='{$post['uid']}'", 1, true); 1755 } 1756 } 1757 1758 if(empty($pids) && empty($threads_to_update)) 1759 { 1760 return false; 1761 } 1762 1763 if(!empty($pids)) 1764 { 1765 $where = "pid IN (".implode(',', $pids).")"; 1766 $db->update_query("posts", $approve, $where); 1767 } 1768 1769 if(is_array($thread_counters)) 1770 { 1771 foreach($thread_counters as $tid => $counters) 1772 { 1773 $counters_update = array( 1774 "unapprovedposts" => "+".$counters['unapprovedposts'], 1775 "replies" => "-".$counters['replies'] 1776 ); 1777 1778 update_thread_counters($tid, $counters_update); 1779 1780 update_thread_data($tid); 1781 } 1782 } 1783 1784 if(is_array($forum_counters)) 1785 { 1786 foreach($forum_counters as $fid => $counters) 1787 { 1788 $updated_forum_stats = array( 1789 "posts" => "-{$counters['num_posts']}", 1790 "unapprovedposts" => "+{$counters['num_posts']}", 1791 "threads" => "-{$counters['num_threads']}", 1792 "unapprovedthreads" => "+{$counters['num_threads']}" 1793 ); 1794 1795 update_forum_counters($fid, $updated_forum_stats); 1796 } 1797 } 1798 1799 return true; 1800 } 1801 1802 /** 1803 * Change thread subject 1804 * 1805 * @param mixed Thread ID(s) 1806 * @param string Format of new subject (with {subject}) 1807 * @return boolean true 1808 */ 1809 function change_thread_subject($tids, $format) 1810 { 1811 global $db, $mybb, $plugins; 1812 1813 // Get tids into list 1814 if(!is_array($tids)) 1815 { 1816 $tids = array(intval($tids)); 1817 } 1818 1819 1820 // Make sure we only have valid values 1821 $tids = array_map('intval', $tids); 1822 1823 $tid_list = implode(',', $tids); 1824 1825 // Get original subject 1826 $query = $db->simple_select("threads", "subject, tid", "tid IN ($tid_list)"); 1827 while($thread = $db->fetch_array($query)) 1828 { 1829 // Update threads and first posts with new subject 1830 $subject = str_replace('{username}', $mybb->user['username'], $format); 1831 $subject = str_replace('{subject}', $thread['subject'], $subject); 1832 $new_subject = array( 1833 "subject" => $db->escape_string($subject) 1834 ); 1835 $db->update_query("threads", $new_subject, "tid='{$thread['tid']}'", 1); 1836 $db->update_query("posts", $new_subject, "tid='{$thread['tid']}' AND replyto='0'", 1); 1837 } 1838 1839 $arguments = array("tids" => $tids, "format" => $format); 1840 $plugins->run_hooks("class_moderation_change_thread_subject", $arguments); 1841 1842 return true; 1843 } 1844 1845 /** 1846 * Add thread expiry 1847 * 1848 * @param int Thread ID 1849 * @param int Timestamp when the thread is deleted 1850 * @return boolean true 1851 */ 1852 function expire_thread($tid, $deletetime) 1853 { 1854 global $db, $plugins; 1855 1856 $tid = intval($tid); 1857 1858 $update_thread = array( 1859 "deletetime" => intval($deletetime) 1860 ); 1861 $db->update_query("threads", $update_thread, "tid='{$tid}'"); 1862 1863 $arguments = array("tid" => $tid, "deletetime" => $deletetime); 1864 $plugins->run_hooks("class_moderation_expire_thread", $arguments); 1865 1866 return true; 1867 } 1868 1869 /** 1870 * Toggle post visibility (approved/unapproved) 1871 * 1872 * @param array Post IDs 1873 * @param int Thread ID 1874 * @param int Forum ID 1875 * @return boolean true 1876 */ 1877 function toggle_post_visibility($pids) 1878 { 1879 global $db; 1880 1881 // Make sure we only have valid values 1882 $pids = array_map('intval', $pids); 1883 1884 $pid_list = implode(',', $pids); 1885 $query = $db->simple_select("posts", 'pid, visible', "pid IN ($pid_list)"); 1886 while($post = $db->fetch_array($query)) 1887 { 1888 if($post['visible'] == 1) 1889 { 1890 $unapprove[] = $post['pid']; 1891 } 1892 else 1893 { 1894 $approve[] = $post['pid']; 1895 } 1896 } 1897 if(is_array($unapprove)) 1898 { 1899 $this->unapprove_posts($unapprove); 1900 } 1901 if(is_array($approve)) 1902 { 1903 $this->approve_posts($approve); 1904 } 1905 return true; 1906 } 1907 1908 /** 1909 * Toggle thread visibility (approved/unapproved) 1910 * 1911 * @param array Thread IDs 1912 * @param int Forum ID 1913 * @return boolean true 1914 */ 1915 function toggle_thread_visibility($tids, $fid) 1916 { 1917 global $db; 1918 1919 // Make sure we only have valid values 1920 $tids = array_map('intval', $tids); 1921 $fid = intval($fid); 1922 1923 $tid_list = implode(',', $tids); 1924 $query = $db->simple_select("threads", 'tid, visible', "tid IN ($tid_list)"); 1925 while($thread = $db->fetch_array($query)) 1926 { 1927 if($thread['visible'] == 1) 1928 { 1929 $unapprove[] = $thread['tid']; 1930 } 1931 else 1932 { 1933 $approve[] = $thread['tid']; 1934 } 1935 } 1936 if(is_array($unapprove)) 1937 { 1938 $this->unapprove_threads($unapprove, $fid); 1939 } 1940 if(is_array($approve)) 1941 { 1942 $this->approve_threads($approve, $fid); 1943 } 1944 return true; 1945 } 1946 1947 /** 1948 * Toggle threads open/closed 1949 * 1950 * @param array Thread IDs 1951 * @return boolean true 1952 */ 1953 function toggle_thread_status($tids) 1954 { 1955 global $db; 1956 1957 // Make sure we only have valid values 1958 $tids = array_map('intval', $tids); 1959 1960 $tid_list = implode(',', $tids); 1961 $query = $db->simple_select("threads", 'tid, closed', "tid IN ($tid_list)"); 1962 while($thread = $db->fetch_array($query)) 1963 { 1964 if($thread['closed'] == 1) 1965 { 1966 $open[] = $thread['tid']; 1967 } 1968 elseif($thread['closed'] == 0) 1969 { 1970 $close[] = $thread['tid']; 1971 } 1972 } 1973 if(is_array($open)) 1974 { 1975 $this->open_threads($open); 1976 } 1977 if(is_array($close)) 1978 { 1979 $this->close_threads($close); 1980 } 1981 return true; 1982 } 1983 1984 /** 1985 * Remove thread subscriptions (from one or multiple threads in the same forum) 1986 * 1987 * @param int $tids Thread ID, or an array of thread IDs from the same forum. 1988 * @param boolean $all True (default) to delete all subscriptions, false to only delete subscriptions from users with no permission to read the thread 1989 * @param int $fid (Only applies if $all is false) The forum ID of the thread 1990 * @return boolean true 1991 */ 1992 function remove_thread_subscriptions($tids, $all = true, $fid = 0) 1993 { 1994 global $db, $plugins; 1995 1996 // Format thread IDs 1997 if(!is_array($tids)) 1998 { 1999 $tids = array($tids); 2000 } 2001 2002 // Make sure we only have valid values 2003 $tids = array_map('intval', $tids); 2004 $fid = intval($fid); 2005 2006 $tids_csv = implode(',', $tids); 2007 2008 // Delete only subscriptions from users who no longer have permission to read the thread. 2009 if(!$all) 2010 { 2011 // Get groups that cannot view the forum or its threads 2012 $forum_parentlist = get_parent_list($fid); 2013 $query = $db->simple_select("forumpermissions", "gid", "fid IN ({$forum_parentlist}) AND (canview=0 OR canviewthreads=0)"); 2014 $groups = array(); 2015 while($group = $db->fetch_array($query)) 2016 { 2017 $groups[] = $group['gid']; 2018 switch($db->type) 2019 { 2020 case "pgsql": 2021 case "sqlite": 2022 $additional_groups .= " OR ','||u.additionalgroups||',' LIKE ',{$group['gid']},'"; 2023 break; 2024 default: 2025 $additional_groups .= " OR CONCAT(',',u.additionalgroups,',') LIKE ',{$group['gid']},'"; 2026 } 2027 } 2028 // If there are groups found, delete subscriptions from users in these groups 2029 if(count($groups) > 0) 2030 { 2031 $groups_csv = implode(',', $groups); 2032 $query = $db->query(" 2033 SELECT s.tid, u.uid 2034 FROM ".TABLE_PREFIX."threadsubscriptions s 2035 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=s.uid) 2036 WHERE s.tid IN ({$tids_csv}) 2037 AND (u.usergroup IN ({$groups_csv}){$additional_groups}) 2038 "); 2039 while($subscription = $db->fetch_array($query)) 2040 { 2041 $db->delete_query("threadsubscriptions", "uid='{$subscription['uid']}' AND tid='{$subscription['tid']}'"); 2042 } 2043 } 2044 } 2045 // Delete all subscriptions of this thread 2046 else 2047 { 2048 $db->delete_query("threadsubscriptions", "tid IN ({$tids_csv})"); 2049 } 2050 2051 $arguments = array("tids" => $tids, "all" => $all, "fid" => $fid); 2052 $plugins->run_hooks("class_moderation_remove_thread_subscriptions", $arguments); 2053 2054 return true; 2055 } 2056 2057 /** 2058 * Apply a thread prefix (to one or multiple threads in the same forum) 2059 * 2060 * @param int $tids Thread ID, or an array of thread IDs from the same forum. 2061 * @param int $prefix Prefix ID to apply to the threads 2062 */ 2063 function apply_thread_prefix($tids, $prefix = 0) 2064 { 2065 global $db, $plugins; 2066 2067 // Format thread IDs 2068 if(!is_array($tids)) 2069 { 2070 $tids = array($tids); 2071 } 2072 2073 // Make sure we only have valid values 2074 $tids = array_map('intval', $tids); 2075 $tids_csv = implode(',', $tids); 2076 2077 $update_thread = array('prefix' => $prefix); 2078 $db->update_query('threads', $update_thread, "tid IN ({$tids_csv})"); 2079 2080 $arguments = array('tids' => $tids, 'prefix' => $prefix); 2081 2082 $plugins->run_hooks('class_moderation_apply_thread_prefix', $arguments); 2083 2084 return true; 2085 } 2086 } 2087 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Tue Aug 3 20:35:36 2010 | Cross-referenced by PHPXref 0.7 |