ForumPostPolicy.php 4.23 KB
<?php

namespace FootyRoom\Core\ForumPost;

use FootyRoom\User\User;
use FootyRoom\Core\AuthException;
use FootyRoom\Core\CoreException;
use FootyRoom\Core\Comment\CommentPolicy;
use FootyRoom\Queries\Post\ForumPostQueryHandler;
use FootyRoom\Queries\Post\ForumPostsInPeriodQuery;

class ForumPostPolicy
{
    /**
     * \FootyRoom\Core\Comment\CommentPolicy.
     */
    protected $commentPolicy;

    /**
     * \FootyRoom\Queries\Post\ForumPostQueryHandler.
     */
    protected $forumPostQueryHandler;

    /**
     * Constructor.
     *
     * @param \FootyRoom\Core\Comment\CommentPolicy $commentPolicy
     * @param \FootyRoom\Queries\Post\ForumPostQueryHandler $forumPostQueryHandler
     */
    public function __construct(
        CommentPolicy $commentPolicy,
        ForumPostQueryHandler $forumPostQueryHandler
    ) {
        $this->commentPolicy = $commentPolicy;
        $this->forumPostQueryHandler = $forumPostQueryHandler;
    }

    /**
     * Determine if user can post in forum.
     *
     * @param int $userId
     * @param string $content
     * @param bool $throw
     *
     * @throws CoreException
     * @return bool
     */
    public function canPost(User $user, string $content, $throw = false)
    {
        // Count comments in last 60 minutes.
        $count = $this->forumPostQueryHandler->postsInPeriod(
            new ForumPostsInPeriodQuery(60 * 60, $user->getUserId())
        );

        if ($count >= 3) {
            if ($throw) {
                throw new CoreException('Members can post in forum 3 times per hour.');
            } else {
                return false;
            }
        }

        try {
            return $this->canComment($user, $content, $throw);
        } catch (Exception $e) {
            $message = str_replace('commenting', 'posting', $e->getMessage());

            throw new CoreException($message);
        }
    }

    /**
     * Determine if user can comment in forum.
     *
     * @param \FootyRoom\User\User $user
     * @param string $content
     * @param bool $throw
     *
     * @return bool
     */
    public function canComment(User $user, string $content, $throw = false)
    {
        if ($user->isNewborn()) {
            $hasLink = strstr($content, 'http://') ?: strstr($content, 'https://');

            if ($hasLink && $throw) {
                throw new CoreException('New users are not allowed to post links.');
            }

            if ($hasLink) {
                return false;
            }
        }

        return $this->commentPolicy->canComment($user, $throw);
    }

    /**
     * Checks whether user can edit specific comment.
     */
    public function canEdit(User $user, int $commentUserId, string $discussionId, $throw = false): bool
    {
        return $this->commentPolicy->canEdit($user, $commentUserId, $discussionId, $throw);
    }

    /**
     * Decides whether user can moderate forum discussions.
     *
     * @param \FootyRoom\User\User $user
     * @param bool $throw
     *
     * @return bool
     */
    public static function canModerate(User $user, $throw = false)
    {
        return CommentPolicy::canModerate($user, $throw);
    }

    /**
     * Decides whether user can administer forum discussions.
     *
     * @param \FootyRoom\User\User $user
     * @param bool $throw
     *
     * @return bool
     */
    public static function canAdminister(User $user, $throw = false)
    {
        if ($user->getRole() >= 30) {
            return true;
        }

        if ($throw) {
            throw new AuthException();
        }

        return false;
    }

    /**
     * Determine if user can create new discussions in specified forum category.
     *
     * @param int $userRole
     * @param string $categorySlug
     *
     * @return bool
     */
    public static function canPostIn($userRole, $categorySlug)
    {
        if ($userRole >= 10 && $categorySlug !== 'footyroom-blog') {
            return true;
        }

        if ($userRole >= 30) {
            return true;
        }

        return false;
    }

    /**
     * Determine if specific user role can see unpublished comments.
     *
     * @param int $userRole
     *
     * @return bool
     */
    public static function seeUnpublished($userRole)
    {
        return $userRole >= 25 ? true : false;
    }
}