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

namespace XF\Api\Controller;

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

use function
intval;

/**
 * @api-group Conversations
 */
class Conversation extends AbstractController
{
    protected function
preDispatchController($action, ParameterBag $params)
    {
       
$this->assertApiScopeByRequestMethod('conversation');
    }

   
/**
     * @api-desc Gets information about the specified conversation.
     *
     * @api-in bool $with_messages If specified, the response will include a page of messages.
     * @api-in int $page The page of messages to include
     *
     * @api-out Conversation $conversation
     * @api-see self::getMessagesInConversationPaginated()
     */
   
public function actionGet(ParameterBag $params)
    {
       
$userConv = $this->assertViewableUserConversation($params->conversation_id);

        if (
$this->filter('with_messages', 'bool'))
        {
           
$messageData = $this->getMessagesInConversationPaginated($userConv->Master, $this->filterPage());
        }
        else
        {
           
$messageData = [];
        }

       
$result = [
           
'conversation' => $userConv->toApiResult(Entity::VERBOSITY_VERBOSE)
        ];
       
$result += $messageData;

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

   
/**
     * @api-desc Gets a page of messages in the specified conversation.
     *
     * @api-in int $page
     *
     * @api-see self::getMessagesInConversationPaginated
     */
   
public function actionGetMessages(ParameterBag $params)
    {
       
$userConv = $this->assertViewableUserConversation($params->conversation_id);

       
$messageData = $this->getMessagesInConversationPaginated($userConv->Master, $this->filterPage());

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

   
/**
     * @api-out ConversationMessage[] $messages List of messages on the requested page
     * @api-out pagination $pagination Pagination details
     *
     * @param \XF\Entity\ConversationMaster $conversation
     * @param int $page
     * @param null $perPage
     *
     * @return array
     */
   
protected function getMessagesInConversationPaginated(\XF\Entity\ConversationMaster $conversation, $page = 1, $perPage = null)
    {
       
$perPage = intval($perPage);
        if (
$perPage <= 0)
        {
           
$perPage = $this->options()->messagesPerPage;
        }
       
$total = $conversation->reply_count + 1;

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

       
$finder = $this->setupMessageFinder($conversation);
       
$messages = $finder->limitByPage($page, $perPage)->fetch();

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

       
$messageResults = $messages->toApiResults();

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

   
/**
     * @param \XF\Entity\ConversationMaster $conversation
     *
     * @return \XF\Finder\ConversationMessage
     */
   
protected function setupMessageFinder(\XF\Entity\ConversationMaster $conversation)
    {
       
/** @var \XF\Finder\ConversationMessage $finder */
       
$finder = $this->finder('XF:ConversationMessage');
       
$finder
           
->inConversation($conversation)
            ->
order('message_date')
            ->
with('api');

        return
$finder;
    }

   
/**
     * @param \XF\Entity\ConversationMaster $conversation
     *
     * @return \XF\Service\Conversation\Editor
     */
   
protected function setupConversationEdit(\XF\Entity\ConversationMaster $conversation)
    {
       
/** @var \XF\Service\Conversation\Editor $editor */
       
$editor = $this->service('XF:Conversation\Editor', $conversation);

       
$input = $this->filter([
           
'title' => '?str',
           
'conversation_open' => '?bool',
           
'open_invite' => '?bool'
       
]);

        if (isset(
$input['title']))
        {
           
$editor->setTitle($input['title']);
        }
        if (isset(
$input['open_invite']))
        {
           
$editor->setOpenInvite($input['open_invite']);
        }
        if (isset(
$input['conversation_open']))
        {
           
$editor->setConversationOpen($input['conversation_open']);
        }

        return
$editor;
    }

   
/**
     * @api-desc Updates the specified conversation
     *
     * @api-in str $title Conversation title
     * @api-in bool $open_invite If true, any member of the conversation can add others
     * @api-in bool $conversation_open If false, no further replies are allowed.
     *
     * @api-out true $success
     * @api-out Conversation $conversation
     */
   
public function actionPost(ParameterBag $params)
    {
       
$userConv = $this->assertViewableUserConversation($params->conversation_id);
       
$conversation = $userConv->Master;

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

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

       
$editor->save();

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

   
/**
     * @api-desc Sets the star status of the specified conversation
     *
     * @api-in bool $star If provided, sets the star status as specified. If not provided, toggles the status.
     *
     * @api-out true $success
     */
   
public function actionPostStar(ParameterBag $params)
    {
       
$userConv = $this->assertViewableUserConversation($params->conversation_id);

       
$star = $this->filter('star', '?bool');
        if (
$star === null)
        {
           
$star = $userConv->is_starred ? false : true;
        }

       
$userConv->is_starred = $star;
       
$userConv->save();

        return
$this->apiSuccess();
    }

   
/**
     * @api-desc Marks the conversation as read up until the specified time. This cannot move the
     *  read marking date to an earlier point in time.
     *
     * @api-in int $date Unix timestamp to mark the conversation read to. If not specified, defaults to the current time.
     *
     * @api-out true $success
     */
   
public function actionPostMarkRead(ParameterBag $params)
    {
       
$userConv = $this->assertViewableUserConversation($params->conversation_id);

       
$readDate = $this->filter('date', 'uint');
        if (!
$readDate)
        {
           
$readDate = null;
        }

       
$this->repository('XF:Conversation')->markUserConversationRead($userConv, $readDate);

        return
$this->apiSuccess();
    }

   
/**
     * @api-desc Marks a conversation as unread. This will mark all messages in the conversation as unread.
     *
     * @api-out true $success
     */
   
public function actionPostMarkUnread(ParameterBag $params)
    {
       
$userConv = $this->assertViewableUserConversation($params->conversation_id);

       
$this->repository('XF:Conversation')->markUserConversationUnread($userConv);

        return
$this->apiSuccess();
    }

   
/**
     * @api-desc Invites the specified users to this conversation.
     *
     * @api-in <req> int[] $recipient_ids List of user IDs to invite
     *
     * @api-out true $success
     */
   
public function actionPostInvite(ParameterBag $params)
    {
       
$userConv = $this->assertViewableUserConversation($params->conversation_id);
       
$conversation = $userConv->Master;

        if (\
XF::isApiCheckingPermissions() && !$conversation->canInvite())
        {
            return
$this->noPermission();
        }

       
$this->assertRequiredApiInput('recipient_ids');

       
/** @var \XF\Service\Conversation\Inviter $inviter */
       
$inviter = $this->service('XF:Conversation\Inviter', $conversation, \XF::visitor());

       
$recipientIds = $this->filter('recipient_ids', 'array-uint');
       
$recipients = $this->em()->findByIds('XF:User', $recipientIds);

        if (\
XF::isApiBypassingPermissions())
        {
           
$inviter->overrideMaxAllowed(-1);
        }
       
$inviter->setRecipients($recipients, \XF::isApiCheckingPermissions());

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

       
$inviter->save();

        return
$this->apiSuccess();
    }

   
/**
     * @api-desc Deletes the specified conversation from the API user's list. Does not delete the conversation for other receivers.
     *
     * @api-in bool $ignore If true, further replies to this conversation will be ignored. (Otherwise, replies will restore this conversation to the list.)
     *
     * @api-out true $success
     */
   
public function actionDelete(ParameterBag $params)
    {
       
$userConv = $this->assertViewableUserConversation($params->conversation_id);

       
$recipient = $userConv->Recipient;
        if (
$recipient)
        {
           
$recipient->recipient_state = $this->filter('ignore', 'bool') ? 'deleted_ignored' : 'deleted';
           
$recipient->save();
        }

        return
$this->apiSuccess();
    }

   
/**
     * @param int $id
     * @param string|array $with
     *
     * @return \XF\Entity\ConversationUser
     *
     * @throws \XF\Mvc\Reply\Exception
     */
   
protected function assertViewableUserConversation($id, $with = 'api')
    {
       
/** @var \XF\Api\ControllerPlugin\Conversation $conversationPlugin */
       
$conversationPlugin = $this->plugin('XF:Api:Conversation');
        return
$conversationPlugin->assertViewableUserConversation($id, $with);
    }
}