Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Service/Thread/Editor.php
<?php

namespace XF\Service\Thread;

use
XF\Entity\Thread;
use
XF\Entity\User;

use function
is_array;

class
Editor extends \XF\Service\AbstractService
{
    use \
XF\Service\ValidateAndSavableTrait;

   
/**
     * @var Thread
     */
   
protected $thread;

   
/**
     * @var User
     */
   
protected $user;

   
/**
     * @var \XF\Service\Tag\Changer
     */
   
protected $tagChanger;

   
/** @var TypeData\SaverInterface|null */
   
protected $typeDataSaver;

    protected
$performValidations = true;

    public function
__construct(\XF\App $app, Thread $thread)
    {
       
parent::__construct($app);
       
$this->thread = $thread;
       
$this->user = \XF::visitor();

       
$this->tagChanger = $this->service('XF:Tag\Changer', 'thread', $thread);
    }

    public function
getThread()
    {
        return
$this->thread;
    }

    public function
getUser()
    {
        return
$this->user;
    }

    public function
setPerformValidations($perform)
    {
       
$this->performValidations = (bool)$perform;
    }

    public function
getPerformValidations()
    {
        return
$this->performValidations;
    }

    public function
setTypeDataSaver(TypeData\SaverInterface $saver = null)
    {
       
$this->typeDataSaver = $saver;
    }

    public function
getTypeDataSaver()
    {
        return
$this->typeDataSaver;
    }

    public function
setTitle($title)
    {
       
$this->thread->set('title', $title,
            [
'forceConstraint' => $this->performValidations ? false : true]
        );
    }

    public function
setPrefix($prefixId)
    {
       
$this->thread->prefix_id = $prefixId;
    }

    public function
setDiscussionOpen($discussionOpen)
    {
       
$this->thread->discussion_open = $discussionOpen;
    }

    public function
setDiscussionState($discussionState)
    {
       
$this->thread->discussion_state = $discussionState;
    }

    public function
setDiscussionTypeData(\XF\Http\Request $request, array $typeOptions = [])
    {
        return
$this->setDiscussionTypeDataInternal($request, $typeOptions);
    }

    public function
setDiscussionTypeDataForApi(\XF\Http\Request $request, array $typeOptions = [])
    {
        return
$this->setDiscussionTypeDataInternal($request, $typeOptions, 'api');
    }

    protected function
setDiscussionTypeDataInternal(\XF\Http\Request $request, array $typeOptions, $callType = '')
    {
       
$thread = $this->thread;
       
$typeHandler = $thread->TypeHandler;
       
$isApi = ($callType == 'api');

       
$typeOptions['editor'] = $this;

        if (
$isApi)
        {
           
$extraData = $typeHandler->processExtraDataForApiSimple(
               
$thread, 'edit', $request, $typeErrors, $typeOptions
           
);
        }
        else
        {
           
$extraData = $typeHandler->processExtraDataSimple(
               
$thread, 'edit', $request, $typeErrors, $typeOptions
           
);
        }

        if (
$extraData instanceof \XF\Mvc\Entity\ArrayValidator)
        {
           
$extraData->appendErrors($typeErrors);
           
$extraData = $extraData->getValuesForced();
        }

        if (
is_array($extraData))
        {
           
$thread->type_data = $extraData;
        }
        if (
$typeErrors)
        {
            foreach (
$typeErrors AS $error)
            {
               
$thread->error($error);
            }
        }

        if (
$isApi)
        {
           
$extraDataService = $typeHandler->processExtraDataForApiService(
               
$thread, 'edit', $request, $typeOptions
           
);
        }
        else
        {
           
$extraDataService = $typeHandler->processExtraDataService(
               
$thread, 'edit', $request, $typeOptions
           
);
        }

        if (
$extraDataService)
        {
           
$this->setTypeDataSaver($extraDataService);
        }

        return
true;
    }

    public function
setDiscussionTypeDataRaw(array $typeData)
    {
       
$this->thread->type_data = $typeData;
    }

    public function
setSticky($sticky)
    {
       
$this->thread->sticky = $sticky;
    }

    public function
setCustomFields(array $customFields, $subsetUpdate = false)
    {
       
$thread = $this->thread;

       
$editMode = $thread->getFieldEditMode();

       
/** @var \XF\CustomField\Set $fieldSet */
       
$fieldSet = $thread->custom_fields;
       
$fieldDefinition = $fieldSet->getDefinitionSet()
            ->
filterEditable($fieldSet, $editMode)
            ->
filterOnly($thread->Forum->field_cache);

       
$customFieldsShown = array_keys($fieldDefinition->getFieldDefinitions());

        if (
$subsetUpdate)
        {
           
// only updating the values passed through, so remove anything not present
           
foreach ($customFieldsShown AS $k => $fieldName)
            {
                if (!isset(
$customFields[$fieldName]))
                {
                    unset(
$customFieldsShown[$k]);
                }
            }
        }

        if (
$customFieldsShown)
        {
           
$fieldSet->bulkSet($customFields, $customFieldsShown, $editMode);
        }
    }

    public function
setTags($tags)
    {
        if (
$this->tagChanger->canEdit())
        {
           
$this->tagChanger->setEditableTags($tags);
        }
    }

    public function
addTags($tags)
    {
        if (
$this->tagChanger->canEdit())
        {
           
$this->tagChanger->addTags($tags);
        }
    }

    public function
removeTags($tags)
    {
        if (
$this->tagChanger->canEdit())
        {
           
$this->tagChanger->removeTags($tags);
        }
    }

    public function
checkForSpam()
    {
       
$thread = $this->thread;
       
$post = $thread->FirstPost;

        if (
$thread->discussion_state == 'visible' && $this->user->isSpamCheckRequired())
        {
           
$user = $this->user;

           
$message = $thread->title . "\n" . $post->message;

           
$checker = $this->app->spam()->contentChecker();
           
$checker->check($user, $message, [
               
'permalink' => $this->app->router('public')->buildLink('canonical:threads', $thread),
               
'content_type' => 'thread'
           
]);

           
$decision = $checker->getFinalDecision();
            switch (
$decision)
            {
                case
'moderated':

                   
$thread->discussion_state = 'moderated';
                    break;

                case
'denied':
                   
$checker->logSpamTrigger('thread', $thread->thread_id);
                   
$thread->error(\XF::phrase('your_content_cannot_be_submitted_try_later'));
                    break;
            }
        }
    }
   
    protected function
finalSetup()
    {
    }

    protected function
_validate()
    {
       
$this->finalSetup();

       
$thread = $this->thread;

        if (
$this->performValidations)
        {
           
$this->checkForSpam();
        }

       
$thread->preSave();
       
$errors = $thread->getErrors();

        if (
$this->performValidations)
        {
            if (!
$thread->prefix_id
               
&& $thread->Forum->require_prefix
               
&& $thread->Forum->getUsablePrefixes()
                && !
$thread->canMove()
            )
            {
               
$errors[] = \XF::phraseDeferred('please_select_a_prefix');
            }
           
// the canMove check allows moderators to bypass this requirement when editing; they're likely editing
            // another user's thread so don't force them to add a prefix

           
if ($this->tagChanger->canEdit() && $this->tagChanger->tagsChanged())
            {
               
$tagErrors = $this->tagChanger->getErrors();
                if (
$tagErrors)
                {
                   
$errors = array_merge($errors, $tagErrors);
                }
            }
        }

        if (
$this->typeDataSaver)
        {
            if (!
$this->typeDataSaver->validate($typeErrors))
            {
               
$errors = array_merge($errors, $typeErrors);
            }
        }

        return
$errors;
    }

    protected function
_save()
    {
       
$thread = $this->thread;

       
$db = $this->db();
       
$db->beginTransaction();

       
$thread->save(true, false);

        if (
$this->tagChanger->canEdit() && $this->tagChanger->tagsChanged())
        {
           
$this->tagChanger->save($this->performValidations);
        }

        if (
$this->typeDataSaver)
        {
           
$this->typeDataSaver->save();
        }

       
$db->commit();

        return
$thread;
    }
}