public function execute(array $deferred, array $data, $targetRunTime, &$status) { $data = array_merge(array('contentType' => '', 'contentIds' => false), $data); $status = sprintf('Search Index (Partial)'); if (!$data['contentType'] || !$data['contentIds'] || !is_array($data['contentIds'])) { return false; } $limitTime = $targetRunTime > 0; do { $s = microtime(true); $i = 0; $contentIds = array(); foreach ($data['contentIds'] as $key => $id) { $contentIds[] = $id; unset($data['contentIds'][$key]); if (++$i >= 10) { break; } } $indexer = new XenForo_Search_Indexer(); $indexer->quickIndex($data['contentType'], $contentIds); $targetRunTime -= microtime(true) - $s; } while ((!$limitTime || $targetRunTime > 0) && $data['contentIds']); if (!$data['contentIds']) { return false; } return $data; }
/** * Merge multiple threads into a single thread * * @param array $threads * @param integer $targetThreadId * @param array $options * * @return boolean|array False if failure, otherwise thread array of merged thread */ public function mergeThreads(array $threads, $targetThreadId, array $options = array()) { if (!isset($threads[$targetThreadId])) { return false; } $targetThread = $threads[$targetThreadId]; unset($threads[$targetThreadId]); $mergeFromThreadIds = array_keys($threads); if (!$mergeFromThreadIds) { return false; } $options = array_merge(array('redirect' => false, 'redirectExpiry' => 0), $options); $postModel = $this->_getPostModel(); $db = $this->_getDb(); $movePosts = $this->fetchAllKeyed(' SELECT post_id, thread_id, user_id, message_state FROM xf_post WHERE thread_id IN (' . $db->quote($mergeFromThreadIds) . ') ', 'post_id'); $movePostIds = array_keys($movePosts); XenForo_Db::beginTransaction($db); $db->update('xf_post', array('thread_id' => $targetThreadId), 'post_id IN (' . $db->quote($movePostIds) . ')'); $newCounters = $postModel->recalculatePostPositionsInThread($targetThreadId); if (!$newCounters['firstPostId']) { XenForo_Db::rollback($db); return false; } // TODO: user message counts will go off if merging from a visible thread into a hidden one or vice versa $threadDw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'); $threadDw->setExistingData($targetThreadId); $threadDw->rebuildDiscussionCounters($newCounters['visibleCount'] - 1, $newCounters['firstPostId'], $newCounters['lastPostId']); $threadDw->save(); if ($options['redirect']) { $targetUrl = XenForo_Link::buildPublicLink('threads', $targetThread); $redirectKey = "thread-{$targetThread['thread_id']}-"; foreach ($threads as $thread) { $redirectDw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'); $redirectDw->setExistingData($thread, true); $redirectDw->set('discussion_type', 'redirect'); $redirectDw->save(); $this->getModelFromCache('XenForo_Model_ThreadRedirect')->insertThreadRedirect($thread['thread_id'], $targetUrl, $redirectKey, $options['redirectExpiry']); } $idsQuoted = $db->quote($mergeFromThreadIds); $db->delete('xf_thread_watch', "thread_id IN ({$idsQuoted})"); $db->delete('xf_thread_user_post', "thread_id IN ({$idsQuoted})"); } else { foreach ($threads as $thread) { $deleteDw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'); $deleteDw->setExistingData($thread, true); $deleteDw->delete(); } } $forumIds = array(); foreach ($threads as $thread) { $forumIds[$thread['node_id']] = $thread['node_id']; } foreach ($forumIds as $forumId) { $forumDw = XenForo_DataWriter::create('XenForo_DataWriter_Forum', XenForo_DataWriter::ERROR_SILENT); $forumDw->setExistingData($forumId); $forumDw->rebuildCounters(); $forumDw->save(); } $this->replaceThreadUserPostCounters($targetThreadId, $newCounters['userPosts']); $indexer = new XenForo_Search_Indexer(); $indexer->quickIndex('post', $movePostIds); XenForo_Db::commit($db); return $threadDw->getMergedData(); }
/** * Moves the specified posts (in the given threads) to a new thread. The * new thread will be created in this function. * * @param array $posts * @param array $sourceThreads * @param array $newThread Information about the new thread; first/last/poster info filled in automatically * * @return array|false New thread ID or false */ public function movePostsToNewThread(array $posts, array $sourceThreads, array $newThread) { if (!$posts) { return false; } $firstPostId = 0; $firstPostDate = PHP_INT_MAX; foreach ($posts as $postId => $post) { $sourceThreadIds[$post['thread_id']] = true; if ($post['post_date'] < $firstPostDate || $post['post_date'] == $firstPostDate && $post['post_id'] < $firstPostId) { $firstPostId = $postId; $firstPostDate = $post['post_date']; } } if (!isset($posts[$firstPostId])) { return false; } $firstPost = $posts[$firstPostId]; $postIds = array_keys($posts); // TODO: consider user message count issues if moving from invisible to visible, etc unset($newThread['thread_id']); $newThread['first_post_id'] = $firstPostId; $newThread['post_date'] = $firstPost['post_date']; $newThread['user_id'] = $firstPost['user_id']; $newThread['username'] = $firstPost['username']; $newThread['discussion_state'] = $firstPost['message_state']; $db = $this->_getDb(); XenForo_Db::beginTransaction($db); $threadDw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'); $threadDw->setOption(XenForo_DataWriter_Discussion::OPTION_REQUIRE_INSERT_FIRST_MESSAGE, false); $threadDw->bulkSet($newThread); $threadDw->save(); $newThread = $threadDw->getMergedData(); $db->update('xf_post', array('thread_id' => $newThread['thread_id']), 'post_id IN (' . $db->quote($postIds) . ')'); $firstPostDw = XenForo_DataWriter::create('XenForo_DataWriter_DiscussionMessage_Post', XenForo_DataWriter::ERROR_SILENT); $firstPostDw->setExistingData($firstPostId); $firstPostDw->set('message_state', 'visible'); $firstPostDw->save(); $newCounters = $this->recalculatePostPositionsInThread($newThread['thread_id']); $threadDw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'); $threadDw->setExistingData($newThread, true); $threadDw->set('reply_count', $newCounters['visibleCount'] - 1); $threadDw->updateLastPost(); $threadDw->save(); $this->_getThreadModel()->replaceThreadUserPostCounters($newThread['thread_id'], $newCounters['userPosts']); $reindexPostIds = $postIds; foreach ($sourceThreads as $sourceThread) { $threadDw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread'); $threadDw->setExistingData($sourceThread, true); $newSourceCounters = $this->recalculatePostPositionsInThread($sourceThread['thread_id']); if (!$newSourceCounters['firstPostId']) { // all posts removed -> delete $threadDw->delete(); } else { if ($newSourceCounters['firstPostId'] != $sourceThread['first_post_id']) { $sourceFirstPost = $this->getPostById($newSourceCounters['firstPostId']); $threadDw->set('first_post_id', $sourceFirstPost['post_id']); $threadDw->set('post_date', $sourceFirstPost['post_date']); $threadDw->set('user_id', $sourceFirstPost['user_id']); $threadDw->set('username', $sourceFirstPost['username']); // TODO: possible situation where new first post is moderated $reindexPostIds[] = $sourceFirstPost['post_id']; } $threadDw->set('reply_count', $newSourceCounters['visibleCount'] - 1); if ($newSourceCounters['lastPostId'] != $sourceThread['last_post_id']) { $threadDw->updateLastPost(); } $threadDw->save(); $this->_getThreadModel()->replaceThreadUserPostCounters($sourceThread['thread_id'], $newSourceCounters['userPosts']); } } $indexer = new XenForo_Search_Indexer(); $indexer->quickIndex('post', $reindexPostIds); XenForo_Db::commit($db); return $newThread; }