/**
  * @see EventListener::execute()
  */
 public function execute($eventObj, $className, $eventName)
 {
     if (MODULE_USER_NOTIFICATION) {
         if ($className === 'PostActionPage') {
             $markedPostIDs = WCF::getSession()->getVar('markedPosts');
             if ($eventObj->post !== null && $eventObj->post->userID != WCF::getUser()->userID) {
                 if ($eventObj->action === 'trash') {
                     if (!THREAD_ENABLE_RECYCLE_BIN || !$eventObj->board->getModeratorPermission('canDeletePost') || $eventObj->post->isDeleted) {
                         return;
                     }
                     NotificationHandler::fireEvent('trashed', 'postDelete', $eventObj->post->postID, $eventObj->post->userID, array('trashedByUserID' => WCF::getUser()->userID, 'trashedByUsername' => WCF::getUser()->username, 'trashReason' => $eventObj->reason, 'threadID' => $eventObj->thread->threadID, 'threadTopic' => $eventObj->thread->topic));
                     return true;
                 } else {
                     if ($eventObj->action === 'delete') {
                         if (!$eventObj->board->getModeratorPermission('canDeletePostCompletely')) {
                             return;
                         }
                         NotificationHandler::revokeEvent(array('trashed'), 'postDelete', $eventObj->post->postID);
                         NotificationHandler::fireEvent('deleted', 'postDelete', $eventObj->post->postID, $eventObj->post->userID, array('deletedByUserID' => WCF::getUser()->userID, 'deletedByUsername' => WCF::getUser()->username, 'threadID' => $eventObj->thread->threadID, 'threadTopic' => $eventObj->thread->topic));
                         return true;
                     } else {
                         if ($eventObj->action === 'recover') {
                             if (!$eventObj->board->getModeratorPermission('canDeletePostCompletely') || !$eventObj->post->isDeleted) {
                                 return;
                             }
                             NotificationHandler::revokeEvent(array('trashed'), 'postDelete', $eventObj->post);
                             return true;
                         }
                     }
                 }
             }
             if ($markedPostIDs !== null && count($markedPostIDs)) {
                 if ($eventObj->action === 'deleteAll') {
                     $trashPosts = array();
                     $trashPostsThreadIDs = array();
                     $deletePosts = array();
                     $deletePostsThreadIDs = array();
                     $sql = "SELECT\t\tpost.*, thread.threadID, thread.topic\n\t\t\t\t\t\t\tFROM\t\twbb" . WBB_N . "_post post\n\t\t\t\t\t\t\tLEFT JOIN\twbb" . WBB_N . "_thread thread\n\t\t\t\t\t\t\tON\t\t(post.threadID = thread.threadID)\n\t\t\t\t\t\t\tWHERE\t\tpost.postID IN (" . implode(',', $markedPostIDs) . ")";
                     $result = WCF::getDB()->sendQuery($sql);
                     while ($row = WCF::getDB()->fetchArray($result)) {
                         if ($row['userID'] != WCF::getUser()->userID) {
                             if ($row['isDeleted'] || !THREAD_ENABLE_RECYCLE_BIN) {
                                 $deletePosts[$row['postID']] = new PostDeleteNotificationObject(null, $row);
                                 $deletePostsThreadIDs[] = $row['threadID'];
                             } else {
                                 $trashPosts[$row['postID']] = new PostDeleteNotificationObject(null, $row);
                                 $trashPostsThreadIDs[] = $row['threadID'];
                             }
                         }
                     }
                     list($trashPostsBoards, $trashPostsBoardIDs) = ThreadEditor::getBoards(implode(',', $trashPostsThreadIDs));
                     list($deletePostsBoards, $deletePostsBoardIDs) = ThreadEditor::getBoards(implode(',', $deletePostsThreadIDs));
                     foreach ($trashPostsBoards as $trashPostsBoard) {
                         $trashPostsBoard->checkModeratorPermission('canDeletePost');
                     }
                     foreach ($deletePostsBoards as $deletePostsBoard) {
                         $deletePostsBoard->checkModeratorPermission('canDeletePostCompletely');
                     }
                     unset($trashPostsThreadIDs, $deletePostsThreadIDs, $trashPostsBoards, $deletePostsBoards, $trashPostsBoardIDs, $deletePostsBoardIDs);
                     foreach ($trashPosts as $trashPost) {
                         NotificationHandler::fireEvent('trashed', 'postDelete', $trashPost, $trashPost->userID, array('trashedByUserID' => WCF::getUser()->userID, 'trashedByUsername' => WCF::getUser()->username, 'trashReason' => $eventObj->reason, 'threadID' => $trashPost->threadID, 'threadTopic' => $trashPost->topic));
                     }
                     foreach ($deletePosts as $deletePost) {
                         NotificationHandler::revokeEvent(array('trashed'), 'postDelete', $deletePost);
                         NotificationHandler::fireEvent('deleted', 'postDelete', $deletePost, $deletePost->userID, array('deletedByUserID' => WCF::getUser()->userID, 'deletedByUsername' => WCF::getUser()->username, 'threadID' => $deletePost->threadID, 'threadTopic' => $deletePost->topic));
                     }
                     return true;
                 } else {
                     if ($eventObj->action === 'recoverAll') {
                         $threadIDs = PostEditor::getThreadIDs(implode(',', $markedPostIDs));
                         $notificationObjectObjects = NotificationHandler::getNotificationObjectTypeObject('postDelete')->getObjects($markedPostIDs);
                         list($boards, $boardIDs) = ThreadEditor::getBoards($threadIDs);
                         foreach ($boards as $board) {
                             $board->checkModeratorPermission('canDeletePostCompletely');
                         }
                         unset($threadIDs, $boards, $boardIDs);
                         foreach ($notificationObjectObjects as $notificationObjectObject) {
                             NotificationHandler::revokeEvent(array('trashed'), 'postDelete', $notificationObjectObject);
                         }
                         return true;
                     }
                 }
             }
         } else {
             if ($className === 'ThreadPage') {
                 $posts = $eventObj->postList->posts;
                 $postIDs = array();
                 $user = new NotificationUser(null, WCF::getUser(), false);
                 $packageID = NotificationHandler::getNotificationObjectTypeObject('postDelete')->getPackageID();
                 foreach ($posts as $post) {
                     if ($post->isDeleted && $post->userID == $user->userID) {
                         $postIDs[] = $post->postID;
                     }
                 }
                 unset($posts);
                 if (isset($user->notificationFlags[$packageID]) && $user->notificationFlags[$packageID] > 0) {
                     $count = NotificationEditor::markConfirmedByObjectVisit($user->userID, array('trashed'), 'postDelete', $postIDs);
                     $user->removeOutstandingNotification($packageID, $count);
                 }
             } else {
                 if ($className === 'PostEditForm' && $eventObj->post->userID != WCF::getUser()->userID && isset($_POST['deletePost']) && isset($_POST['sure'])) {
                     if ((!THREAD_ENABLE_RECYCLE_BIN || THREAD_ENABLE_RECYCLE_BIN && $eventObj->post->isDeleted) && $eventObj->board->getModeratorPermission('canDeletePostCompletely')) {
                         NotificationHandler::revokeEvent(array('trashed'), 'postDelete', $eventObj->post->postID);
                         NotificationHandler::fireEvent('deleted', 'postDelete', $eventObj->post->postID, $eventObj->post->userID, array('deletedByUserID' => WCF::getUser()->userID, 'deletedByUsername' => WCF::getUser()->username, 'threadID' => $eventObj->thread->threadID, 'threadTopic' => $eventObj->thread->topic));
                     } else {
                         if (!$eventObj->post->isDeleted && THREAD_ENABLE_RECYCLE_BIN && $eventObj->board->getModeratorPermission('canDeletePost')) {
                             NotificationHandler::fireEvent('trashed', 'postDelete', $eventObj->post->postID, $eventObj->post->userID, array('trashedByUserID' => WCF::getUser()->userID, 'trashedByUsername' => WCF::getUser()->username, 'trashReason' => $eventObj->deleteReason, 'threadID' => $eventObj->thread->threadID, 'threadTopic' => $eventObj->thread->topic));
                         }
                     }
                 }
             }
         }
     }
 }
 /**
  * Moves and inserts the marked posts in a new thread.
  */
 public function moveAndInsert()
 {
     if ($this->board == null) {
         throw new IllegalLinkException();
     }
     // check permission
     $this->board->checkModeratorPermission('canMovePost');
     // get threadids
     $threadIDs = PostEditor::getThreadIDs($this->postIDs);
     // get boards
     list($boards, $boardIDs) = ThreadEditor::getBoards($threadIDs);
     // check permissions
     foreach ($boards as $board) {
         $board->checkModeratorPermission('canMovePost');
     }
     // remove user stats
     ThreadEditor::updateUserStats($threadIDs, 'delete');
     PostEditor::updateUserStats(ThreadEditor::getAllPostIDs($threadIDs), 'delete');
     // create new thread
     $thread = ThreadEditor::createFromPosts($this->postIDs, $this->board->boardID);
     // move posts
     PostEditor::moveAll($this->postIDs, $thread->threadID, $thread->boardID);
     PostEditor::unmarkAll();
     // check threads
     ThreadEditor::checkVisibilityAll($threadIDs . ',' . $thread->threadID);
     // refresh
     ThreadEditor::refreshAll($threadIDs . ',' . $thread->threadID);
     // re-add user stats
     ThreadEditor::updateUserStats($threadIDs, 'enable');
     PostEditor::updateUserStats($this->postIDs, 'enable');
     PostEditor::updateUserStats(ThreadEditor::getAllPostIDs($threadIDs), 'enable');
     // refresh counts
     BoardEditor::refreshAll($boardIDs . ',' . $this->board->boardID);
     // set last post
     $this->board->setLastPosts();
     foreach ($boards as $board) {
         $board->setLastPosts();
     }
     self::resetCache();
     HeaderUtil::redirect($this->url);
     exit;
 }
 /**
  * Merges posts.
  */
 public function merge()
 {
     if ($this->post === null || empty($this->postIDs)) {
         throw new IllegalLinkException();
     }
     // remove target post from source
     $postIDArray = explode(',', $this->postIDs);
     if (($key = array_search($this->post->postID, $postIDArray)) !== false) {
         unset($postIDArray[$key]);
         $this->postIDs = implode(',', $postIDArray);
     }
     // get thread ids
     $threadIDs = PostEditor::getThreadIDs($this->postIDs);
     // get boards
     list($boards, $boardIDs) = ThreadEditor::getBoards($threadIDs);
     // check permissions
     $this->board->checkModeratorPermission('canMergePost');
     foreach ($boards as $board) {
         $board->checkModeratorPermission('canMergePost');
     }
     // remove user stats
     ThreadEditor::updateUserStats($threadIDs, 'delete');
     PostEditor::updateUserStats(ThreadEditor::getAllPostIDs($threadIDs), 'delete');
     // merge posts
     PostEditor::mergeAll($this->postIDs, $this->post->postID);
     PostEditor::unmarkAll();
     // handle threads (check for empty, deleted and hidden threads)
     ThreadEditor::checkVisibilityAll($threadIDs);
     // refresh last post, replies, attachments, polls in threads
     ThreadEditor::refreshAll($threadIDs);
     // re-add user stats
     ThreadEditor::updateUserStats($threadIDs, 'enable');
     PostEditor::updateUserStats(ThreadEditor::getAllPostIDs($threadIDs), 'enable');
     // refresh counts
     BoardEditor::refreshAll($boardIDs);
     // refresh last post in boards
     $this->board->setLastPosts();
     foreach ($boards as $board) {
         $board->setLastPosts();
     }
     HeaderUtil::redirect($this->url);
     exit;
 }
 /**
  * @see Form::save()
  */
 public function save()
 {
     // build conditions
     $this->conditions = new ConditionBuilder();
     parent::save();
     // boardIDs
     if (count($this->boardIDs)) {
         $this->conditions->add("threadID IN (SELECT threadID FROM wbb" . WBB_N . "_thread WHERE boardID IN (" . implode(',', $this->boardIDs) . "))");
     }
     // time
     if ($this->timeAfterDay && $this->timeAfterMonth && $this->timeAfterYear) {
         $time = @gmmktime(0, 0, 0, $this->timeAfterMonth, $this->timeAfterDay, $this->timeAfterYear);
         if ($time !== false && $time !== -1) {
             $this->conditions->add("time > " . $time);
         }
     }
     if ($this->timeBeforeDay && $this->timeBeforeMonth && $this->timeBeforeYear) {
         $time = @gmmktime(0, 0, 0, $this->timeBeforeMonth, $this->timeBeforeDay, $this->timeBeforeYear);
         if ($time !== false && $time !== -1) {
             $this->conditions->add("time < " . $time);
         }
     }
     // username
     if ($this->createdBy != '') {
         $users = preg_split('/\\s*,\\s*/', $this->createdBy, -1, PREG_SPLIT_NO_EMPTY);
         $users = array_map('escapeString', $users);
         $this->conditions->add("username IN ('" . implode("','", $users) . "')");
     }
     // status
     if ($this->deleted) {
         $this->conditions->add("isDeleted = 1");
     }
     if ($this->notDeleted) {
         $this->conditions->add("isDeleted = 0");
     }
     if ($this->disabled) {
         $this->conditions->add("isDisabled = 1");
     }
     if ($this->notDisabled) {
         $this->conditions->add("isDisabled = 0");
     }
     if ($this->closed) {
         $this->conditions->add("isClosed = 1");
     }
     if ($this->open) {
         $this->conditions->add("isClosed = 0");
     }
     // execute action
     $conditions = $this->conditions->get();
     switch ($this->action) {
         case 'delete':
             $postIDs = '';
             $sql = "SELECT\tpostID\n\t\t\t\t\tFROM\twbb" . WBB_N . "_post\n\t\t\t\t\t" . $conditions;
             $result = WCF::getDB()->sendQuery($sql);
             while ($row = WCF::getDB()->fetchArray($result)) {
                 if (!empty($postIDs)) {
                     $postIDs .= ',';
                 }
                 $postIDs .= $row['postID'];
                 $this->affectedPosts++;
             }
             // get thread ids
             $threadIDs = PostEditor::getThreadIDs($postIDs);
             // delete posts
             PostEditor::deleteAllCompletely($postIDs);
             // check threads
             ThreadEditor::checkVisibilityAll($threadIDs);
             break;
         case 'trash':
         case 'restore':
             $sql = "UPDATE\twbb" . WBB_N . "_post\n\t\t\t\t\tSET\tisDeleted = " . ($this->action == 'trash' ? 1 : 0) . "\n\t\t\t\t\t\t" . ($this->action == 'trash' ? ",deleteTime = " . TIME_NOW . ", deletedBy = '" . escapeString(WCF::getUser()->username) . "', deletedByID = " . WCF::getUser()->userID : '') . "\n\t\t\t\t\t" . $conditions;
             WCF::getDB()->sendQuery($sql);
             $this->affectedPosts = WCF::getDB()->getAffectedRows();
             break;
         case 'disable':
         case 'enable':
             $sql = "UPDATE\twbb" . WBB_N . "_post\n\t\t\t\t\tSET\tisDisabled = " . ($this->action == 'disable' ? 1 : 0) . "\n\t\t\t\t\t" . $conditions;
             WCF::getDB()->sendQuery($sql);
             $this->affectedPosts = WCF::getDB()->getAffectedRows();
             break;
         case 'close':
         case 'open':
             $sql = "UPDATE\twbb" . WBB_N . "_post\n\t\t\t\t\tSET\tisClosed = " . ($this->action == 'close' ? 1 : 0) . "\n\t\t\t\t\t" . $conditions;
             WCF::getDB()->sendQuery($sql);
             $this->affectedPosts = WCF::getDB()->getAffectedRows();
             break;
     }
     $this->saved();
     WCF::getTPL()->assign('affectedPosts', $this->affectedPosts);
 }