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

namespace XF\Api\Controller;

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

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

   
/**
     * @api-desc Gets a list of threads
     *
     * @api-in int $page
     * @api-see XF\Api\ControllerPlugin\Thread::applyThreadListFilters
     * @api-see XF\Api\ControllerPlugin\Thread::applyThreadListSort
     *
     * @api-out Thread[] $threads
     * @api-out pagination $pagination
     */
   
public function actionGet()
    {
       
$page = $this->filterPage();
       
$perPage = $this->options()->discussionsPerPage;

       
$threadFinder = $this->setupThreadFinder()->limitByPage($page, $perPage);
       
$total = $threadFinder->total();

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

       
$threads = $threadFinder->fetch();

        if (\
XF::isApiCheckingPermissions())
        {
           
// only filtered to the forums we could view -- could still be other conditions
           
$threads = $threads->filterViewable();
        }

        return
$this->apiResult([
           
'threads' => $threads->toApiResults(),
           
'pagination' => $this->getPaginationData($threads, $page, $perPage, $total)
        ]);
    }

   
/**
     * @param array $filters List of filters that have been applied from input
     * @param array|null $sort If array, sort that has been applied from input
     *
     * @return \XF\Finder\Thread
     */
   
protected function setupThreadFinder(&$filters = [], &$sort = null)
    {
       
$threadRepo = $this->repository('XF:Thread');
       
$threadFinder = $threadRepo->findThreadsForApi();

       
/** @var \XF\Api\ControllerPlugin\Thread $threadPlugin */
       
$threadPlugin = $this->plugin('XF:Api:Thread');

       
$filters = $threadPlugin->applyThreadListFilters($threadFinder);

       
$sort = $threadPlugin->applyThreadListSort($threadFinder);

        if (!isset(
$filters['last_days']))
        {
            if (!
$sort || ($sort[0] == 'last_post_date' && $sort[1] == 'desc'))
            {
               
$threadFinder->where('last_post_date', '>', $threadRepo->getReadMarkingCutOff());
            }
        }

        if (
$sort && $sort[0] == 'post_date' && $sort[1] == 'desc' && !$filters)
        {
           
// if sorting by post_date without any other filters, MySQL may choose not to use the
            // post_date index and that tends to be very inefficient
           
$threadFinder->indexHint('USE', 'post_date');
        }

        return
$threadFinder;
    }

   
/**
     * @return \XF\Api\Mvc\Reply\ApiResult|\XF\Mvc\Reply\Error
     * @throws \XF\Mvc\Reply\Exception
     *
     * @api-desc Creates a thread. Thread type data can be set using additional input specific to the target thread type.
     *
     * @api-in <req> int $node_id ID of the forum to create the thread in.
     * @api-in <req> str $title Title of the thread.
     * @api-in <req> str $message Body of the first post in the thread.
     * @api-in str $discussion_type The type of thread to create. Specific types may require additional input.
     * @api-in int $prefix_id ID of the prefix to apply to the thread. If not valid in the selected forum, will be ignored.
     * @api-in str[] $tags Array of tag names to apply to the thread.
     * @api-in string $custom_fields[<name>] Value to apply to the custom field with the specified name.
     * @api-in bool $discussion_open
     * @api-in bool $sticky
     * @api-in str $attachment_key API attachment key to upload files. Attachment key context type must be post with context[node_id] set to the ID of the forum this is being posted in.
     *
     * @api-out true $success
     * @api-out Thread $thread
     *
     * @api-error no_permission No permission error.
     */
   
public function actionPost()
    {
       
$this->assertRequiredApiInput(['node_id', 'title', 'message']);

       
$nodeId = $this->filter('node_id', 'uint');

       
/** @var \XF\Entity\Forum $forum */
       
$forum = $this->assertViewableApiRecord('XF:Forum', $nodeId);

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

       
$creator = $this->setupThreadCreate($forum);

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

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

       
/** @var \XF\Entity\Thread $thread */
       
$thread = $creator->save();
       
$this->finalizeThreadCreate($creator);

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

    protected function
setupThreadCreate(\XF\Entity\Forum $forum)
    {
       
$input = $this->filter([
           
'title' => 'str',
           
'message' => 'str',
           
'prefix_id' => 'uint',
           
'custom_fields' => 'array',
           
'tags' => 'array-str',
           
'discussion_open' => '?bool',
           
'sticky' => '?bool',
           
'attachment_key' => 'str',
           
'discussion_type' => 'str',
           
'allow_uncreatable_type' => 'bool'
       
]);

       
$isBypassingPermissions = \XF::isApiBypassingPermissions();

       
/** @var \XF\Service\Thread\Creator $creator */
       
$creator = $this->service('XF:Thread\Creator', $forum);

       
$allowUncreatable = \XF::isApiBypassingPermissions() && $input['allow_uncreatable_type'];
       
$creator->setDiscussionTypeAndDataForApi($input['discussion_type'], $this->request, [], $allowUncreatable);

       
$creator->setContent($input['title'], $input['message']);
       
$creator->setCustomFields($input['custom_fields']);

        if (
$input['prefix_id'] && ($isBypassingPermissions || $forum->isPrefixUsable($input['prefix_id'])))
        {
           
$creator->setPrefix($input['prefix_id']);
        }

        if (
$isBypassingPermissions || $forum->canEditTags())
        {
           
$creator->setTags($input['tags']);
        }

        if (
$isBypassingPermissions || $forum->canUploadAndManageAttachments())
        {
           
$hash = $this->getAttachmentTempHashFromKey($input['attachment_key'], 'post', ['node_id' => $forum->node_id]);
           
$creator->setAttachmentHash($hash);
        }

       
$thread = $creator->getThread();

        if (isset(
$input['discussion_open']) && ($isBypassingPermissions || $thread->canLockUnlock()))
        {
           
$creator->setDiscussionOpen($input['discussion_open']);
        }
        if (isset(
$input['sticky']) && ($isBypassingPermissions || $thread->canStickUnstick()))
        {
           
$creator->setSticky($input['sticky']);
        }

        return
$creator;
    }

    protected function
finalizeThreadCreate(\XF\Service\Thread\Creator $creator)
    {
       
$creator->sendNotifications();

       
$thread = $creator->getThread();
       
$visitor = \XF::visitor();

        if (
$visitor->user_id)
        {
           
$this->getThreadRepo()->markThreadReadByVisitor($thread, $thread->post_date);
        }
    }

   
/**
     * @return \XF\Repository\Thread
     */
   
protected function getThreadRepo()
    {
        return
$this->repository('XF:Thread');
    }

   
/**
     * @return \XF\Repository\Post
     */
   
protected function getPostRepo()
    {
        return
$this->repository('XF:Post');
    }
}