Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Like/AbstractHandler.php
<?php

namespace XF\Like;

use
XF\Entity\LikedContent;
use
XF\Mvc\Entity\Entity;

use function
is_array;

abstract class
AbstractHandler
{
    protected
$contentType;

    protected
$contentCacheFields = [
       
'count' => 'likes',
       
'recent' => 'like_users'
   
];

    public function
__construct($contentType)
    {
       
$this->contentType = $contentType;
    }

    abstract public function
likesCounted(Entity $entity);

    public function
canViewContent(Entity $entity, &$error = null)
    {
        if (
method_exists($entity, 'canView'))
        {
            return
$entity->canView($error);
        }

        throw new \
LogicException("Could not determine content viewability; please override");
    }

    public function
getTemplateName()
    {
        return
'public:like_item_' . $this->contentType;
    }

    public function
getTemplateData(LikedContent $like, Entity $content = null)
    {
        if (!
$content)
        {
           
$content = $like->Content;
        }

        return [
           
'like' => $like,
           
'content' => $content
       
];
    }

    public function
render(LikedContent $like, Entity $content = null)
    {
        if (!
$content)
        {
           
$content = $like->Content;
            if (!
$content)
            {
                return
'';
            }
        }

       
$template = $this->getTemplateName();
       
$data = $this->getTemplateData($like, $content);

        return \
XF::app()->templater()->renderTemplate($template, $data);
    }

    public function
isRenderable(LikedContent $like)
    {
        return
$this->isLikeRenderable($like);
    }

    public function
isLikeRenderable(LikedContent $like)
    {
       
$template = $this->getTemplateName();
        return \
XF::app()->templater()->isKnownTemplate($template);
    }

    public function
updateContentLikes(Entity $entity, $count, array $latestLikes)
    {
        if (
is_array($count))
        {
           
$count = reset($count);
        }

       
$countField = $this->contentCacheFields['count'] ?? false;
       
$recentField = $this->contentCacheFields['recent'] ?? false;

        if (!
$countField && !$recentField)
        {
            return;
        }

        if (
$countField)
        {
           
$entity->$countField = $count;
        }
        if (
$recentField)
        {
           
$entity->$recentField = $latestLikes;
        }

       
$entity->save();
    }

    public function
updateRecentCacheForUserChange($oldUserId, $newUserId, $oldUsername, $newUsername)
    {
        if (empty(
$this->contentCacheFields['recent']))
        {
            return;
        }

       
$entityType = \XF::app()->getContentTypeEntity($this->contentType, false);
        if (!
$entityType)
        {
            return;
        }

       
$structure = \XF::em()->getEntityStructure($entityType);

       
// note that xf_reaction_content must already be updated
       
$oldFind = $this->getUserStringForLikeUsers($oldUserId, $oldUsername);
       
$newReplace = $this->getUserStringForLikeUsers($newUserId, $newUsername);


       
$recentField = $this->contentCacheFields['recent'];
       
$table = $structure->table;
       
$primaryKey = $structure->primaryKey;

        \
XF::db()->query("
            UPDATE (
                SELECT content_id FROM xf_reaction_content
                WHERE content_type = ?
                AND reaction_user_id = ?
            ) AS temp
            INNER JOIN
{$table} AS reaction_table ON (reaction_table.`$primaryKey` = temp.content_id)
            SET reaction_table.`
{$recentField}` = REPLACE(reaction_table.`{$recentField}`, ?, ?)
        "
, [$this->contentType, $newUserId, $oldFind, $newReplace]);
    }

    protected function
getUserStringForLikeUsers($userId, $username)
    {
        return
substr(json_encode(['user_id' => $userId, 'username' => $username]), 1, -1);
    }

    public function
getContentLikeCaches(Entity $entity)
    {
       
$countField = $this->contentCacheFields['count'] ?? false;
       
$recentField = $this->contentCacheFields['recent'] ?? false;
       
$output = [];

        if (
$countField)
        {
           
$output['count'] = $entity->$countField;
        }
        if (
$recentField)
        {
           
$output['recent'] = $entity->$recentField;
        }

        return
$output;
    }

    public function
sendLikeAlert(\XF\Entity\User $receiver, \XF\Entity\User $sender, $contentId, Entity $content)
    {
       
$canView = \XF::asVisitor($receiver, function() use ($content)
        {
            return
$this->canViewContent($content);
        });
        if (!
$canView)
        {
            return
false;
        }

       
/** @var \XF\Repository\UserAlert $alertRepo */
       
$alertRepo = \XF::repository('XF:UserAlert');
        return
$alertRepo->alertFromUser(
           
$receiver,
           
$sender,
           
$this->contentType,
           
$contentId,
           
'like',
           
$this->getExtraDataForAlertOrFeed($content, 'alert')
        );
    }

    public function
removeLikeAlert(LikedContent $like)
    {
       
/** @var \XF\Repository\UserAlert $alertRepo */
       
$alertRepo = \XF::repository('XF:UserAlert');
       
$alertRepo->fastDeleteAlertsFromUser($like->reaction_user_id, $this->contentType, $like->content_id, 'like');
    }

    public function
publishLikeNewsFeed(\XF\Entity\User $sender, $contentId, Entity $content)
    {
       
/** @var \XF\Repository\NewsFeed $newsFeedRepo */
       
$newsFeedRepo = \XF::repository('XF:NewsFeed');
       
$newsFeedRepo->publish(
           
$this->contentType, $contentId, 'like', $sender->user_id, $sender->username,
           
$this->getExtraDataForAlertOrFeed($content, 'feed')
        );
    }

    public function
unpublishLikeNewsFeed(LikedContent $like)
    {
       
/** @var \XF\Repository\NewsFeed $newsFeedRepo */
       
$newsFeedRepo = \XF::repository('XF:NewsFeed');
       
$newsFeedRepo->unpublish($this->contentType, $like->content_id, $like->reaction_user_id, 'like');
    }

    protected function
getExtraDataForAlertOrFeed(Entity $content, $context)
    {
        return [];
    }

    public function
getContentUserId(Entity $entity)
    {
        if (isset(
$entity->user_id))
        {
            return
$entity->user_id;
        }
        else if (isset(
$entity->User))
        {
           
$user = $entity->User;
            if (
$user instanceof \XF\Entity\User)
            {
                return
$user->user_id;
            }
            else
            {
                throw new \
LogicException("Found a User relation but it did not match a user; please override");
            }
        }

        throw new \
LogicException("Could not determine content user ID; please override");
    }

    public function
getEntityWith()
    {
        return [];
    }

    public function
getContent($id)
    {
        return \
XF::app()->findByContentType($this->contentType, $id, $this->getEntityWith());
    }

    public function
getContentType()
    {
        return
$this->contentType;
    }
}