Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Notifier/Post/AbstractWatch.php
<?php

namespace XF\Notifier\Post;

use
XF\Notifier\AbstractNotifier;

use function
in_array;

abstract class
AbstractWatch extends AbstractNotifier
{
   
/**
     * @var \XF\Entity\Post
     */
   
protected $post;

    protected
$actionType;
    protected
$isApplicable;

    protected
$userReadDates = [];
    protected
$previousPosts = null;

    abstract protected function
getDefaultWatchNotifyData();
    abstract protected function
getApplicableActionTypes();
    abstract protected function
getWatchEmailTemplateName();

    public function
__construct(\XF\App $app, \XF\Entity\Post $post, $actionType)
    {
       
parent::__construct($app);

       
$this->post = $post;
       
$this->actionType = $actionType;
       
$this->isApplicable = $this->isApplicable();
    }

    protected function
isApplicable()
    {
        if (!
in_array($this->actionType, $this->getApplicableActionTypes()))
        {
            return
false;
        }

        if (!
$this->post->isVisible())
        {
            return
false;
        }

        return
true;
    }

    public function
canNotify(\XF\Entity\User $user)
    {
        if (!
$this->isApplicable)
        {
            return
false;
        }

        if (!isset(
$this->userReadDates[$user->user_id]))
        {
           
// this should have a record for every user, so generally shouldn't happen
           
return false;
        }

       
$userReadDate = $this->userReadDates[$user->user_id];
       
$post = $this->post;

        if (
$user->user_id == $post->user_id || $user->isIgnoring($post->user_id))
        {
            return
false;
        }

        if (
$userReadDate > $post->Thread->last_post_date)
        {
            return
false;
        }

        if (
$this->actionType == 'reply')
        {
           
$previousVisiblePost = null;
            foreach (
$this->getPreviousPosts() AS $previousPost)
            {
                if (!
$user->isIgnoring($previousPost->user_id))
                {
                   
$previousVisiblePost = $previousPost;
                    break;
                }
            }

           
$autoReadDate = \XF::$time - $this->app()->options()->readMarkingDataLifetime * 86400;
            if (!
$previousVisiblePost || $previousVisiblePost->post_date < $autoReadDate)
            {
               
// always alert
           
}
            else if (
$previousVisiblePost->post_date > $userReadDate)
            {
                return
false;
            }
        }

        return
true;
    }

    public function
sendAlert(\XF\Entity\User $user)
    {
       
$post = $this->post;

        return
$this->basicAlert(
           
$user,
           
$post->user_id,
           
$post->username,
           
'post',
           
$post->post_id,
           
'insert'
       
);
    }

    public function
sendEmail(\XF\Entity\User $user)
    {
        if (!
$user->email || $user->user_state != 'valid')
        {
            return
false;
        }

       
$post = $this->post;

       
$params = [
           
'post' => $post,
           
'thread' => $post->Thread,
           
'forum' => $post->Thread->Forum,
           
'receiver' => $user
       
];

       
$template = $this->getWatchEmailTemplateName();

       
$this->app()->mailer()->newMail()
            ->
setToUser($user)
            ->
setTemplate($template, $params)
            ->
queue();

        return
true;
    }

    public function
getDefaultNotifyData()
    {
        if (!
$this->isApplicable)
        {
            return [];
        }

        return
$this->getDefaultWatchNotifyData();
    }

    public function
getUserData(array $userIds)
    {
       
$users = parent::getUserData($userIds);
       
$this->userReadDates = $this->getUserReadDates($userIds);

        return
$users;
    }

    protected function
getUserReadDates(array $userIds)
    {
        if (!
$userIds)
        {
            return [];
        }

       
$autoReadDate = \XF::$time - $this->app()->options()->readMarkingDataLifetime * 86400;
       
$post = $this->post;

       
$db = $this->app()->db();
       
$readDates = $db->fetchPairs("
            SELECT user.user_id,
                GREATEST(
                    COALESCE(thread_read.thread_read_date, 0),
                    COALESCE(forum_read.forum_read_date, 0),
                    ?
                )
            FROM xf_user AS user
            LEFT JOIN xf_thread_read AS thread_read ON
                (thread_read.user_id = user.user_id AND thread_read.thread_id = ?)
            LEFT JOIN xf_forum_read AS forum_read ON
                (forum_read.user_id = user.user_id AND forum_read.node_id = ?)
            WHERE user.user_id IN ("
. $db->quote($userIds) . ")
        "
, [$autoReadDate, $post->thread_id, $post->Thread->node_id]);

        foreach (
$userIds AS $userId)
        {
            if (!isset(
$readDates[$userId]))
            {
               
$readDates[$userId] = $autoReadDate;
            }
        }

        return
$readDates;
    }

    protected function
getPreviousPosts()
    {
        if (
$this->previousPosts === null)
        {
           
$autoReadDate = \XF::$time - $this->app()->options()->readMarkingDataLifetime * 86400;

           
$finder = $this->app()->finder('XF:Post')
                ->
where('thread_id', $this->post->thread_id)
                ->
where('message_state', 'visible')
                ->
where('post_date', '<', $this->post->post_date)
                ->
where('post_date', '>=', $autoReadDate)
                ->
order('post_date', 'desc');

           
$this->previousPosts = $finder->fetch(15);
        }

        return
$this->previousPosts;
    }
}