Вход Регистрация
Файл: library/XenForo/Model/Like.php
Строк: 574
<?php

/**
 * Model for liking content.
 *
 * @package XenForo_Like
 */
class XenForo_Model_Like extends XenForo_Model
{
    
/**
     * Gets a liked content record for a user that has liked a piece of content.
     *
     * @param string $contentType
     * @param integer $contentId
     * @param integer $userId
     *
     * @return array|false
     */
    
public function getContentLikeByLikeUser($contentType, $contentId, $userId)
    {
        return 
$this->_getDb()->fetchRow('
            SELECT *
            FROM xf_liked_content
            WHERE content_type = ?
                AND content_id = ?
                AND like_user_id = ?
        '
, array($contentType, $contentId, $userId));
    }

    
/**
     * Gets likes based on the content user.
     *
     * @param integer $userId
     * @param array $fetchOptions Fetch options. Supports limit only now.
     *
     * @return array Format: [like id] => info
     */
    
public function getLikesForContentUser($userId, array $fetchOptions = array())
    {
        
$limitOptions = $this->prepareLimitFetchOptions($fetchOptions);

        return 
$this->fetchAllKeyed($this->limitQueryResults(
            
'
                SELECT liked_content.*,
                    user.*
                FROM xf_liked_content AS liked_content
                LEFT JOIN xf_user AS user ON (user.user_id = liked_content.like_user_id)
                WHERE liked_content.content_user_id = ?
                ORDER BY liked_content.like_date DESC
            '
, $limitOptions['limit'], $limitOptions['offset']
        ), 
'like_id', $userId);
    }

    
/**
     * Count the number of likes a content user has received.
     *
     * @param integer $userId
     *
     * @return integer
     */
    
public function countLikesForContentUser($userId)
    {
        return 
$this->_getDb()->fetchOne('
            SELECT COUNT(*)
            FROM xf_liked_content
            WHERE content_user_id = ?
        '
, $userId);
    }

    
/**
     * Get all the likes for a particular piece of content.
     *
     * @param string $contentType
     * @param integer $contentId
     * @param array $fetchOptions Fetch options (limit only right now)
     *
     * @return array Format: [like id] => info
     */
    
public function getContentLikes($contentType, $contentId, array $fetchOptions = array())
    {
        
$limitOptions = $this->prepareLimitFetchOptions($fetchOptions);

        return 
$this->fetchAllKeyed($this->limitQueryResults(
            
'
                SELECT liked_content.*,
                    user.*,
                    user_profile.*,
                    user_option.*
                FROM xf_liked_content AS liked_content
                INNER JOIN xf_user AS user ON
                    (user.user_id = liked_content.like_user_id)
                INNER JOIN xf_user_profile AS user_profile ON
                    (user_profile.user_id = user.user_id)
                INNER JOIN xf_user_option AS user_option ON
                    (user_option.user_id = user.user_id)
                WHERE liked_content.content_type = ?
                    AND liked_content.content_id = ?
                ORDER BY liked_content.like_date DESC
            '
, $limitOptions['limit'], $limitOptions['offset']
        ), 
'like_id', array($contentType, $contentId));
    }

    
/**
     * Gets the latest like users on a piece of content. Currently returns the last 5.
     *
     * @param string $contentType
     * @param integer $contentId
     *
     * @return array Format: [] => [user_id] and [username]
     */
    
public function getLatestContentLikeUsers($contentType, $contentId)
    {
        
$likes = $this->getContentLikes($contentType, $contentId, array(
            
'limit' => 5
        
));

        
$output = array();
        foreach (
$likes AS $like)
        {
            
$output[] = array(
                
'user_id' => $like['like_user_id'],
                
'username' => $like['username']
            );
        }

        return 
$output;
    }

    
/**
     * Inserts a new like for a piece of content.
     *
     * @param string $contentType
     * @param integer $contentId
     * @param integer $contentUserId User that owns/created the content
     * @param integer|null $likeUserId User liking content; defaults to visitor
     * @param integer|null $likeDate Timestamp of liking; defaults to now.
     *
     * @return array|false List of latest like users or false
     */
    
public function likeContent($contentType, $contentId, $contentUserId, $likeUserId = null, $likeDate = null)
    {
        
$visitor = XenForo_Visitor::getInstance();

        if (
$likeUserId === null)
        {
            
$likeUserId = $visitor['user_id'];
        }
        if (!
$likeUserId)
        {
            return 
false;
        }

        if (
$likeUserId != $visitor['user_id'])
        {
            
$user = $this->getModelFromCache('XenForo_Model_User')->getUserById($likeUserId);
            if (!
$user)
            {
                return 
false;
            }
            
$likeUsername = $user['username'];
        }
        else
        {
            
$likeUsername = $visitor['username'];
        }

        if (
$likeDate === null)
        {
            
$likeDate = XenForo_Application::$time;
        }

        
$likeHandler = $this->getLikeHandler($contentType);
        if (!
$likeHandler)
        {
            return 
false;
        }

        
$db = $this->_getDb();
        
XenForo_Db::beginTransaction($db);

        
$result = $db->query('
            INSERT IGNORE INTO xf_liked_content
                (content_type, content_id, content_user_id, like_user_id, like_date)
            VALUES
                (?, ?, ?, ?, ?)
        '
, array($contentType, $contentId, $contentUserId, $likeUserId, $likeDate));

        if (!
$result->rowCount())
        {
            
XenForo_Db::commit($db);
            return 
false;
        }

        if (
$contentUserId)
        {
            
$userModel = $this->getModelFromCache('XenForo_Model_User');
            
$contentUser = $this->getModelFromCache('XenForo_Model_User')->getUserById($contentUserId, array(
                
'join' => XenForo_Model_User::FETCH_USER_OPTION | XenForo_Model_User::FETCH_USER_PROFILE
            
));

            if (
$contentUser)
            {
                
$db->query('
                    UPDATE xf_user
                    SET like_count = like_count + 1
                    WHERE user_id = ?
                '
, $contentUserId);


                if (!
$userModel->isUserIgnored($contentUser, $likeUserId)
                    && 
XenForo_Model_Alert::userReceivesAlert($contentUser, $contentType, 'like')
                )
                {
                    
XenForo_Model_Alert::alert(
                        
$contentUserId,
                        
$likeUserId,
                        
$likeUsername,
                        
$contentType,
                        
$contentId,
                        
'like'
                    
);
                }
            }
        }

        
// publish to news feed
        
$this->getModelFromCache('XenForo_Model_NewsFeed')->publish(
            
$likeUserId,
            
$likeUsername,
            
$contentType,
            
$contentId,
            
'like'
        
);

        
$latestLikeUsers = $this->getLatestContentLikeUsers($contentType, $contentId);
        
$likeHandler->incrementLikeCounter($contentId, $latestLikeUsers);

        
XenForo_Db::commit($db);

        return 
$latestLikeUsers;
    }

    
/**
     * Unlikes the specified like record.
     *
     * @param array $like
     *
     * @return array|false List of latest like users or false
     */
    
public function unlikeContent(array $like)
    {
        
$likeHandler = $this->getLikeHandler($like['content_type']);
        if (!
$likeHandler)
        {
            return 
false;
        }

        
$db = $this->_getDb();
        
XenForo_Db::beginTransaction($db);

        
$result = $db->query('
            DELETE FROM xf_liked_content
            WHERE like_id = ?
        '
, $like['like_id']);

        if (!
$result->rowCount())
        {
            
XenForo_Db::commit($db);
            return 
false;
        }

        if (
$like['content_user_id'])
        {
            
$db->query('
                UPDATE xf_user
                SET like_count = IF(like_count > 1, like_count - 1, 0)
                WHERE user_id = ?
            '
, $like['content_user_id']);

            
$this->_getAlertModel()->deleteAlerts(
                
$like['content_type'], $like['content_id'], $like['like_user_id'], 'like'
            
);
        }

        
$this->_getNewsFeedModel()->delete(
            
$like['content_type'], $like['content_id'], $like['like_user_id'], 'like'
        
);

        
$latestLikeUsers = $this->getLatestContentLikeUsers($like['content_type'], $like['content_id']);
        
$likeHandler->incrementLikeCounter($like['content_id'], $latestLikeUsers, -1);

        
XenForo_Db::commit($db);

        return 
$latestLikeUsers;
    }

    
/**
     * Deletes all the likes applied to a piece of content.
     *
     * @param string $contentType
     * @param integer|array $contentIds Single content ID or an array of them
     * @param boolean Update the likes counter for liked users
     */
    
public function deleteContentLikes($contentType, $contentIds, $updateUserLikeCounter = true)
    {
        if (!
is_array($contentIds))
        {
            
$contentIds = array($contentIds);
        }
        if (!
$contentIds)
        {
            return;
        }

        
$db = $this->_getDb();
        
$contentIdsQuoted = $db->quote($contentIds);

        if (
$updateUserLikeCounter)
        {
            
$updates = $db->fetchPairs('
                SELECT content_user_id, COUNT(*)
                FROM xf_liked_content
                WHERE content_type = ?
                    AND content_id IN (' 
. $contentIdsQuoted . ')
                GROUP BY content_user_id
            '
, $contentType);

            foreach (
$updates AS $userId => $decrement)
            {
                
$decrementQuoted = $db->quote($decrement);
                
$db->query("
                    UPDATE xf_user
                    SET like_count = IF(like_count > 
$decrementQuoted, like_count - $decrementQuoted, 0)
                    WHERE user_id = ?
                "
, $userId);
            }
        }

        
$db->delete('xf_liked_content',
            
'content_type = ' . $db->quote($contentType) . ' AND content_id IN (' . $contentIdsQuoted . ')'
        
);
    }

    
/**
     * Gets the like handler for a specific type of content.
     *
     * @param string $contentType
     *
     * @return false|XenForo_LikeHandler_Abstract
     */
    
public function getLikeHandler($contentType)
    {
        
$handlerClass = $this->getContentTypeField($contentType, 'like_handler_class');
        if (!
$handlerClass || !class_exists($handlerClass))
        {
            return 
false;
        }

        
$handlerClass = XenForo_Application::resolveDynamicClass($handlerClass);
        return new 
$handlerClass();
    }

    
/**
     * Gets the like handlers for all content types.
     *
     * @return array Array of XenForo_LikeHandler_Abstract objects
     */
    
public function getLikeHandlers()
    {
        
$handlerClasses = $this->getContentTypesWithField('like_handler_class');
        
$handlers = array();
        foreach (
$handlerClasses AS $contentType => $handlerClass)
        {
            if (!
class_exists($handlerClass))
            {
                continue;
            }

            
$handlerClass = XenForo_Application::resolveDynamicClass($handlerClass);
            
$handlers[$contentType] = new $handlerClass();
        }

        return 
$handlers;
    }

    
/**
     * Adds content specific data to a list of likes. Likes of unviewable content will
     * be removed.
     *
     * @param array $likes
     * @param array|null $viewingUser
     *
     * @return array Viewable likes with content key added (sub keys: url, title)
     */
    
public function addContentDataToLikes(array $likes, array $viewingUser = null)
    {
        
$this->standardizeViewingUserReference($viewingUser);

        
$likesGrouped = array();
        foreach (
$likes AS $key => $like)
        {
            
$likesGrouped[$like['content_type']][$key] = $like['content_id'];
        }

        
$handlers = $this->getLikeHandlers();
        foreach (
$likesGrouped AS $contentType => $contentIds)
        {
            if (!isset(
$handlers[$contentType]))
            {
                foreach (
$contentIds AS $key => $contentId)
                {
                    unset(
$likes[$key]);
                }
            }
            else
            {
                
$contents = $handlers[$contentType]->getContentData($contentIds, $viewingUser);
                
$listTemplateName = $handlers[$contentType]->getListTemplateName();
                foreach (
$contentIds AS $key => $contentId)
                {
                    if (isset(
$contents[$contentId]))
                    {
                        
$likes[$key]['content'] = $contents[$contentId];
                        
$likes[$key]['listTemplateName'] = $listTemplateName;
                    }
                    else
                    {
                        unset(
$likes[$key]);
                    }
                }
            }
        }

        return 
$likes;
    }

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

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