Вход Регистрация
Файл: library/XenForo/DataWriter/Discussion/Thread.php
Строк: 398
<?php

/**
* Data writer for threads.
*
* @package XenForo_Discussion
*/
class XenForo_DataWriter_Discussion_Thread extends XenForo_DataWriter_Discussion
{
    public static 
$forumCache = array();

    const 
DATA_FORUM 'forumInfo';

    
/**
     * Gets the object that represents the definition of this type of discussion.
     *
     * @return XenForo_Discussion_Definition_Abstract
     */
    
public function getDiscussionDefinition()
    {
        return new 
XenForo_Discussion_Definition_Thread();
    }

    
/**
     * Gets the object that represents the definition of the message within this discussion.
     *
     * @return XenForo_DiscussionMessage_Definition_Abstract
     */
    
public function getDiscussionMessageDefinition()
    {
        return new 
XenForo_DiscussionMessage_Definition_Post();
    }

    
/**
     * Gets information about the last message in this discussion.
     *
     * @return array|false
     */
    
protected function _getLastMessageInDiscussion()
    {
        return 
$this->_getPostModel()->getLastPostInThread($this->get('thread_id'));
    }

    
/**
     * Gets simple information about all messages in this discussion.
     *
     * @param boolean $includeMessage If true, includes the message contents
     *
     * @return array Format: [post id] => info
     */
    
protected function _getMessagesInDiscussionSimple($includeMessage false)
    {
        return 
$this->_getPostModel()->getPostsInThreadSimple($this->get('thread_id'), $includeMessage);
    }

    
/**
     * Rebuilds the discussion info.
     *
     * @return boolean True if still valid
     */
    
public function rebuildDiscussion()
    {
        
$threadId $this->get('thread_id');

        
$newCounters $this->_getPostModel()->recalculatePostPositionsInThread($threadId);
        if (!
$newCounters['firstPostId'])
        {
            return 
false;
        }

        
$this->rebuildDiscussionCounters($newCounters['visibleCount'] - 1$newCounters['firstPostId'], $newCounters['lastPostId']);
        
$this->_getThreadModel()->replaceThreadUserPostCounters($threadId$newCounters['userPosts']);

        return 
true;
    }

    
/**
     * Rebuilds the counters of the discussion.
     *
     * @param integer|false $replyCount Total reply count, if known
     * @param integer|false $firstPostId First post ID, if known already
     * @param integer|false $lastPostId Last post ID, if known already
     */
    
public function rebuildDiscussionCounters($replyCount false$firstPostId false$lastPostId false)
    {
        
$postModel $this->_getPostModel();
        
$threadId $this->get('thread_id');

        if (
$firstPostId && $lastPostId)
        {
            
$posts $postModel->getPostsByIds(
                array(
$firstPostId$lastPostId),
                array(
'join' => XenForo_Model_Post::FETCH_USER)
            );
            
$firstPost $posts[$firstPostId];
            
$lastPost $posts[$lastPostId];
        }
        else
        {
            
$postsTemp $postModel->getPostsInThread(
                
$threadId,
                array(
'join' => XenForo_Model_Post::FETCH_USER'limit' => 1)
            );
            
$firstPost reset($postsTemp);

            
$lastPost $postModel->getLastPostInThread(
                
$threadId,
                array(
'join' => XenForo_Model_Post::FETCH_USER)
            );
        }

        if (!
$firstPost || !$lastPost)
        {
            return;
        }

        if (
$replyCount === false)
        {
            
$replyCount $postModel->countVisiblePostsInThread($threadId) - 1;
        }

        
$this->set('first_post_id'$firstPost['post_id']);
        
$this->set('post_date'$firstPost['post_date']);
        
$this->set('user_id'$firstPost['user_id']);
        
$this->set('username'$firstPost['username'] !== '' $firstPost['username'] : '-');
        
$this->set('first_post_likes'$firstPost['likes']);
        
$this->set('reply_count'$replyCount);

        
$this->set('last_post_id'$lastPost['post_id']);
        
$this->set('last_post_date'$lastPost['post_date']);
        
$this->set('last_post_user_id'$lastPost['user_id']);
        
$this->set('last_post_username'$lastPost['username']);
    }

    
/**
    * Gets the fields that are defined for the table. See parent for explanation.
    *
    * @return array
    */
    
protected function _getFields()
    {
        
$fields $this->_getCommonFields();
        
$fields['xf_thread']['first_post_likes'] = array('type' => self::TYPE_UINT_FORCED'default' => 0);
        
$fields['xf_thread']['prefix_id'] = array('type' => self::TYPE_UINT'default' => 0);

        return 
$fields;
    }

    
/**
    * Gets the actual existing data out of data that was passed in. See parent for explanation.
    *
    * @param mixed
    *
    * @return array|false
    */
    
protected function _getExistingData($data)
    {
        if (!
$threadId $this->_getExistingPrimaryKey($data))
        {
            return 
false;
        }

        return array(
$this->getDiscussionTableName() => $this->_getThreadModel()->getThreadById($threadId));
    }

    
/**
     * Specific discussion pre-save behaviors.
     */
    
protected function _discussionPreSave()
    {
        if (
$this->get('prefix_id') && ($this->isChanged('prefix_id') || $this->isChanged('node_id')))
        {
            if (!
$this->_getPrefixModel()->getPrefixIfInForum($this->get('prefix_id'), $this->get('node_id')))
            {
                
$this->set('prefix_id'0); // invalid prefix
            
}
        }
    }

    
/**
     * Specific discussion post-save behaviors.
     */
    
protected function _discussionPostSave()
    {
        
$threadId $this->get('thread_id');

        if (
$this->isUpdate() && $this->isChanged('discussion_state') && $this->get('discussion_state') != 'visible')
        {
            
$this->_deleteRedirects('thread-' $threadId '-%'true);
        }
        else if (
$this->isUpdate() && $this->isChanged('node_id'))
        {
            if (
$this->get('discussion_type') == 'redirect')
            {
                
$threadRedirectModel $this->getModelFromCache('XenForo_Model_ThreadRedirect');
                
$redirect $threadRedirectModel->getThreadRedirectById($threadId);
                if (
$redirect && $redirect['redirect_key'])
                {
                    
$redirectKey preg_replace('/^(thread-d+)-(d+)$/''$1-' $this->get('node_id'), $redirect['redirect_key']);
                    if (
$redirectKey != $redirect['redirect_key'])
                    {
                        
$threadRedirectModel->updateThreadRedirect($this->get('thread_id'), array('redirect_key' => $redirectKey));
                    }
                }
            }
            else
            {
                
// delete redirects if moving back to forum that already had it
                
$this->_deleteRedirects('thread-' $threadId '-' $this->get('node_id') . '-');
            }
        }

        if (
$this->isUpdate() && $this->get('discussion_state') == 'visible' && $this->isChanged('node_id'))
        {
            
$messageHandler $this->_messageDefinition->getSearchDataHandler();
            if (
$messageHandler)
            {
                
XenForo_Application::defer('SearchIndexPartial', array(
                    
'contentType' => 'post',
                    
'contentIds' => $this->_getDiscussionMessageIds()
                ));
            }

            
$this->_handleForumMove($this->getExisting('node_id'), $this->get('node_id'));
        }
    }

    
/**
     * Returns true if the changes made require the search index to be updated.
     *
     * @return boolean
     */
    
protected function _needsSearchIndexUpdate()
    {
        return (
parent::_needsSearchIndexUpdate() || $this->isChanged('prefix_id'));
    }

    
/**
     * Specific discussion post-delete behaviors.
     */
    
protected function _discussionPostDelete()
    {
        
$threadId $this->get('thread_id');
        
$threadIdQuoted $this->_db->quote($threadId);

        
$this->_db->delete('xf_thread_watch'"thread_id = $threadIdQuoted");
        
$this->_db->delete('xf_thread_user_post'"thread_id = $threadIdQuoted");

        if (
$this->get('discussion_type') == 'redirect')
        {
            
$this->getModelFromCache('XenForo_Model_ThreadRedirect')->deleteThreadRedirects(array($threadId));
        }
        else
        {
            
$this->_deleteRedirects('thread-' $this->get('thread_id') . '-%'true);
        }

        if (
$this->get('discussion_type') == 'poll')
        {
            
$poll $this->getModelFromCache('XenForo_Model_Poll')->getPollByContent('thread'$threadId);
            if (
$poll)
            {
                
$pollDw XenForo_DataWriter::create('XenForo_DataWriter_Poll'XenForo_DataWriter::ERROR_SILENT);
                
$pollDw->setExistingData($polltrue);
                
$pollDw->delete();
            }
        }
    }

    
/**
     * Checks that the messages posted in the containing forum count towards the
     * user message count before running the standard message count update.
     *
     * @see XenForo_DataWriter_DiscussionMessage::_updateUserMessageCount()
     */
    
protected function _updateUserMessageCount($isDelete false$forceUpdateType null)
    {
        if (
$this->_forumCountsMessages())
        {
            return 
parent::_updateUserMessageCount($isDelete$forceUpdateType);
        }
    }

    
/**
     * Determine if messages posted in the containing forum count towards the
     * user message count.
     *
     * @param array $forum If empty, will attempt to fetch DATA_FORUM, or query for forum based on thread node_id
     *
     * @return boolean
     */
    
protected function _forumCountsMessages(array $forum null)
    {
        if (empty(
$forum))
        {
            
$forum $this->_getForumData();
        }

        if (
$forum && isset($forum['count_messages']))
        {
            return !empty(
$forum['count_messages']);
        }
        else
        {
            
// default fallback
            
return true;
        }
    }

    
/**
     * Handle moving from a non-counting to a counting forum, or vice versa
     *
     * @param integer $sourceForumId
     * @param integer $destinationForumId
     */
    
protected function _handleForumMove($sourceForumId$destinationForumId)
    {
        
// fetch the source and destination forum info
        
if (!self::isForumCacheItem($sourceForumId) || !self::isForumCacheItem($destinationForumId))
        {
            
$forums $this->getModelFromCache('XenForo_Model_Forum')->getForumsByIds(
                array(
$sourceForumId$destinationForumId));

            foreach (
$forums AS $forum)
            {
                
self::setForumCacheItem($forum);
            }
        }

        
$sourceForum self::getForumCacheItem($sourceForumId);
        
$destinationForum self::getForumCacheItem($destinationForumId);

        
// do the 'count_messages' settings differ?
        
if ($sourceForum && $destinationForum && $sourceForum['count_messages'] != $destinationForum['count_messages'])
        {
            
$oldState $this->getExisting('discussion_state');
            
$newState $this->get('discussion_state');

            if (
$newState == 'visible' && ($oldState != 'visible' || $destinationForum['count_messages']))
            {
                
// moving to a counting forum from a non-counting forum
                
parent::_updateUserMessageCount(false'add');
            }
            else if (
$oldState == 'visible' && ($newState != 'visible' || !$destinationForum['count_messages']))
            {
                
// moving from a counting forum from a non-counting forum
                
parent::_updateUserMessageCount(false'subtract');
            }
        }
    }

    
/**
    * @see XenForo_DataWriter::setExtraData
    */
    
public function setExtraData($name$value)
    {
        if (
$name == self::DATA_FORUM && is_array($value) && !empty($value['node_id']))
        {
            
self::setForumCacheItem($value);
        }

        return 
parent::setExtraData($name$value);
    }

    
/**
     * Get the data for the forum the thread is in
     *
     * @return array
     */
    
protected function _getForumData()
    {
        if (!
$forum $this->getExtraData(self::DATA_FORUM))
        {
            
$forum self::getForumCacheItem($this->get('node_id'));
        }

        return 
$forum;
    }

    public static function 
setForumCacheItem(array $forum)
    {
        
self::$forumCache[$forum['node_id']] = $forum;
    }

    public static function 
getForumCacheItem($forumId)
    {
        if (!
self::isForumCacheItem($forumId))
        {
            
$forum XenForo_Model::create('XenForo_Model_Forum')->getForumById($forumId);
            if (!
$forum)
            {
                
self::$forumCache[$forumId] = false;
            }
            else
            {
                
self::setForumCacheItem($forum);
            }
        }

        return 
self::$forumCache[$forumId];
    }

    public static function 
isForumCacheItem($forumId)
    {
        return 
array_key_exists($forumIdself::$forumCache);
    }

    
/**
     * Deletes thread redirects with the specified key(s).
     *
     * @param string $redirectKey
     * @param boolean $likeMatch
     */
    
protected function _deleteRedirects($redirectKey$likeMatch false)
    {
        
$threadRedirectModel $this->getModelFromCache('XenForo_Model_ThreadRedirect');
        
$redirects $threadRedirectModel->getThreadRedirectsByKey($redirectKey$likeMatch);
        
$threadRedirectModel->deleteThreadRedirects(array_keys($redirects));
    }

    
/**
     * @return XenForo_Model_Thread
     */
    
protected function _getThreadModel()
    {
        return 
$this->getModelFromCache('XenForo_Model_Thread');
    }

    
/**
     * @return XenForo_Model_ThreadPrefix
     */
    
protected function _getPrefixModel()
    {
        return 
$this->getModelFromCache('XenForo_Model_ThreadPrefix');
    }

    
/**
     * @return XenForo_Model_Post
     */
    
protected function _getPostModel()
    {
        return 
$this->getModelFromCache('XenForo_Model_Post');
    }
}
Онлайн: 0
Реклама