Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Api/Controller/ProfilePost.php
<?php

namespace XF\Api\Controller;

use
XF\Mvc\Entity\Entity;
use
XF\Mvc\Entity\Finder;
use
XF\Mvc\ParameterBag;

use function
intval;

/**
 * @api-group Profile posts
 */
class ProfilePost extends AbstractController
{
    protected function
preDispatchController($action, ParameterBag $params)
    {
       
$this->assertApiScopeByRequestMethod('profile_post');
    }

   
/**
     * @api-desc Gets information about the specified profile post.
     *
     * @api-in   bool $with_comments If specified, the response will include a page of comments.
     * @api-in   int $page The page of comments to include
     *
     * @api-out  ProfilePost $profile_post
     * @api-see  self::getCommentsOnProfilePostPaginated()
     */
   
public function actionGet(ParameterBag $params)
    {
       
$profilePost = $this->assertViewableProfilePost($params->profile_post_id, 'api|profile');

        if (
$this->filter('with_comments', 'bool'))
        {
           
$commentData = $this->getCommentsOnProfilePostPaginated($profilePost, $this->filterPage());
        }
        else
        {
           
$commentData = [];
        }

       
$result = $profilePost->toApiResult(
           
Entity::VERBOSITY_VERBOSE, [
           
'with_profile' => true
       
]
        );

       
$result = [
           
'profile_post' => $result
       
];
       
$result += $commentData;

        return
$this->apiResult($result);
    }

   
/**
     * @api-desc Gets a page of comments on the specified profile post.
     *
     * @api-in   int $page
     *
     * @api-see  self::getCommentsOnProfilePostPaginated
     */
   
public function actionGetComments(ParameterBag $params)
    {
       
$profilePost = $this->assertViewableProfilePost($params->profile_post_id);

       
$commentData = $this->getCommentsOnProfilePostPaginated($profilePost, $this->filterPage());

        return
$this->apiResult($commentData);
    }

   
/**
     *
     * @api-in  string $direction Request a particular sort order for comments - default 'desc' (newest first) also allows 'asc' (oldest first)
     *
     * @api-out ProfilePostComment[] $comments List of comments on the requested page
     * @api-out pagination $pagination Pagination details
     *
     * @param \XF\Entity\ProfilePost $profilePost
     * @param int                    $page
     * @param null|int               $perPage
     *
     * @return array
     *
     * @throws \XF\Mvc\Reply\Exception
     */
   
protected function getCommentsOnProfilePostPaginated(\XF\Entity\ProfilePost $profilePost, $page = 1, $perPage = null)
    {
       
$perPage = intval($perPage);
        if (
$perPage <= 0)
        {
           
$perPage = $this->options()->messagesPerPage;
        }

       
$commentFinder = $this->setupCommentsFinder($profilePost);

       
$total = $commentFinder->total();
       
$this->assertValidApiPage($page, $perPage, $total);

       
$commentFinder->limitByPage($page, $perPage);
       
$postResults = $commentFinder->fetch()->toApiResults();

       
/** @var \XF\Repository\Attachment $attachmentRepo */
       
$attachmentRepo = $this->repository('XF:Attachment');
       
$attachmentRepo->addAttachmentsToContent($postResults, 'profile_post_comment');

        return [
           
'comments' => $postResults,
           
'pagination' => $this->getPaginationData($postResults, $page, $perPage, $total)
        ];
    }

   
/**
     * @param \XF\Entity\ProfilePost $profilePost
     *
     * @return \XF\Finder\ProfilePostComment
     */
   
protected function setupCommentsFinder(\XF\Entity\ProfilePost $profilePost)
    {
       
/** @var \XF\Finder\ProfilePostComment $finder */
       
$finder = $this->finder('XF:ProfilePostComment');
       
$finder
           
->forProfilePost($profilePost)
            ->
with('api');

       
$this->applyCommentOrder($finder);

        return
$finder;
    }

   
/**
     * @param Finder $finder
     *
     * @return array [order, direction] as applied
     */
   
protected function applyCommentOrder(Finder $finder): array
    {
       
$order = 'comment_date'; // alternative orders are not available at this time

       
$direction = $this->filter('direction', 'str');
        if (
$direction !== 'asc')
        {
           
$direction = 'desc';
        }

       
$finder->order($order, $direction);

        return [
$order, $direction];
    }

   
/**
     * @api-desc Updates the specified profile post.
     *
     * @api-in str $message
     * @api-in bool $author_alert
     * @api-in bool $author_alert_reason
     * @api-in str $attachment_key API attachment key to upload files. Attachment key context type must be profile_post with context[profile_post_id] set to this profile post ID.
     *
     * @api-out true $success
     * @api-out ProfilePost $profile_post
     */
   
public function actionPost(ParameterBag $params)
    {
       
$profilePost = $this->assertViewableProfilePost($params->profile_post_id);

        if (\
XF::isApiCheckingPermissions() && !$profilePost->canEdit($error))
        {
            return
$this->noPermission($error);
        }

       
$editor = $this->setupProfilePostEdit($profilePost);

        if (\
XF::isApiCheckingPermissions())
        {
           
$editor->checkForSpam();
        }

        if (!
$editor->validate($errors))
        {
            return
$this->error($errors);
        }

       
$editor->save();

        return
$this->apiSuccess([
           
'profile_post' => $profilePost->toApiResult(Entity::VERBOSITY_VERBOSE)
        ]);
    }

   
/**
     * @param \XF\Entity\ProfilePost $profilePost
     *
     * @return \XF\Service\ProfilePost\Editor
     */
   
protected function setupProfilePostEdit(\XF\Entity\ProfilePost $profilePost)
    {
       
$input = $this->filter([
           
'message' => '?str',
           
'author_alert' => 'bool',
           
'author_alert_reason' => 'str',
           
'attachment_key' => 'str'
       
]);

       
/** @var \XF\Service\ProfilePost\Editor $editor */
       
$editor = $this->service('XF:ProfilePost\Editor', $profilePost);

        if (
$input['message'] !== null)
        {
           
$editor->setMessage($input['message']);
        }

        if (\
XF::isApiBypassingPermissions() || $profilePost->canUploadAndManageAttachments())
        {
           
$hash = $this->getAttachmentTempHashFromKey(
               
$input['attachment_key'],
               
'profile_post',
                [
'profile_post_id' => $profilePost->profile_post_id]
            );
           
$editor->setAttachmentHash($hash);
        }

        if (
$input['author_alert'] && $profilePost->canSendModeratorActionAlert())
        {
           
$editor->setSendAlert(true, $input['author_alert_reason']);
        }

        return
$editor;
    }

   
/**
     * @api-desc Deletes the specified profile post. Default to soft deletion.
     *
     * @api-in bool $hard_delete
     * @api-in str $reason
     * @api-in bool $author_alert
     * @api-in str $author_alert_reason
     *
     * @api-out true $success
     */
   
public function actionDelete(ParameterBag $params)
    {
       
$profilePost = $this->assertViewableProfilePost($params->profile_post_id);

        if (\
XF::isApiCheckingPermissions() && !$profilePost->canDelete('soft', $error))
        {
            return
$this->noPermission($error);
        }

       
$type = 'soft';
       
$reason = $this->filter('reason', 'str');

        if (
$this->filter('hard_delete', 'bool'))
        {
           
$this->assertApiScope('profile_post:delete_hard');

            if (\
XF::isApiCheckingPermissions() && !$profilePost->canDelete('hard', $error))
            {
                return
$this->noPermission($error);
            }

           
$type = 'hard';
        }

       
/** @var \XF\Service\ProfilePost\Deleter $deleter */
       
$deleter = $this->service('XF:ProfilePost\Deleter', $profilePost);

        if (
$this->filter('author_alert', 'bool') && $profilePost->canSendModeratorActionAlert())
        {
           
$deleter->setSendAlert(true, $this->filter('author_alert_reason', 'str'));
        }

       
$deleter->delete($type, $reason);

        return
$this->apiSuccess();
    }

   
/**
     * @api-desc Reacts to the specified profile post
     *
     * @api-see \XF\Api\ControllerPlugin\Reaction::actionReact()
     */
   
public function actionPostReact(ParameterBag $params)
    {
       
$profilePost = $this->assertViewableProfilePost($params->profile_post_id);

       
/** @var \XF\Api\ControllerPlugin\Reaction $reactPlugin */
       
$reactPlugin = $this->plugin('XF:Api:Reaction');
        return
$reactPlugin->actionReact($profilePost);
    }

   
/**
     * @param int $id
     * @param string|array $with
     *
     * @return \XF\Entity\ProfilePost
     *
     * @throws \XF\Mvc\Reply\Exception
     */
   
protected function assertViewableProfilePost($id, $with = 'api')
    {
        return
$this->assertViewableApiRecord('XF:ProfilePost', $id, $with);
    }
}