Ejemplo n.º 1
0
 /**
  * Post multi-mod: Merge posts
  *
  * @return	@e void		[Outputs to screen]
  */
 protected function _multiMergePost()
 {
     $this->_resetModerator($this->topic['forum_id']);
     $this->_genericPermissionCheck('split_merge');
     if (count($this->pids) < 2) {
         $this->_showError('mod_only_one_pid', 10383);
     }
     //-----------------------------------------
     // Form or print?
     //-----------------------------------------
     if (!$this->request['checked']) {
         //-----------------------------------------
         // Get post data
         //-----------------------------------------
         $master_post = "";
         $dropdown = array();
         $authors = array();
         $seen_author = array();
         $upload_html = "";
         $seoTitle = '';
         //-----------------------------------------
         // Grab teh posts
         //-----------------------------------------
         $this->DB->build(array('select' => 'p.*', 'from' => array('posts' => 'p'), 'where' => "p.pid IN (" . implode(",", $this->pids) . ")", 'add_join' => array(array('select' => 't.forum_id, t.title_seo', 'from' => array('topics' => 't'), 'where' => 't.tid=p.topic_id', 'type' => 'left'))));
         $outer = $this->DB->execute();
         while ($p = $this->DB->fetch($outer)) {
             if (IPSMember::checkPermissions('read', $p['forum_id']) == TRUE) {
                 $master_post .= $p['post'] . "<br /><br />";
                 $dropdown[] = array($p['pid'], ipsRegistry::getClass('class_localization')->getDate($p['post_date'], 'LONG') . " (#{$p['pid']})");
                 if (!in_array($p['author_id'], $seen_author)) {
                     $authors[] = array($p['author_id'], "{$p['author_name']} (#{$p['pid']})");
                     $seen_author[] = $p['author_id'];
                 }
                 $seoTitle = $p['title_seo'];
             }
         }
         //-----------------------------------------
         // Get Attachment Data
         //-----------------------------------------
         $this->DB->build(array('select' => '*', 'from' => 'attachments', 'where' => "attach_rel_module='post' AND attach_rel_id IN (" . implode(",", $this->pids) . ")"));
         $this->DB->execute();
         while ($row = $this->DB->fetch()) {
             $row['image'] = $this->caches['attachtypes'][$row['attach_ext']]['atype_img'];
             $row['size'] = IPSLib::sizeFormat($row['attach_filesize']);
             $row['attach_file'] = IPSText::truncate($row['attach_file'], 50);
             $attachments[] = $row;
         }
         //-----------------------------------------
         // Print form
         //-----------------------------------------
         /* Load editor stuff */
         $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/editor/composite.php', 'classes_editor_composite');
         $_editor = new $classToLoad();
         $_editor->setContent(trim($master_post));
         $editor = $_editor->show('Post', array('autoSaveKey' => md5('merge-' . $this->topic['tid']), 'height' => 350));
         $this->output .= $this->registry->getClass('output')->getTemplate('mod')->mergePostForm($editor, $dropdown, $authors, $attachments, $seoTitle);
         if ($this->topic['tid']) {
             $this->registry->getClass('output')->addNavigation($this->topic['title'], "showtopic={$this->topic['tid']}", $this->topic['title_seo'], 'showtopic');
         }
         $this->registry->getClass('output')->addNavigation($this->lang->words['cm_title'], '');
         $this->registry->getClass('output')->setTitle($this->lang->words['cm_title'] . ' - ' . ipsRegistry::$settings['board_name']);
         $this->registry->output->addContent($this->output);
         $this->registry->getClass('output')->sendOutput();
     } else {
         //-----------------------------------------
         // DO THE THING, WITH THE THING!!
         //-----------------------------------------
         $this->request['postdate'] = intval($this->request['postdate']);
         if (empty($this->request['selectedpids']) || empty($this->request['postdate']) || empty($this->request['Post'])) {
             $this->_showError('mod_merge_posts', 10384);
         }
         /* Load editor stuff */
         $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/editor/composite.php', 'classes_editor_composite');
         $_editor = new $classToLoad();
         /* remove saved content */
         if ($this->memberData['member_id']) {
             $_editor->removeAutoSavedContent(array('member_id' => $this->memberData['member_id'], 'autoSaveKey' => md5('merge-' . $this->topic['tid'])));
         }
         IPSText::getTextClass('bbcode')->parse_smilies = 1;
         IPSText::getTextClass('bbcode')->parse_html = 0;
         IPSText::getTextClass('bbcode')->parse_bbcode = 1;
         IPSText::getTextClass('bbcode')->parsing_section = 'topics';
         $post = $_editor->process($_POST['Post']);
         $post = IPSText::getTextClass('bbcode')->preDbParse($post);
         //-----------------------------------------
         // Post to keep...
         //-----------------------------------------
         $posts = array();
         $author = array();
         $post_to_delete = array();
         $new_post_key = md5(time());
         $topics = array();
         $forums = array();
         $append_edit = 0;
         //-----------------------------------------
         // Grab teh posts
         //-----------------------------------------
         $this->DB->build(array('select' => 'p.*', 'from' => array('posts' => 'p'), 'where' => "p.pid IN (" . implode(",", $this->pids) . ")", 'add_join' => array(array('select' => 't.forum_id', 'from' => array('topics' => 't'), 'where' => 't.tid=p.topic_id', 'type' => 'left'))));
         $outer = $this->DB->execute();
         while ($p = $this->DB->fetch($outer)) {
             $posts[$p['pid']] = $p;
             $topics[$p['topic_id']] = $p['topic_id'];
             $forums[$p['forum_id']] = $p['forum_id'];
             if ($p['author_id'] == $this->request['postauthor']) {
                 $author = array('id' => $p['author_id'], 'name' => $p['author_name']);
             }
             if ($p['pid'] != $this->request['postdate']) {
                 $post_to_delete[] = $p['pid'];
             }
             if ($p['append_edit']) {
                 $append_edit = 1;
             }
         }
         //-----------------------------------------
         // Update main post...
         //-----------------------------------------
         $this->DB->update('posts', array('author_id' => $author['id'], 'author_name' => $author['name'], 'post' => $post, 'post_key' => $new_post_key, 'edit_time' => time(), 'edit_name' => $this->memberData['members_display_name'], 'append_edit' => ($append_edit or !$this->memberData['g_append_edit']) ? 1 : 0), 'pid=' . $this->request['postdate']);
         /* Run moderation sync */
         $this->modLibrary->runModSync('postMerge', $this->pids, $this->request['postdate']);
         //-----------------------------------------
         // Fix attachments
         //-----------------------------------------
         $attach_keep = array();
         $attach_kill = array();
         foreach ($_POST as $key => $value) {
             if (preg_match('/^attach_(\\d+)$/', $key, $match)) {
                 if ($this->request[$match[0]] == 'keep') {
                     $attach_keep[] = $match[1];
                 } else {
                     $attach_kill[] = $match[1];
                 }
             }
         }
         $attach_keep = IPSLib::cleanIntArray($attach_keep);
         $attach_kill = IPSLib::cleanIntArray($attach_kill);
         //-----------------------------------------
         // Keep
         //-----------------------------------------
         if (count($attach_keep)) {
             $this->DB->update('attachments', array('attach_rel_id' => $this->request['postdate'], 'attach_post_key' => $new_post_key, 'attach_member_id' => $author['id']), 'attach_id IN(' . implode(",", $attach_keep) . ')');
         }
         //-----------------------------------------
         // Kill Attachments
         //-----------------------------------------
         if (count($attach_kill)) {
             $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('core') . '/sources/classes/attach/class_attach.php', 'class_attach');
             $class_attach = new $classToLoad($this->registry);
             $class_attach->type = 'post';
             $class_attach->init();
             $class_attach->bulkRemoveAttachment($attach_kill, 'attach_id');
         }
         //-----------------------------------------
         // Kill old posts
         //-----------------------------------------
         if (count($post_to_delete)) {
             $this->DB->delete('posts', 'pid IN(' . implode(",", $post_to_delete) . ')');
             IPSDeleteLog::removeEntries($post_to_delete, 'post', TRUE);
             /* Handle Rep */
             $this->DB->delete('reputation_cache', "app='forums' AND type='pid' AND type_id IN(" . implode(",", $post_to_delete) . ")");
             $this->DB->delete('reputation_index', "app='forums' AND type='pid' AND type_id IN(" . implode(",", $post_to_delete) . ")");
             foreach ($post_to_delete as $post) {
                 $this->DB->delete('reputation_totals', "rt_key=MD5('forums;pid;" . $post . "') AND rt_type_id=" . $post);
             }
         }
         foreach ($topics as $t) {
             $this->modLibrary->rebuildTopic($t, 0);
         }
         foreach ($forums as $f) {
             $this->modLibrary->forumRecount($f);
         }
         $this->cache->rebuildCache('stats', 'global');
         /* Clear the content cache */
         IPSContentCache::drop('post', $this->pids);
         $this->_addModeratorLog(sprintf($this->lang->words['acp_merged_posts'], implode(", ", $this->pids)));
     }
 }
Ejemplo n.º 2
0
 /**
  * Post a reply
  * Very simply posts a reply. Simple.
  *
  * Usage:
  * $post->setTopicID(100);
  * $post->setForumID(5);
  * $post->setAuthor( $member );
  * 
  * $post->setPostContent( "Hello [b]there![/b]" );
  * # Optional: No bbcode, etc parsing will take place
  * # $post->setPostContentPreFormatted( "Hello [b]there![/b]" );
  * $post->addReply();
  *
  * Exception Error Codes:
  * NO_TOPIC_ID       : No topic ID set
  * NO_FORUM_ID		: No forum ID set
  * NO_AUTHOR_SET	    : No Author set
  * NO_CONTENT        : No post content set
  * NO_SUCH_TOPIC     : No such topic
  * NO_SUCH_FORUM		: No such forum
  * NO_REPLY_PERM     : Author cannot reply to this topic
  * TOPIC_LOCKED		: The topic is locked
  * NO_REPLY_POLL     : Cannot reply to this poll only topic
  * TOPIC_LOCKED		: The topic is locked
  * NO_POST_FORUM		: Unable to post in that forum
  * FORUM_LOCKED		: Forum read only
  *
  * @return	mixed	Exception, boolean, or void
  */
 public function addReply()
 {
     //-----------------------------------------
     // Global checks and functions
     //-----------------------------------------
     try {
         $this->globalSetUp();
     } catch (Exception $error) {
         $this->_postErrors = $error->getMessage();
     }
     if ($this->_bypassPermChecks !== TRUE && IPSMember::isOnModQueue($this->getAuthor()) === NULL) {
         $this->_postErrors = 'warnings_restrict_post_perm';
     }
     if (!$this->getPostContent() and !$this->getPostContentPreFormatted() and !$this->getIsPreview()) {
         $this->_postErrors = 'NO_CONTENT';
     }
     //-----------------------------------------
     // Get topic
     //-----------------------------------------
     try {
         $topic = $this->replySetUp();
     } catch (Exception $error) {
         $this->_postErrors = $error->getMessage();
     }
     //-----------------------------------------
     // Parse the post, and check for any errors.
     //-----------------------------------------
     $post = $this->compilePostData();
     $forumData = $this->getForumData();
     //-----------------------------------------
     // Do we have a valid post?
     // alt+255 = chr(160) = blank space
     //-----------------------------------------
     if (strlen(trim(IPSText::removeControlCharacters(IPSText::br2nl($post['post'])))) < 1 and !$this->getIsPreview()) {
         $this->_postErrors = 'post_too_short';
     }
     if (IPSText::mbstrlen($post['post']) > $this->settings['max_post_length'] * 1024 and !$this->getIsPreview()) {
         $this->_postErrors = 'post_too_long';
     }
     //-----------------------------------------
     // Compile the poll
     //-----------------------------------------
     $this->poll_questions = $this->compilePollData();
     if ($this->_postErrors != "" or $this->getIsPreview() === TRUE) {
         //-----------------------------------------
         // Show the form again
         //-----------------------------------------
         return FALSE;
     }
     //-----------------------------------------
     // Insert the post into the database to get the
     // last inserted value of the auto_increment field
     //-----------------------------------------
     $post['topic_id'] = $topic['tid'];
     //-----------------------------------------
     // Merge concurrent posts?
     //-----------------------------------------
     if ($this->getAuthor('member_id') and $this->settings['post_merge_conc']) {
         //-----------------------------------------
         // Get check time
         //-----------------------------------------
         $time_check = IPS_UNIX_TIME_NOW - $this->settings['post_merge_conc'] * 60;
         //-----------------------------------------
         // Last to post?
         //-----------------------------------------
         if ($topic['last_post'] > $time_check and $topic['last_poster_id'] == $this->getAuthor('member_id')) {
             //-----------------------------------------
             // Get the last post. 2 queries more efficient
             // than one... trust me
             //-----------------------------------------
             $last_pid = $this->DB->buildAndFetch(array('select' => 'MAX(pid) as maxpid', 'from' => 'posts', 'where' => 'topic_id=' . $topic['tid'], 'limit' => array(0, 1)));
             $last_post = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'posts', 'where' => 'pid=' . intval($last_pid['maxpid'])));
             //-----------------------------------------
             // Sure we're the last poster?
             //-----------------------------------------
             if ($last_post['author_id'] == $this->getAuthor('member_id')) {
                 $orig_post = $post['post'];
                 $new_post = $last_post['post'] . '<br />' . $post['post'];
                 //-----------------------------------------
                 // Make sure we don't have too many images
                 //-----------------------------------------
                 /* Load parser */
                 $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/text/parser.php', 'classes_text_parser');
                 $parser = new $classToLoad();
                 $parser->testForParsingLimits($new_post);
                 if (is_array($parser->getErrors()) && count($parser->getErrors())) {
                     $this->_postErrors = 'merge_' . array_pop($parser->getErrors());
                     $this->showReplyForm();
                     return;
                 }
                 //-----------------------------------------
                 // Update post row
                 //-----------------------------------------
                 $this->DB->setDataType('pid', 'int');
                 $this->DB->setDataType('post', 'string');
                 $_autoMergeData = array('post' => $new_post, 'post_date' => IPS_UNIX_TIME_NOW, 'pid' => $last_post['pid']);
                 /* Data Hook Location */
                 IPSLib::doDataHooks($_autoMergeData, 'postAutoMerge');
                 /* Terabyte didn't notice a bug in this location since fixed */
                 unset($_autoMergeData['pid']);
                 $this->DB->update('posts', $_autoMergeData, 'pid=' . $last_post['pid']);
                 /* Add to cache */
                 IPSContentCache::drop('post', $last_post['pid']);
                 // Commented out for bug #14252, replace is unreliable
                 //IPSContentCache::update( $last_post['pid'], 'post', $this->formatPostForCache( $new_post ) );
                 $post['pid'] = $last_post['pid'];
                 $post['post_key'] = $last_post['post_key'];
                 $post['post'] = $new_post;
                 $this->_isMergingPosts = 1;
                 /* Make sure we reset the post key for attachments */
                 $this->DB->update('attachments', array('attach_post_key' => $post['post_key']), "attach_rel_module='post' AND attach_post_key='" . $this->post_key . "'");
             }
         }
     }
     //-----------------------------------------
     // No?
     //-----------------------------------------
     if (!$this->_isMergingPosts) {
         //-----------------------------------------
         // Add post to DB
         //-----------------------------------------
         $post['post_key'] = $this->post_key;
         //-----------------------------------------
         // Typecast
         //-----------------------------------------
         $this->DB->setDataType('pid', 'int');
         $this->DB->setDataType('post', 'string');
         /* Data Hook Location */
         IPSLib::doDataHooks($post, 'postAddReply');
         /* Finally insert.. */
         $this->DB->insert('posts', $post);
         $post['pid'] = $this->DB->getInsertId();
         //-----------------------------------------
         // Require pre-approval of posts?
         //-----------------------------------------
         if ($post['queued']) {
             $this->DB->insert('mod_queued_items', array('type' => 'post', 'type_id' => $post['pid']));
             /*noLibHook*/
         }
         /* Add to cache */
         IPSContentCache::update($post['pid'], 'post', $this->formatPostForCache($post['post']));
     }
     //-----------------------------------------
     // If we are still here, lets update the
     // board/forum/topic stats
     //-----------------------------------------
     $this->updateForumAndStats($topic, 'reply');
     //-----------------------------------------
     // Update view counts
     //-----------------------------------------
     $this->updateViewCounter($topic['tid']);
     //-----------------------------------------
     // Get the correct number of replies
     //-----------------------------------------
     $this->DB->build(array('select' => 'COUNT(*) as posts', 'from' => 'posts', 'where' => "topic_id={$topic['tid']} AND " . $this->registry->class_forums->fetchPostHiddenQuery(array('visible'))));
     $this->DB->execute();
     $posts = $this->DB->fetch();
     $pcount = intval($posts['posts'] - 1);
     //-----------------------------------------
     // Get the correct number of queued replies
     //-----------------------------------------
     $this->DB->build(array('select' => 'COUNT(*) as posts', 'from' => 'posts', 'where' => "topic_id={$topic['tid']} AND " . $this->registry->class_forums->fetchPostHiddenQuery(array('hidden'))));
     $this->DB->execute();
     $qposts = $this->DB->fetch();
     $qpcount = intval($qposts['posts']);
     //-----------------------------------------
     // Get the correct number of deleted replies
     //-----------------------------------------
     $this->DB->build(array('select' => 'COUNT(*) as posts', 'from' => 'posts', 'where' => "topic_id={$topic['tid']} AND " . $this->registry->class_forums->fetchPostHiddenQuery(array('sdeleted'))));
     $this->DB->execute();
     $qposts = $this->DB->fetch();
     $dcount = intval($qposts['posts']);
     //-----------------------------------------
     // UPDATE TOPIC
     //-----------------------------------------
     $poster_name = $this->getAuthor('member_id') ? $this->getAuthor('members_display_name') : $this->request['UserName'];
     $update_array = array('posts' => $pcount, 'topic_queuedposts' => $qpcount, 'topic_deleted_posts' => $dcount);
     if ($this->getPublished()) {
         $update_array['last_poster_id'] = $this->getAuthor('member_id');
         $update_array['last_poster_name'] = $poster_name;
         $update_array['seo_last_name'] = IPSText::makeSeoTitle($poster_name);
         $update_array['last_post'] = IPS_UNIX_TIME_NOW;
         $update_array['pinned'] = $topic['pinned'];
         $update_array['last_real_post'] = IPS_UNIX_TIME_NOW;
         $update_array['state'] = $topic['state'];
         if (count($this->poll_questions) and $this->can_add_poll) {
             $update_array['poll_state'] = 1;
         }
     }
     /* Typecast */
     $this->DB->setDataType(array('title', 'starter_name', 'seo_last_name', 'last_poster_name'), 'string');
     /* Data Hook Location */
     IPSLib::doDataHooks($update_array, 'postAddReplyTopicUpdate');
     $this->DB->update('topics', $update_array, "tid={$topic['tid']}");
     //-----------------------------------------
     // Add the poll to the polls table
     //-----------------------------------------
     if (count($this->poll_questions) and $this->can_add_poll) {
         $poll_only = 0;
         if ($this->settings['ipb_poll_only'] and ipsRegistry::$request['poll_only'] == 1) {
             $poll_only = 1;
         }
         $_pollData = array('tid' => $topic['tid'], 'forum_id' => $this->getForumData('id'), 'start_date' => IPS_UNIX_TIME_NOW, 'choices' => serialize($this->poll_questions), 'starter_id' => $this->getAuthor('member_id'), 'votes' => 0, 'poll_question' => ipsRegistry::$request['poll_question'], 'poll_only' => $poll_only);
         /* Data Hook Location */
         IPSLib::doDataHooks($_pollData, 'postAddReplyPoll');
         $this->DB->insert('polls', $_pollData);
     }
     //-----------------------------------------
     // If we are a member, lets update thier last post
     // date and increment their post count.
     //-----------------------------------------
     if (!$this->_isMergingPosts) {
         $this->incrementUsersPostCount();
     }
     /* Upload Attachments */
     $this->uploadAttachments($post['post_key'], $post['pid']);
     //-----------------------------------------
     // Make attachments "permanent"
     //-----------------------------------------
     $this->makeAttachmentsPermanent($post['post_key'], $post['pid'], 'post', array('topic_id' => $topic['tid']));
     //-----------------------------------------
     // Send out notifications
     //-----------------------------------------
     if (!$this->_isMergingPosts and $this->getPublished() === FALSE) {
         $this->sendNewTopicForApprovalEmails($topic['tid'], $topic['title'], $topic['starter_name'], $post['post'], $post['pid'], 'reply');
     }
     //-----------------------------------------
     // Are we tracking topics we reply in 'auto_track'?
     //-----------------------------------------
     $this->addTopicToTracker($topic['tid'], 1);
     //-----------------------------------------
     // Moderating?
     //-----------------------------------------
     if (!$this->_isMergingPosts and $this->getPublished() === FALSE and $this->getIsAjax() !== TRUE) {
         $page = floor($topic['posts'] / $this->settings['display_max_posts']);
         $page = $page * $this->settings['display_max_posts'];
         ipsRegistry::getClass('output')->redirectScreen($this->lang->words['moderate_post'], $this->settings['base_url'] . "showtopic={$topic['tid']}&st={$page}");
     } else {
         if (!$this->_isMergingPosts and $this->getPublished() === FALSE and $this->getIsAjax() === TRUE) {
             //-----------------------------------------
             // Leave data for other apps
             //-----------------------------------------
             $this->setTopicData($topic);
             $this->setPostData($post);
             return TRUE;
         }
     }
     /* remove saved content */
     if ($this->memberData['member_id']) {
         $this->editor->removeAutoSavedContent(array('member_id' => $this->memberData['member_id'], 'autoSaveKey' => 'reply-' . intval($topic['tid'])));
     }
     /* add to recent post cache */
     if (!$this->_isMergingPosts && $this->memberData['member_id']) {
         $this->registry->topics->addRecentPost(array('post_id' => $post['pid'], 'post_topic_id' => $topic['tid'], 'post_forum_id' => $topic['forum_id'], 'post_author_id' => $this->memberData['member_id'], 'post_date' => IPS_UNIX_TIME_NOW));
     }
     //-----------------------------------------
     // Check for subscribed topics
     // XXPass on the previous last post time of the topic
     // 12.26.2007 - we want to send email if the new post was
     // made after the member's last visit...which should be
     // last_activity minus session expiration
     // to see if we need to send emails out
     //-----------------------------------------
     $notificationsSentTo = $this->sendOutTrackedTopicEmails($topic, $post['post'], $poster_name);
     //-----------------------------------------
     // Send notification of post quoted
     //-----------------------------------------
     $_post = $post;
     /* If we're merging use only the new post data. #39158 */
     if (!$this->_isMergingPosts) {
         $this->sendOutQuoteNotifications($_post, $notificationsSentTo);
     } else {
         $_post['post'] = $orig_post;
         $this->sendOutQuoteNotifications($_post, $notificationsSentTo);
     }
     /* Mark as read */
     $this->registry->getClass('classItemMarking')->markRead(array('forumID' => $forumData['id'], 'itemID' => $topic['tid'], 'markDate' => IPS_UNIX_TIME_NOW, 'containerLastActivityDate' => $forumData['last_post']), 'forums');
     //-----------------------------------------
     // Leave data for other apps
     //-----------------------------------------
     $this->setTopicData($topic);
     $this->setPostData($post);
     return TRUE;
 }
Ejemplo n.º 3
0
 /**
  * Delete a topic
  *
  * @param	mixed 		Topic id | Array of topic ids
  * @param	boolean		Skip updating the stats
  * @return	boolean
  */
 public function topicDeleteFromDB($id, $nostats = 0)
 {
     $posts = array();
     $attach = array();
     $this->error = "";
     $ids = array();
     if (is_array($id)) {
         $id = IPSLib::cleanIntArray($id);
         if (count($id) > 0) {
             $ids = $id;
             $tid = " IN(" . implode(",", $id) . ")";
         } else {
             return false;
         }
     } else {
         if (intval($id)) {
             $ids = array($id);
             $tid = "={$id}";
         } else {
             return false;
         }
     }
     /* GET AND EXAMINE */
     $topics = $this->registry->topics->getTopics(array('topicId' => $ids, 'archiveState' => array('not', 'exclude'), 'topicType' => array('all')));
     if (!count($topics)) {
         return false;
     } else {
         $ids = array_keys($topics);
         $tid = " IN(" . implode(",", $ids) . ")";
     }
     /* Remove from deletion log */
     IPSDeleteLog::removeEntries($ids, 'topic', TRUE);
     /* Tagging */
     $this->registry->tags->deleteByMetaId($ids);
     /* Delete from recent posts */
     $this->registry->topics->deleteRecentPost(array('post_topic_id' => $ids));
     //-----------------------------------------
     // Remove polls assigned to this topic
     //-----------------------------------------
     $this->DB->delete('polls', "tid" . $tid);
     $this->DB->delete('voters', "tid" . $tid);
     $this->DB->delete('topic_ratings', "rating_tid" . $tid);
     $this->DB->delete('topic_views', "views_tid" . $tid);
     $this->DB->delete('topics', "tid" . $tid);
     //-----------------------------------------
     // Like class
     //-----------------------------------------
     require_once IPS_ROOT_PATH . 'sources/classes/like/composite.php';
     /*noLibHook*/
     $_like = classes_like::bootstrap('forums', 'topics');
     $_like->remove($ids);
     //-----------------------------------------
     // Get PIDS for attachment deletion
     //-----------------------------------------
     $this->DB->build(array('select' => 'pid', 'from' => 'posts', 'where' => "topic_id" . $tid));
     $this->DB->execute();
     while ($r = $this->DB->fetch()) {
         $posts[] = $r['pid'];
     }
     /* Remove cache content */
     IPSContentCache::drop('post', $posts);
     //-----------------------------------------
     // Remove the attachments
     //-----------------------------------------
     $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('core') . '/sources/classes/attach/class_attach.php', 'class_attach');
     $class_attach = new $classToLoad($this->registry);
     $class_attach->type = 'post';
     $class_attach->init();
     $class_attach->bulkRemoveAttachment($posts);
     //-----------------------------------------
     // Remove the posts
     //-----------------------------------------
     $this->DB->delete('posts', "topic_id" . $tid);
     if (count($posts)) {
         $this->DB->delete('reputation_cache', "app='forums' AND type='pid' AND type_id IN (" . implode(',', $posts) . ")");
         $this->DB->delete('reputation_index', "app='forums' AND type='pid' AND type_id IN (" . implode(',', $posts) . ")");
         $this->DB->delete('reputation_totals', "rt_key=MD5('forums;pid') AND rt_type_id IN (" . implode(',', $posts) . ")");
     }
     //-----------------------------------------
     // Recount forum...
     //-----------------------------------------
     if (!$nostats) {
         if ($this->forum['id']) {
             $this->registry->class_forums->allForums[$this->forum['id']]['_update_deletion'] = 1;
             $this->forumRecount($this->forum['id']);
         }
         $this->cache->rebuildCache('stats', 'global');
     }
     /* Run moderation sync */
     $this->runModSync('topicDelete', $ids);
     return TRUE;
 }
 /**
  * Delete member(s)
  *
  * @access	public
  * @param 	mixed		[Integer] member ID or [Array] array of member ids
  * @param	boolean		Check if request is from an admin
  * @return	boolean		Action completed successfully
  */
 public static function remove($id, $check_admin = true)
 {
     //-----------------------------------------
     // INIT
     //-----------------------------------------
     $tmp_mids = array();
     $emails = array();
     //-----------------------------------------
     // Sort out thingie
     //-----------------------------------------
     if (is_array($id)) {
         $id = IPSLib::cleanIntArray($id);
         $mids = ' IN (' . implode(",", $id) . ')';
     } else {
         $mids = ' = ' . intval($id);
     }
     //-----------------------------------------
     // Get accounts and check IDS
     //-----------------------------------------
     ipsRegistry::DB()->build(array('select' => 'm.member_id, m.name, m.member_group_id, m.email', 'from' => array('members' => 'm'), 'where' => 'm.member_id' . $mids, 'add_join' => array(array('select' => 'g.g_access_cp', 'from' => array('groups' => 'g'), 'where' => 'g.g_id=m.member_group_id', 'type' => 'left'))));
     ipsRegistry::DB()->execute();
     while ($r = ipsRegistry::DB()->fetch()) {
         //-----------------------------------------
         // Non root admin attempting to edit root admin?
         //-----------------------------------------
         if ($check_admin) {
             if (!ipsRegistry::member()->getProperty('g_access_cp')) {
                 if ($r['g_access_cp']) {
                     continue;
                 }
             }
         }
         $tmp_mids[] = $r['member_id'];
         $emails[] = $r['email'];
         self::_removeFromCache($r['member_id']);
     }
     if (!count($tmp_mids)) {
         return false;
     }
     $mids = ' IN (' . implode(",", $tmp_mids) . ')';
     //-----------------------------------------
     // Get avatars / photo
     //-----------------------------------------
     $delete_files = array();
     ipsRegistry::DB()->build(array('select' => '*', 'from' => 'profile_portal', 'where' => 'pp_member_id' . $mids));
     ipsRegistry::DB()->execute();
     while ($r = ipsRegistry::DB()->fetch()) {
         if ($r['pp_main_photo']) {
             $delete_files[] = $r['pp_main_photo'];
         }
         if ($r['pp_thumb_photo']) {
             $delete_files[] = $r['pp_thumb_photo'];
         }
         if ($r['avatar_type'] == 'upload' and $r['avatar_location']) {
             $delete_files[] = $r['avatar_location'];
         }
     }
     //-----------------------------------------
     // Take care of forum stuff
     //-----------------------------------------
     ipsRegistry::DB()->update('posts', array('author_id' => 0), "author_id" . $mids);
     ipsRegistry::DB()->update('topics', array('starter_id' => 0), "starter_id" . $mids);
     ipsRegistry::DB()->update('announcements', array('announce_member_id' => 0), "announce_member_id" . $mids);
     ipsRegistry::DB()->update('attachments', array('attach_member_id' => 0), "attach_member_id" . $mids);
     ipsRegistry::DB()->update('polls', array('starter_id' => 0), "starter_id" . $mids);
     //ipsRegistry::DB()->update( 'topic_ratings'			, array( 'rating_member_id' => 0 ), "rating_member_id" . $mids );
     ipsRegistry::DB()->update('voters', array('member_id' => 0), "member_id" . $mids);
     ipsRegistry::DB()->update('forums', array('last_poster_name' => ''), "last_poster_id" . $mids);
     ipsRegistry::DB()->update('forums', array('seo_last_name' => ''), "last_poster_id" . $mids);
     ipsRegistry::DB()->update('forums', array('last_poster_id' => 0), "last_poster_id" . $mids);
     //-----------------------------------------
     // Clean up profile stuff
     //-----------------------------------------
     ipsRegistry::DB()->update('profile_comments', array('comment_by_member_id' => 0), "comment_by_member_id" . $mids);
     ipsRegistry::DB()->update('profile_ratings', array('rating_by_member_id' => 0), "rating_by_member_id" . $mids);
     ipsRegistry::DB()->delete('profile_comments', "comment_for_member_id" . $mids);
     ipsRegistry::DB()->delete('profile_ratings', "rating_for_member_id" . $mids);
     ipsRegistry::DB()->delete('profile_portal', "pp_member_id" . $mids);
     ipsRegistry::DB()->delete('profile_portal_views', "views_member_id" . $mids);
     ipsRegistry::DB()->delete('profile_friends', "friends_member_id" . $mids);
     ipsRegistry::DB()->delete('profile_friends', "friends_friend_id" . $mids);
     ipsRegistry::DB()->delete('dnames_change', "dname_member_id" . $mids);
     //-----------------------------------------
     // Delete member...
     //-----------------------------------------
     ipsRegistry::DB()->delete('pfields_content', "member_id" . $mids);
     ipsRegistry::DB()->delete('members_partial', "partial_member_id" . $mids);
     ipsRegistry::DB()->delete('moderators', "member_id" . $mids);
     ipsRegistry::DB()->delete('sessions', "member_id" . $mids);
     ipsRegistry::DB()->delete('warn_logs', "wlog_mid" . $mids);
     ipsRegistry::DB()->update('warn_logs', array('wlog_addedby' => 0), "wlog_addedby" . $mids);
     //-----------------------------------------
     // Update admin stuff
     //-----------------------------------------
     ipsRegistry::DB()->delete('admin_permission_rows', "row_id_type='member' AND row_id" . $mids);
     ipsRegistry::DB()->delete('core_sys_cp_sessions', 'session_member_id' . $mids);
     ipsRegistry::DB()->update('upgrade_history', array('upgrade_mid' => 0), "upgrade_mid" . $mids);
     //-----------------------------------------
     // Fix up member messages...
     //-----------------------------------------
     ipsRegistry::DB()->delete('message_topic_user_map', 'map_user_id' . $mids);
     ipsRegistry::DB()->update('message_posts', array('msg_author_id' => 0), 'msg_author_id' . $mids);
     ipsRegistry::DB()->update('message_topics', array('mt_starter_id' => 0), 'mt_starter_id' . $mids);
     ipsRegistry::DB()->delete('ignored_users', "ignore_owner_id" . $mids . " or ignore_ignore_id" . $mids);
     //-----------------------------------------
     // Delete subs, views, markers
     //-----------------------------------------
     ipsRegistry::DB()->delete('tracker', "member_id" . $mids);
     ipsRegistry::DB()->delete('forum_tracker', "member_id" . $mids);
     ipsRegistry::DB()->delete('core_item_markers', "item_member_id" . $mids);
     //-----------------------------------------
     // Delete from validating..
     //-----------------------------------------
     ipsRegistry::DB()->delete('validating', "member_id" . $mids);
     ipsRegistry::DB()->delete('members', "member_id" . $mids);
     //-----------------------------------------
     // Delete avatars / photos
     //-----------------------------------------
     if (count($delete_files)) {
         foreach ($delete_files as $file) {
             @unlink(ipsRegistry::$settings['upload_dir'] . "/" . $file);
         }
     }
     //-----------------------------------------
     // Member Sync
     //-----------------------------------------
     IPSLib::runMemberSync('onDelete', $mids);
     /* Remove from cache */
     IPSContentCache::drop('sig', $tmp_mids);
     //-----------------------------------------
     // Get current stats...
     //-----------------------------------------
     ipsRegistry::cache()->rebuildCache('stats', 'global');
     ipsRegistry::cache()->rebuildCache('moderators', 'global');
 }
Ejemplo n.º 5
0
 /**
  * Delete member(s)
  *
  * @param 	mixed		[Integer] member ID or [Array] array of member ids
  * @param	boolean		Check if request is from an admin
  * @return	boolean		Action completed successfully
  */
 public static function remove($id, $check_admin = true)
 {
     /* Init vars */
     $mids = '';
     $tmp_mids = array();
     $emails = array();
     //-----------------------------------------
     // Sort out thingie
     //-----------------------------------------
     if (is_array($id)) {
         $id = IPSLib::cleanIntArray($id);
         if (count($id)) {
             $mids = ' IN (' . implode(",", $id) . ')';
         }
     } else {
         $id = intval($id);
         if ($id > 0) {
             $mids = ' = ' . $id;
         }
     }
     if (empty($mids)) {
         return false;
     }
     //-----------------------------------------
     // Get accounts and check IDS
     //-----------------------------------------
     ipsRegistry::DB()->build(array('select' => 'm.member_id, m.name, m.member_group_id, m.email', 'from' => array('members' => 'm'), 'where' => 'm.member_id' . $mids, 'add_join' => array(array('select' => 'g.g_access_cp', 'from' => array('groups' => 'g'), 'where' => 'g.g_id=m.member_group_id', 'type' => 'left'))));
     ipsRegistry::DB()->execute();
     while ($r = ipsRegistry::DB()->fetch()) {
         //-----------------------------------------
         // Non root admin attempting to edit root admin?
         //-----------------------------------------
         if ($check_admin) {
             if (!ipsRegistry::member()->getProperty('g_access_cp')) {
                 if ($r['g_access_cp']) {
                     continue;
                 }
             }
         }
         $tmp_mids[] = $r['member_id'];
         $emails[] = $r['email'];
         self::_removeFromCache($r['member_id']);
     }
     if (!count($tmp_mids)) {
         return false;
     }
     $mids = ' IN (' . implode(",", $tmp_mids) . ')';
     //-----------------------------------------
     // Login modules
     // (Have to do this first otherwise we've
     // deleted stuff we may need like email, etc.)
     //-----------------------------------------
     $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/handlers/han_login.php', 'han_login');
     $han_login = new $classToLoad(ipsRegistry::instance());
     $han_login->init();
     $han_login->deleteAccount($id);
     //-----------------------------------------
     // Get photo
     //-----------------------------------------
     $delete_files = array();
     ipsRegistry::DB()->build(array('select' => '*', 'from' => 'profile_portal', 'where' => 'pp_member_id' . $mids));
     ipsRegistry::DB()->execute();
     while ($r = ipsRegistry::DB()->fetch()) {
         if ($r['pp_main_photo']) {
             $delete_files[] = $r['pp_main_photo'];
         }
         if ($r['pp_thumb_photo']) {
             $delete_files[] = $r['pp_thumb_photo'];
         }
         $_customizations = IPSLib::safeUnserialize($r['pp_customization']);
         if ($_customizations['type'] == 'upload' and $_customizations['bg_url']) {
             $delete_files[] = $_customizations['bg_url'];
         }
     }
     //-----------------------------------------
     // Take care of forum stuff
     //-----------------------------------------
     ipsRegistry::DB()->update('posts', array('author_id' => 0), "author_id" . $mids);
     ipsRegistry::DB()->update('topics', array('starter_id' => 0), "starter_id" . $mids);
     ipsRegistry::DB()->update('topics', array('last_poster_id' => 0), "last_poster_id" . $mids);
     ipsRegistry::DB()->update('announcements', array('announce_member_id' => 0), "announce_member_id" . $mids);
     ipsRegistry::DB()->update('attachments', array('attach_member_id' => 0), "attach_member_id" . $mids);
     ipsRegistry::DB()->update('polls', array('starter_id' => 0), "starter_id" . $mids);
     /**
      * @todo	Why is this query commented? Need to investigate and change for 3.4 if needed
      */
     //ipsRegistry::DB()->update( 'topic_ratings'			, array( 'rating_member_id' => 0 ), "rating_member_id" . $mids );
     ipsRegistry::DB()->update('voters', array('member_id' => 0), "member_id" . $mids);
     ipsRegistry::DB()->update('forums', array('last_poster_id' => 0, 'last_poster_name' => '', 'seo_last_name' => ''), "last_poster_id" . $mids);
     ipsRegistry::DB()->delete('core_share_links_log', "log_member_id" . $mids);
     ipsRegistry::DB()->delete('core_soft_delete_log', "sdl_obj_member_id" . $mids);
     ipsRegistry::DB()->delete('mobile_device_map', "member_id" . $mids);
     ipsRegistry::DB()->update('rss_import', array('rss_import_mid' => 0), "rss_import_mid" . $mids);
     ipsRegistry::DB()->update('core_tags', array('tag_member_id' => 0), "tag_member_id" . $mids);
     /* Update archived posts */
     $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/archive/writer.php', 'classes_archive_writer');
     $archiveWriter = new $classToLoad();
     $archiveWriter->setApp('forums');
     $archiveWriter->update(array('archive_author_id' => 0), 'archive_author_id' . $mids);
     //-----------------------------------------
     // Likes - also invalidates likes cache
     // @todo - Move this into like class - problem is like object expects to know what plugin to use in bootstrap method, but we want to remove for all plugins...
     //-----------------------------------------
     $_likes = array();
     ipsRegistry::DB()->build(array('select' => 'like_lookup_id', 'from' => 'core_like', 'where' => "like_member_id" . $mids));
     ipsRegistry::DB()->execute();
     while ($r = ipsRegistry::DB()->fetch()) {
         $_likes[] = $r['like_lookup_id'];
     }
     if (count($_likes)) {
         ipsRegistry::DB()->delete('core_like', "like_member_id" . $mids);
         ipsRegistry::DB()->delete('core_like_cache', "like_cache_id IN('" . implode("','", array_map('addslashes', $_likes)) . "')");
     }
     //-----------------------------------------
     // Clean up profile stuff
     //-----------------------------------------
     ipsRegistry::DB()->update('profile_ratings', array('rating_by_member_id' => 0), "rating_by_member_id" . $mids);
     ipsRegistry::DB()->delete('profile_ratings', "rating_for_member_id" . $mids);
     ipsRegistry::DB()->delete('profile_portal', "pp_member_id" . $mids);
     ipsRegistry::DB()->delete('profile_portal_views', "views_member_id" . $mids);
     $_friendMemberIds = array();
     ipsRegistry::DB()->build(array('select' => '*', 'from' => 'profile_friends', 'where' => "friends_member_id" . $mids . " OR friends_friend_id" . $mids));
     ipsRegistry::DB()->execute();
     while ($r = ipsRegistry::DB()->fetch()) {
         if (!in_array($r['friends_friend_id'], $tmp_mids)) {
             $_friendMemberIds[$r['friends_friend_id']] = $r['friends_friend_id'];
         }
         if (!in_array($r['friends_member_id'], $tmp_mids)) {
             $_friendMemberIds[$r['friends_member_id']] = $r['friends_member_id'];
         }
     }
     ipsRegistry::DB()->delete('profile_friends', "friends_member_id" . $mids);
     ipsRegistry::DB()->delete('profile_friends', "friends_friend_id" . $mids);
     ipsRegistry::DB()->delete('profile_friends_flood', "friends_member_id" . $mids . " OR friends_friend_id" . $mids);
     ipsRegistry::DB()->delete('dnames_change', "dname_member_id" . $mids);
     ipsRegistry::DB()->delete('mobile_notifications', "member_id" . $mids);
     //-----------------------------------------
     // Delete member...
     //-----------------------------------------
     ipsRegistry::DB()->delete('pfields_content', "member_id" . $mids);
     ipsRegistry::DB()->delete('members_partial', "partial_member_id" . $mids);
     ipsRegistry::DB()->delete('moderators', "member_id" . $mids);
     ipsRegistry::DB()->delete('sessions', "member_id" . $mids);
     ipsRegistry::DB()->delete('search_sessions', "session_member_id" . $mids);
     ipsRegistry::DB()->delete('upgrade_sessions', "session_member_id" . $mids);
     ipsRegistry::DB()->delete('members_warn_logs', "wl_member" . $mids);
     ipsRegistry::DB()->update('members_warn_logs', array('wl_moderator' => 0), "wl_moderator" . $mids);
     ipsRegistry::DB()->delete('member_status_actions', "action_member_id" . $mids);
     ipsRegistry::DB()->delete('member_status_actions', "action_status_owner" . $mids);
     ipsRegistry::DB()->delete('member_status_replies', "reply_member_id" . $mids);
     ipsRegistry::DB()->delete('member_status_updates', "status_member_id" . $mids);
     ipsRegistry::DB()->delete('member_status_updates', "status_author_id" . $mids);
     //-----------------------------------------
     // Update admin stuff and logs
     //-----------------------------------------
     ipsRegistry::DB()->delete('admin_permission_rows', "row_id_type='member' AND row_id" . $mids);
     ipsRegistry::DB()->delete('core_sys_cp_sessions', 'session_member_id' . $mids);
     ipsRegistry::DB()->delete('core_sys_login', 'sys_login_id' . $mids);
     ipsRegistry::DB()->update('upgrade_history', array('upgrade_mid' => 0), "upgrade_mid" . $mids);
     ipsRegistry::DB()->update('admin_logs', array('member_id' => 0), "member_id" . $mids);
     ipsRegistry::DB()->update('error_logs', array('log_member' => 0), "log_member" . $mids);
     ipsRegistry::DB()->update('moderator_logs', array('member_id' => 0, 'member_name' => ''), "member_id" . $mids);
     //-----------------------------------------
     // Delete PMs
     //-----------------------------------------
     $messageIds = array();
     ipsRegistry::DB()->build(array('select' => 'map_topic_id, map_user_id', 'from' => 'message_topic_user_map', 'where' => 'map_user_id' . $mids));
     ipsRegistry::DB()->execute();
     while ($r = ipsRegistry::DB()->fetch()) {
         $messageIds[$r['map_user_id']][] = $r['map_topic_id'];
     }
     if (count($messageIds)) {
         $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('members') . '/sources/classes/messaging/messengerFunctions.php', 'messengerFunctions', 'members');
         $messenger = new $classToLoad(ipsRegistry::instance());
         foreach ($messageIds as $user => $topics) {
             $messenger->deleteTopics($user, $topics);
         }
     }
     //-----------------------------------------
     // Fallback cleanup
     //-----------------------------------------
     ipsRegistry::DB()->delete('message_topic_user_map', 'map_user_id' . $mids);
     ipsRegistry::DB()->update('message_posts', array('msg_author_id' => 0), 'msg_author_id' . $mids);
     ipsRegistry::DB()->update('message_topics', array('mt_starter_id' => 0), 'mt_starter_id' . $mids);
     ipsRegistry::DB()->update('message_topics', array('mt_to_member_id' => 0), 'mt_to_member_id' . $mids);
     //-----------------------------------------
     // Delete subs, views, markers, etc.
     //-----------------------------------------
     ipsRegistry::DB()->delete('ignored_users', "ignore_owner_id" . $mids . " or ignore_ignore_id" . $mids);
     ipsRegistry::DB()->delete('inline_notifications', "notify_to_id" . $mids);
     ipsRegistry::DB()->update('inline_notifications', array('notify_from_id' => 0), 'notify_from_id' . $mids);
     ipsRegistry::DB()->delete('core_item_markers', "item_member_id" . $mids);
     ipsRegistry::DB()->delete('core_item_markers_storage', "item_member_id" . $mids);
     ipsRegistry::DB()->update('rc_comments', array('comment_by' => 0), "comment_by" . $mids);
     ipsRegistry::DB()->delete('rc_modpref', "mem_id" . $mids);
     ipsRegistry::DB()->update('rc_reports', array('report_by' => 0), "report_by" . $mids);
     ipsRegistry::DB()->update('rc_reports_index', array('updated_by' => 0), "updated_by" . $mids);
     ipsRegistry::DB()->delete('rc_reports_index', "seotemplate='showuser' AND exdat1" . $mids);
     ipsRegistry::DB()->delete('reputation_cache', "type='member' AND type_id" . $mids);
     ipsRegistry::DB()->delete('reputation_index', "member_id" . $mids);
     $cache = ipsRegistry::cache()->getCache('report_cache');
     $cache['last_updated'] = time();
     ipsRegistry::cache()->setCache('report_cache', $cache, array('array' => 1));
     //-----------------------------------------
     // Delete from validating..
     //-----------------------------------------
     ipsRegistry::DB()->delete('validating', "member_id" . $mids);
     ipsRegistry::DB()->delete('members', "member_id" . $mids);
     /* Delete from profile cache */
     if (count($_friendMemberIds)) {
         $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('members') . '/sources/friends.php', 'profileFriendsLib', 'members');
         $friends = new $classToLoad(ipsRegistry::instance());
         foreach ($_friendMemberIds as $_mid) {
             $friends->recacheFriends(array('member_id' => $_mid));
         }
     }
     //-----------------------------------------
     // Delete photos
     //-----------------------------------------
     if (count($delete_files)) {
         foreach ($delete_files as $file) {
             @unlink(ipsRegistry::$settings['upload_dir'] . "/" . $file);
         }
     }
     //-----------------------------------------
     // memberSync
     //-----------------------------------------
     IPSLib::runMemberSync('onDelete', $mids);
     //-----------------------------------------
     // Remove from cache
     //-----------------------------------------
     IPSContentCache::drop('sig', $tmp_mids);
     //-----------------------------------------
     // Get current stats...
     //-----------------------------------------
     ipsRegistry::cache()->rebuildCache('stats', 'global');
     ipsRegistry::cache()->rebuildCache('moderators', 'forums');
     ipsRegistry::cache()->rebuildCache('birthdays', 'calendar');
     ipsRegistry::cache()->rebuildCache('announcements', 'forums');
     return true;
 }
 /**
  * Post a reply
  * Very simply posts a reply. Simple.
  *
  * Usage:
  * $post->setTopicID(100);
  * $post->setForumID(5);
  * $post->setAuthor( $member );
  * 
  * $post->setPostContent( "Hello [b]there![/b]" );
  * # Optional: No bbcode, etc parsing will take place
  * # $post->setPostContentPreFormatted( "Hello [b]there![/b]" );
  * $post->addReply();
  *
  * Exception Error Codes:
  * NO_TOPIC_ID       : No topic ID set
  * NO_FORUM_ID		: No forum ID set
  * NO_AUTHOR_SET	    : No Author set
  * NO_CONTENT        : No post content set
  * NO_SUCH_TOPIC     : No such topic
  * NO_SUCH_FORUM		: No such forum
  * NO_REPLY_PERM     : Author cannot reply to this topic
  * TOPIC_LOCKED		: The topic is locked
  * NO_REPLY_POLL     : Cannot reply to this poll only topic
  * TOPIC_LOCKED		: The topic is locked
  * NO_POST_FORUM		: Unable to post in that forum
  * FORUM_LOCKED		: Forum read only
  *
  * @access	public
  * @return	mixed	Exception, boolean, or void
  */
 public function addReply()
 {
     //-----------------------------------------
     // Set up
     //-----------------------------------------
     $topic_id = intval($this->getTopicID());
     $forum_id = intval($this->getForumID());
     //-----------------------------------------
     // Global checks and functions
     //-----------------------------------------
     try {
         $this->globalSetUp();
     } catch (Exception $error) {
         $this->_postErrors = $error->getMessage();
     }
     if (!$this->getPostContent() and !$this->getPostContentPreFormatted() and !$this->getIsPreview()) {
         $this->_postErrors = 'NO_CONTENT';
     }
     //-----------------------------------------
     // Get topic
     //-----------------------------------------
     try {
         $topic = $this->replySetUp();
     } catch (Exception $error) {
         $this->_postErrors = $error->getMessage();
     }
     //-----------------------------------------
     // Parse the post, and check for any errors.
     //-----------------------------------------
     $post = $this->compilePostData();
     //-----------------------------------------
     // Do we have a valid post?
     // alt+255 = chr(160) = blank space
     //-----------------------------------------
     if (strlen(trim(IPSText::removeControlCharacters(IPSText::br2nl($post['post'])))) < 1 and !$this->getIsPreview()) {
         $this->_postErrors = 'post_too_short';
     }
     if (IPSText::mbstrlen($postContent) > $this->settings['max_post_length'] * 1024 and !$this->getIsPreview()) {
         $this->_postErrors = 'post_too_long';
     }
     //-----------------------------------------
     // Compile the poll
     //-----------------------------------------
     $this->poll_questions = $this->compilePollData();
     if ($this->_postErrors != "" or $this->getIsPreview() === TRUE) {
         //-----------------------------------------
         // Show the form again
         //-----------------------------------------
         return FALSE;
     }
     //-----------------------------------------
     // Insert the post into the database to get the
     // last inserted value of the auto_increment field
     //-----------------------------------------
     $post['topic_id'] = $topic['tid'];
     //-----------------------------------------
     // Merge concurrent posts?
     //-----------------------------------------
     if ($this->getAuthor('member_id') and $this->settings['post_merge_conc']) {
         //-----------------------------------------
         // Get check time
         //-----------------------------------------
         $time_check = time() - $this->settings['post_merge_conc'] * 60;
         //-----------------------------------------
         // Last to post?
         //-----------------------------------------
         if ($topic['last_post'] > $time_check and $topic['last_poster_id'] == $this->getAuthor('member_id')) {
             //-----------------------------------------
             // Get the last post. 2 queries more efficient
             // than one... trust me
             //-----------------------------------------
             $last_pid = $this->DB->buildAndFetch(array('select' => 'MAX(pid) as maxpid', 'from' => 'posts', 'where' => 'topic_id=' . $topic['tid'], 'limit' => array(0, 1)));
             $last_post = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'posts', 'where' => 'pid=' . $last_pid['maxpid']));
             //-----------------------------------------
             // Sure we're the last poster?
             //-----------------------------------------
             if ($last_post['author_id'] == $this->getAuthor('member_id')) {
                 $new_post = $last_post['post'] . '<br /><br />' . $post['post'];
                 //-----------------------------------------
                 // Make sure we don't have too many images
                 //-----------------------------------------
                 IPSText::getTextClass('bbcode')->parsing_section = 'topics';
                 IPSText::getTextClass('bbcode')->parsing_mgroup = $this->getAuthor('member_group_id');
                 IPSText::getTextClass('bbcode')->parsing_mgroup_others = $this->getAuthor('mgroup_others');
                 $test_post = IPSText::getTextClass('bbcode')->preEditParse($new_post);
                 $test_post = IPSText::getTextClass('bbcode')->preDbParse($test_post);
                 if (IPSText::getTextClass('bbcode')->error) {
                     $this->_postErrors = 'merge_' . IPSText::getTextClass('bbcode')->error;
                     $this->showReplyForm();
                     return;
                 }
                 //-----------------------------------------
                 // Update post row
                 //-----------------------------------------
                 $this->DB->force_data_type = array('pid' => 'int', 'post' => 'string');
                 $this->DB->update('posts', array('post' => $new_post, 'post_date' => time()), 'pid=' . $last_post['pid']);
                 /* Add to cache */
                 IPSContentCache::drop('post', $last_post['pid']);
                 // Commented out for bug #14252, replace is unreliable
                 //IPSContentCache::update( $last_post['pid'], 'post', $this->formatPostForCache( $new_post ) );
                 $post['pid'] = $last_post['pid'];
                 $post['post_key'] = $last_post['post_key'];
                 $post['post'] = $new_post;
                 $post_saved = 1;
                 $this->_isMergingPosts = 1;
                 /* Make sure we reset the post key for attachments */
                 $this->DB->update('attachments', array('attach_post_key' => $post['post_key']), "attach_rel_module='post' AND attach_post_key='" . $this->post_key . "'");
             }
         }
     }
     //-----------------------------------------
     // No?
     //-----------------------------------------
     if (!$this->_isMergingPosts) {
         //-----------------------------------------
         // Add post to DB
         //-----------------------------------------
         $post['post_key'] = $this->post_key;
         $post['post_parent'] = ipsRegistry::$request['parent_id'] ? intval(ipsRegistry::$request['parent_id']) : 0;
         //-----------------------------------------
         // Typecast
         //-----------------------------------------
         $this->DB->force_data_type = array('pid' => 'int', 'post' => 'string');
         $this->DB->insert('posts', $post);
         $post['pid'] = $this->DB->getInsertId();
         //-----------------------------------------
         // Require pre-approval of posts?
         //-----------------------------------------
         if ($post['queued']) {
             $this->DB->insert('mod_queued_items', array('type' => 'post', 'type_id' => $post['pid']));
         }
         /* Add to cache */
         IPSContentCache::update($post['pid'], 'post', $this->formatPostForCache($post['post']));
     }
     //-----------------------------------------
     // If we are still here, lets update the
     // board/forum/topic stats
     //-----------------------------------------
     $this->updateForumAndStats($topic, 'reply');
     //-----------------------------------------
     // Get the correct number of replies
     //-----------------------------------------
     $this->DB->build(array('select' => 'COUNT(*) as posts', 'from' => 'posts', 'where' => "topic_id={$topic['tid']} and queued != 1"));
     $this->DB->execute();
     $posts = $this->DB->fetch();
     $pcount = intval($posts['posts'] - 1);
     //-----------------------------------------
     // Get the correct number of queued replies
     //-----------------------------------------
     $this->DB->build(array('select' => 'COUNT(*) as posts', 'from' => 'posts', 'where' => "topic_id={$topic['tid']} and queued=1"));
     $this->DB->execute();
     $qposts = $this->DB->fetch();
     $qpcount = intval($qposts['posts']);
     //-----------------------------------------
     // UPDATE TOPIC
     //-----------------------------------------
     $poster_name = $this->getAuthor('member_id') ? $this->getAuthor('members_display_name') : ipsRegistry::$request['UserName'];
     $update_array = array('posts' => $pcount, 'topic_queuedposts' => $qpcount);
     if ($this->getPublished()) {
         $update_array['last_poster_id'] = $this->getAuthor('member_id');
         $update_array['last_poster_name'] = $poster_name;
         $update_array['seo_last_name'] = IPSText::makeSeoTitle($poster_name);
         $update_array['last_post'] = time();
         $update_array['pinned'] = $topic['pinned'];
         $update_array['state'] = $topic['state'];
         if (count($this->poll_questions) and $this->can_add_poll) {
             $update_array['poll_state'] = 1;
         }
     }
     $this->DB->force_data_type = array('title' => 'string', 'description' => 'string', 'starter_name' => 'string', 'seo_last_name' => 'string', 'last_poster_name' => 'string');
     $this->DB->update('topics', $update_array, "tid={$topic['tid']}");
     //-----------------------------------------
     // Add the poll to the polls table
     //-----------------------------------------
     if (count($this->poll_questions) and $this->can_add_poll) {
         $poll_only = 0;
         if ($this->settings['ipb_poll_only'] and ipsRegistry::$request['poll_only'] == 1) {
             $poll_only = 1;
         }
         $this->DB->insert('polls', array('tid' => $topic['tid'], 'forum_id' => $this->getForumData('id'), 'start_date' => time(), 'choices' => serialize($this->poll_questions), 'starter_id' => $this->getAuthor('member_id'), 'votes' => 0, 'poll_question' => ipsRegistry::$request['poll_question'], 'poll_only' => $poll_only));
     }
     //-----------------------------------------
     // If we are a member, lets update thier last post
     // date and increment their post count.
     //-----------------------------------------
     if (!$this->_isMergingPosts) {
         $this->incrementUsersPostCount();
     }
     /* Upload Attachments */
     $this->uploadAttachments($post['post_key'], $post['pid']);
     //-----------------------------------------
     // Make attachments "permanent"
     //-----------------------------------------
     $this->makeAttachmentsPermanent($post['post_key'], $post['pid'], 'post', array('topic_id' => $topic['tid']));
     //-----------------------------------------
     // Moderating?
     //-----------------------------------------
     if (!$this->_isMergingPosts and $this->getPublished() === FALSE) {
         //-----------------------------------------
         // Boing!!!
         //-----------------------------------------
         $this->sendNewTopicForApprovalEmails($topic['tid'], $topic['title'], $topic['starter_name'], $post['pid'], 'reply');
         $page = floor($topic['posts'] / $this->settings['display_max_posts']);
         $page = $page * $this->settings['display_max_posts'];
         ipsRegistry::getClass('output')->redirectScreen($this->lang->words['moderate_post'], $this->settings['base_url'] . "showtopic={$topic['tid']}&st={$page}");
     }
     //-----------------------------------------
     // Are we tracking topics we reply in 'auto_track'?
     //-----------------------------------------
     $this->addTopicToTracker($topic['tid'], 1);
     //-----------------------------------------
     // Check for subscribed topics
     // XXPass on the previous last post time of the topic
     // 12.26.2007 - we want to send email if the new post was
     // made after the member's last visit...which should be
     // last_activity minus session expiration
     // to see if we need to send emails out
     //-----------------------------------------
     $this->sendOutTrackedTopicEmails($topic['tid'], $post['post'], $poster_name, time() - $this->settings['session_expiration'], $this->getAuthor('member_id'));
     //-----------------------------------------
     // Leave data for other apps
     //-----------------------------------------
     $this->setTopicData($topic);
     $this->setPostData($post);
     return TRUE;
 }
 /**
  * Delete a topic
  *
  * @access	public
  * @param	mixed 		Topic id | Array of topic ids
  * @param	boolean		Skip updating the stats
  * @return	boolean
  */
 public function topicDelete($id, $nostats = 0)
 {
     $posts = array();
     $attach = array();
     $this->error = "";
     if (is_array($id)) {
         $id = IPSLib::cleanIntArray($id);
         if (count($id) > 0) {
             $tid = " IN(" . implode(",", $id) . ")";
         } else {
             return false;
         }
     } else {
         if (intval($id)) {
             $tid = "={$id}";
         } else {
             return false;
         }
     }
     //-----------------------------------------
     // Remove polls assigned to this topic
     //-----------------------------------------
     $this->DB->delete('polls', "tid" . $tid);
     $this->DB->delete('voters', "tid" . $tid);
     $this->DB->delete('tracker', "topic_id" . $tid);
     $this->DB->delete('topic_ratings', "rating_tid" . $tid);
     $this->DB->delete('topic_views', "views_tid" . $tid);
     $this->DB->delete('topics', "tid" . $tid);
     //-----------------------------------------
     // Get PIDS for attachment deletion
     //-----------------------------------------
     $this->DB->build(array('select' => 'pid', 'from' => 'posts', 'where' => "topic_id" . $tid));
     $this->DB->execute();
     while ($r = $this->DB->fetch()) {
         $posts[] = $r['pid'];
     }
     /* Remove cache content */
     IPSContentCache::drop('post', $posts);
     //-----------------------------------------
     // Remove the attachments
     //-----------------------------------------
     require_once IPSLib::getAppDir('core') . '/sources/classes/attach/class_attach.php';
     $class_attach = new class_attach($this->registry);
     $class_attach->type = 'post';
     $class_attach->init();
     $class_attach->bulkRemoveAttachment($posts);
     //-----------------------------------------
     // Remove the posts
     //-----------------------------------------
     $this->DB->delete('posts', "topic_id" . $tid);
     $this->DB->delete('search_index', "type='forum' AND type_2='topic' AND type_id_2 " . $tid);
     $this->DB->delete('reputation_cache', "app='forums' AND type='pid' AND type_id " . $tid);
     $this->DB->delete('reputation_index', "app='forums' AND type='pid' AND type_id " . $tid);
     //-----------------------------------------
     // Recount forum...
     //-----------------------------------------
     if (!$nostats) {
         if ($this->forum['id']) {
             $this->registry->class_forums->allForums[$this->forum['id']]['_update_deletion'] = 1;
             $this->forumRecount($this->forum['id']);
         }
         $this->statsRecount();
     }
     return TRUE;
 }
 /**
  * Post multi-mod: Merge posts
  *
  * @access	private
  * @return	void		[Outputs to screen]
  */
 private function _multiMergePost()
 {
     $this->_resetModerator($this->topic['forum_id']);
     $this->_genericPermissionCheck('delete_post');
     if (count($this->pids) < 2) {
         $this->_showError('mod_only_one_pid', 10383);
     }
     //-----------------------------------------
     // Form or print?
     //-----------------------------------------
     if (!$this->request['checked']) {
         //-----------------------------------------
         // Get post data
         //-----------------------------------------
         $master_post = "";
         $dropdown = array();
         $authors = array();
         $seen_author = array();
         $upload_html = "";
         $seoTitle = '';
         //-----------------------------------------
         // Grab teh posts
         //-----------------------------------------
         $this->DB->build(array('select' => 'p.*', 'from' => array('posts' => 'p'), 'where' => "p.pid IN (" . implode(",", $this->pids) . ")", 'add_join' => array(array('select' => 't.forum_id, t.title_seo', 'from' => array('topics' => 't'), 'where' => 't.tid=p.topic_id', 'type' => 'left'))));
         $outer = $this->DB->execute();
         while ($p = $this->DB->fetch($outer)) {
             if (IPSMember::checkPermissions('read', $p['forum_id']) == TRUE) {
                 $master_post .= "<br /><br />" . $p['post'];
                 $dropdown[] = array($p['pid'], ipsRegistry::getClass('class_localization')->getDate($p['post_date'], 'LONG') . " (#{$p['pid']})");
                 if (!in_array($p['author_id'], $seen_author)) {
                     $authors[] = array($p['author_id'], "{$p['author_name']} (#{$p['pid']})");
                     $seen_author[] = $p['author_id'];
                 }
                 $seoTitle = $p['title_seo'];
             }
         }
         //-----------------------------------------
         // Get Attachment Data
         //-----------------------------------------
         $this->DB->build(array('select' => '*', 'from' => 'attachments', 'where' => "attach_rel_module='post' AND attach_rel_id IN (" . implode(",", $this->pids) . ")"));
         $this->DB->execute();
         while ($row = $this->DB->fetch()) {
             $row['image'] = $this->caches['attachtypes'][$row['attach_ext']]['atype_img'];
             $row['size'] = IPSLib::sizeFormat($row['attach_filesize']);
             $row['attach_file'] = IPSText::truncate($row['attach_file'], 50);
             $attachments[] = $row;
         }
         //-----------------------------------------
         // Print form
         //-----------------------------------------
         if (IPSText::getTextClass('editor')->method == 'rte') {
             IPSText::getTextClass('bbcode')->parse_wordwrap = 0;
             IPSText::getTextClass('bbcode')->parse_html = 0;
             $master_post = IPSText::getTextClass('bbcode')->convertForRTE(trim($master_post));
         } else {
             IPSText::getTextClass('bbcode')->parse_html = 0;
             IPSText::getTextClass('bbcode')->parse_nl2br = 0;
             IPSText::getTextClass('bbcode')->parse_smilies = 1;
             IPSText::getTextClass('bbcode')->parse_bbcode = 1;
             IPSText::getTextClass('bbcode')->parsing_section = 'topics';
             if (IPSText::getTextClass('bbcode')->parse_html) {
                 if (!IPSText::getTextClass('bbcode')->parse_nl2br) {
                     $master_post = str_replace(array('<br />', '<br>'), "", trim($master_post));
                 }
             }
             $master_post = IPSText::getTextClass('bbcode')->preEditParse($master_post);
         }
         $editor = IPSText::getTextClass('editor')->showEditor($master_post, 'Post');
         $this->output .= $this->registry->getClass('output')->getTemplate('mod')->mergePostForm($editor, $dropdown, $authors, $attachments, $seoTitle);
         if ($this->topic['tid']) {
             $this->registry->getClass('output')->addNavigation($this->topic['title'], "{$this->settings['_base_url']}showtopic={$this->topic['tid']}");
         }
         $this->registry->getClass('output')->addNavigation($this->lang->words['cm_title'], '');
         $this->registry->getClass('output')->setTitle($this->lang->words['cm_title']);
         $this->registry->output->addContent($this->output);
         $this->registry->getClass('output')->sendOutput();
     } else {
         //-----------------------------------------
         // DO THE THING, WITH THE THING!!
         //-----------------------------------------
         $this->request['postdate'] = intval($this->request['postdate']);
         if (!$this->request['selectedpids'] or !$this->request['postdate'] or !$this->request['postauthor'] or !$this->request['Post']) {
             $this->_showError('mod_merge_posts', 10384);
         }
         IPSText::getTextClass('bbcode')->parse_smilies = 1;
         IPSText::getTextClass('bbcode')->parse_html = 0;
         IPSText::getTextClass('bbcode')->parse_bbcode = 1;
         IPSText::getTextClass('bbcode')->parsing_section = 'topics';
         $post = IPSText::getTextClass('editor')->processRawPost('Post');
         $post = IPSText::getTextClass('bbcode')->preDbParse($post);
         //-----------------------------------------
         // Post to keep...
         //-----------------------------------------
         $posts = array();
         $author = array();
         $post_to_delete = array();
         $new_post_key = md5(time());
         $topics = array();
         $forums = array();
         $append_edit = 0;
         //-----------------------------------------
         // Grab teh posts
         //-----------------------------------------
         $this->DB->build(array('select' => 'p.*', 'from' => array('posts' => 'p'), 'where' => "p.pid IN (" . implode(",", $this->pids) . ")", 'add_join' => array(array('select' => 't.forum_id', 'from' => array('topics' => 't'), 'where' => 't.tid=p.topic_id', 'type' => 'left'))));
         $outer = $this->DB->execute();
         while ($p = $this->DB->fetch($outer)) {
             $posts[$p['pid']] = $p;
             $topics[$p['topic_id']] = $p['topic_id'];
             $forums[$p['forum_id']] = $p['forum_id'];
             if ($p['author_id'] == $this->request['postauthor']) {
                 $author = array('id' => $p['author_id'], 'name' => $p['author_name']);
             }
             if ($p['pid'] != $this->request['postdate']) {
                 $post_to_delete[] = $p['pid'];
             }
             if ($p['append_edit']) {
                 $append_edit = 1;
             }
         }
         //-----------------------------------------
         // Update main post...
         //-----------------------------------------
         $this->DB->update('posts', array('author_id' => $author['id'], 'author_name' => $author['name'], 'post' => $post, 'post_key' => $new_post_key, 'post_parent' => 0, 'edit_time' => time(), 'edit_name' => $this->memberData['members_display_name'], 'append_edit' => ($append_edit or !$this->memberData['g_append_edit']) ? 1 : 0), 'pid=' . $this->request['postdate']);
         //-----------------------------------------
         // Fix attachments
         //-----------------------------------------
         $attach_keep = array();
         $attach_kill = array();
         foreach ($_POST as $key => $value) {
             if (preg_match("/^attach_(\\d+)\$/", $key, $match)) {
                 if ($this->request[$match[0]] == 'keep') {
                     $attach_keep[] = $match[1];
                 } else {
                     $attach_kill[] = $match[1];
                 }
             }
         }
         $attach_keep = IPSLib::cleanIntArray($attach_keep);
         $attach_kill = IPSLib::cleanIntArray($attach_kill);
         //-----------------------------------------
         // Keep
         //-----------------------------------------
         if (count($attach_keep)) {
             $this->DB->update('attachments', array('attach_rel_id' => $this->request['postdate'], 'attach_post_key' => $new_post_key, 'attach_member_id' => $author['id']), 'attach_id IN(' . implode(",", $attach_keep) . ')');
         }
         //-----------------------------------------
         // Kill Attachments
         //-----------------------------------------
         if (count($attach_kill)) {
             require_once IPSLib::getAppDir('core') . '/sources/classes/attach/class_attach.php';
             $class_attach = new class_attach($this->registry);
             $class_attach->type = $rel_module;
             $class_attach->attach_post_key = $post_key;
             $class_attach->attach_rel_id = $rel_id;
             $class_attach->init();
             $class_attach->bulkRemoveAttachment($attach_kill, 'attach_id');
         }
         //-----------------------------------------
         // Kill old posts
         //-----------------------------------------
         if (count($post_to_delete)) {
             $this->DB->delete('posts', 'pid IN(' . implode(",", $post_to_delete) . ')');
         }
         foreach ($topics as $t) {
             $this->modLibrary->rebuildTopic($t, 0);
         }
         foreach ($forums as $f) {
             $this->modLibrary->forumRecount($f);
         }
         $this->modLibrary->statsRecount();
         /* Clear the content cache */
         IPSContentCache::drop('post', $this->pids);
         $this->_addModeratorLog(sprintf($this->lang->words['acp_merged_posts'], implode(", ", $this->pids)));
     }
 }