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

namespace XF\Searcher;

use
XF\Mvc\Entity\Finder;

use function
is_array;

/**
 * @method \XF\Finder\Thread getFinder()
 */
class Thread extends AbstractSearcher
{
    protected
$allowedRelations = ['Forum'];

    protected
$formats = [
       
'title' => 'like',
       
'username' => 'like',
       
'post_date' => 'date',
       
'last_post_date' => 'date'
   
];

    protected
$arrayValueKeys = [
       
'thread_field'
   
];

    protected
$whitelistOrder = [
       
'title' => true,
       
'username' => true,
       
'post_date' => true,
       
'last_post_date' => true,
       
'reply_count' => true,
       
'view_count' => true,
       
'first_post_reaction_score' => true,
       
'vote_score' => true
   
];

    protected
$order = [['last_post_date', 'desc']];

    protected function
getEntityType()
    {
        return
'XF:Thread';
    }

    protected function
getDefaultOrderOptions()
    {
        return [
           
'last_post_date' => \XF::phrase('forum_sort.last_post_date'),
           
'post_date' => \XF::phrase('forum_sort.post_date'),
           
'title' => \XF::phrase('forum_sort.title'),
           
'reply_count' => \XF::phrase('forum_sort.reply_count'),
           
'view_count' => \XF::phrase('forum_sort.view_count'),
           
'first_post_reaction_score' => \XF::phrase('forum_sort.first_post_reaction_score'),
           
'vote_score' => \XF::phrase('forum_sort.vote_score')
        ];
    }

    protected function
validateSpecialCriteriaValueAfter($key, &$value, $column, $format, $relation)
    {
        if (
$key == 'posted_in_last' || $key == 'last_post_in_last')
        {
            if (!
is_array($value) || !isset($value['value']) || $value['value'] <= 0)
            {
                return
false;
            }
        }
        if (
$key == 'prefix_id' && $value == -1)
        {
            return
false;
        }
        if (
$key == 'node_id')
        {
            if (
               
$value == 0
               
|| (is_array($value) && isset($value[0]) && $value[0] == 0)
            )
            {
                return
false;
            }
        }
        if (
            (
$key == 'starter_user_group_id' || $key == 'starter_not_user_group_id')
            && !
$value
       
)
        {
            return
false;
        }

        return
null;
    }

    protected function
applySpecialCriteriaValue(Finder $finder, $key, $value, $column, $format, $relation)
    {
        if (
$key == 'node_id')
        {
            if (!
is_array($value))
            {
               
$value = [$value];
            }

            if (isset(
$value['search_type']) && $value['search_type'] === 'exclude')
            {
               
$matchInForums = false;
            }
            else
            {
               
$matchInForums = true;
            }
            unset(
$value['search_type']);

           
$finder->where('node_id', $matchInForums ? '=' : '<>', $value);

            return
true;
        }

        if (
$key == 'thread_type')
        {
           
$finder->where('discussion_type', $value);
        }

        if (
$key == 'posted_in_last' || $key == 'last_post_in_last')
        {
           
$cutOff = $this->convertRelativeTimeToCutoff(
               
$value['value'],
               
$value['unit']
            );
            if (
$cutOff)
            {
               
$column = $key == 'posted_in_last' ? 'post_date' : 'last_post_date';

               
$finder->where($column, '>=', $cutOff);
            }
            return
true;
        }

        if (
$key == 'not_discussion_type')
        {
           
$finder->where('discussion_type', '<>', $value);
            return
true;
        }

        if (
$key == 'thread_field')
        {
           
$exactMatchFields = !empty($value['exact']) ? $value['exact'] : []; // used for multi-choice field searches
           
$customFields = $value + $exactMatchFields;
            unset(
$customFields['exact']);

            foreach (
$customFields AS $fieldId => $value)
            {
                if (
$value === '' || (is_array($value) && !$value))
                {
                    continue;
                }

               
$finder->with('CustomFields|' . $fieldId);
               
$isExact = !empty($exactMatchFields[$fieldId]);
               
$conditions = [];

                foreach ((array)
$value AS $possible)
                {
                   
$columnName = 'CustomFields|' . $fieldId . '.field_value';
                    if (
$isExact)
                    {
                       
$conditions[] = [$columnName, '=', $possible];
                    }
                    else
                    {
                       
$conditions[] = [$columnName, 'LIKE', $finder->escapeLike($possible, '%?%')];
                    }
                }

                if (
$conditions)
                {
                   
$finder->whereOr($conditions);
                }
            }
        }

        if (
$key == 'tags')
        {
           
/** @var \XF\Repository\Tag $tagRepo */
           
$tagRepo = $this->em->getRepository('XF:Tag');

           
$tags = $tagRepo->splitTagList($value);
            if (
$tags)
            {
               
$validTags = $tagRepo->getTags($tags, $notFound);
                if (
$notFound)
                {
                   
// if they entered an unknown tag, we don't want to ignore it, so we need to force no results
                   
$finder->whereImpossible();
                }
                else
                {
                    foreach (
array_keys($validTags) AS $tagId)
                    {
                       
$finder->with('Tags|' . $tagId, true);
                    }
                }

                return
true;
            }
        }

        if (
$key == 'starter_user_group_id' || $key == 'starter_not_user_group_id')
        {
            if (!
is_array($value))
            {
               
$value = [$value];
            }

           
$finder->with('User');

           
$userGroupIdColumn = $finder->columnSqlName('User.user_group_id');
           
$secondaryGroupIdsColumn = $finder->columnSqlName('User.secondary_group_ids');
           
$positiveMatch = ($key == 'starter_user_group_id');
           
$parts = [];

           
// for negative matches, we default to allowing guests, but if they say "not the guest"
            // group, then we'll disable it
           
$orIsGuest = $positiveMatch ? false : true;

            foreach (
$value AS $userGroupId)
            {
               
$quotedGroupId = $finder->quote($userGroupId);
                if (
$positiveMatch)
                {
                   
$parts[] = "$userGroupIdColumn = $quotedGroupId "
                       
. "OR FIND_IN_SET($quotedGroupId, $secondaryGroupIdsColumn)";

                    if (
$userGroupId == \XF\Entity\User::GROUP_GUEST)
                    {
                       
// if explicitly selecting the guest group, allow guest threads
                        // as they're hard to filter for otherwise
                       
$parts[] = $finder->columnSqlName('user_id') . ' = 0';
                    }
                }
                else
                {
                   
$parts[] = "$userGroupIdColumn <> $quotedGroupId "
                       
. "AND FIND_IN_SET($quotedGroupId, $secondaryGroupIdsColumn) = 0";

                    if (
$userGroupId == \XF\Entity\User::GROUP_GUEST)
                    {
                       
$orIsGuest = false;
                    }
                }
            }
            if (
$parts)
            {
               
$joiner = $positiveMatch ? ' OR ' : ' AND ';
               
$sql = implode($joiner, $parts);
                if (
$orIsGuest)
                {
                   
$sql = "($sql) OR " . $finder->columnSqlName('user_id') . ' = 0';
                }
               
$finder->whereSql($sql);
            }
            return
true;
        }

        return
false;
    }

    public function
getFormData()
    {
       
/** @var \XF\Repository\ThreadPrefix $prefixRepo */
       
$prefixRepo = $this->em->getRepository('XF:ThreadPrefix');
       
$prefixes = $prefixRepo->getPrefixListData();

       
/** @var \XF\Repository\Node $nodeRepo */
       
$nodeRepo = $this->em->getRepository('XF:Node');
       
$forums = $nodeRepo->getNodeOptionsData(false, 'Forum');

       
/** @var \XF\Repository\UserGroup $userGroupRepo */
       
$userGroupRepo = $this->em->getRepository('XF:UserGroup');
       
$userGroups = $userGroupRepo->findUserGroupsForList()->fetch();

       
/** @var \XF\Repository\ThreadType */
       
$threadTypeRepo = $this->em->getRepository('XF:ThreadType');
       
$threadTypes = $threadTypeRepo->getThreadTypeListData();

        return [
           
'prefixes' => $prefixes,
           
'forums' => $forums,
           
'userGroups' => $userGroups,
           
'threadTypes' => $threadTypes,
        ];
    }

    public function
getFormDefaults()
    {
       
$threadTypes = \XF::app()->container('threadTypes');
        unset(
$threadTypes['redirect']);

        return [
           
'prefix_id' => -1,
           
'thread_type' => array_keys($threadTypes),
           
'node_id' => 0,

           
'reply_count' => ['end' => -1],
           
'view_count' => ['end' => -1],

           
'discussion_state' => ['visible', 'moderated', 'deleted'],
           
'discussion_open' => [0, 1],
           
'sticky' => [0, 1]
        ];
    }
}