/** * 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))); } }
/** * 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; }
/** * 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'); }
/** * 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))); } }