Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Search/Data/Post.php
<?php

namespace XF\Search\Data;

use
XF\Mvc\Entity\Entity;
use
XF\Search\IndexRecord;
use
XF\Search\MetadataStructure;
use
XF\Search\Query\MetadataConstraint;

class
Post extends AbstractData
{
    public function
getEntityWith($forView = false)
    {
       
$get = ['Thread', 'Thread.Forum'];
        if (
$forView)
        {
           
$get[] = 'User';

           
$visitor = \XF::visitor();
           
$get[] = 'Thread.Forum.Node.Permissions|' . $visitor->permission_combination_id;
        }

        return
$get;
    }

    public function
getIndexData(Entity $entity)
    {
       
/** @var \XF\Entity\Post $entity */

       
if (!$entity->Thread || !$entity->Thread->Forum)
        {
            return
null;
        }

       
/** @var \XF\Entity\Thread $thread */
       
$thread = $entity->Thread;

        if (
$entity->isFirstPost())
        {
            return
$this->searcher->handler('thread')->getIndexData($thread);
        }

       
$index = IndexRecord::create('post', $entity->post_id, [
           
'message' => $entity->message_,
           
'date' => $entity->post_date,
           
'user_id' => $entity->user_id,
           
'discussion_id' => $entity->thread_id,
           
'metadata' => $this->getMetaData($entity)
        ]);

        if (!
$entity->isVisible())
        {
           
$index->setHidden();
        }

        return
$index;
    }

    protected function
getMetaData(\XF\Entity\Post $entity)
    {
       
/** @var \XF\Entity\Thread $thread */
       
$thread = $entity->Thread;

       
$metadata = [
           
'node' => $thread->node_id,
           
'thread' => $entity->thread_id
       
];
        if (
$thread->prefix_id)
        {
           
$metadata['prefix'] = $thread->prefix_id;
        }

        return
$metadata;
    }

    public function
setupMetadataStructure(MetadataStructure $structure)
    {
       
$structure->addField('node', MetadataStructure::INT);
       
$structure->addField('thread', MetadataStructure::INT);
       
$structure->addField('prefix', MetadataStructure::INT);
    }

    public function
canIncludeInResults(Entity $entity, array $resultIds)
    {
       
/** @var \XF\Entity\Post $entity */
       
if (isset($resultIds['thread-' . $entity->thread_id]) && $entity->isFirstPost())
        {
            return
false;
        }

        return
true;
    }

    public function
getResultDate(Entity $entity)
    {
        return
$entity->post_date;
    }

    public function
getTemplateData(Entity $entity, array $options = [])
    {
        return [
           
'post' => $entity,
           
'options' => $options
       
];
    }

    public function
getSearchableContentTypes()
    {
        return [
'post', 'thread'];
    }

    public function
getSearchFormTab()
    {
        return [
           
'title' => \XF::phrase('search_threads'),
           
'order' => 10
       
];
    }

    public function
getSectionContext()
    {
        return
'forums';
    }

    public function
getSearchFormData()
    {
       
$prefixListData = $this->getPrefixListData();

        return [
           
'prefixGroups' => $prefixListData['prefixGroups'],
           
'prefixesGrouped' => $prefixListData['prefixesGrouped'],

           
'nodeTree' => $this->getSearchableNodeTree()
        ];
    }

   
/**
     * @return \XF\Tree
     */
   
protected function getSearchableNodeTree()
    {
       
/** @var \XF\Repository\Node $nodeRepo */
       
$nodeRepo = \XF::repository('XF:Node');
       
$nodeTree = $nodeRepo->createNodeTree($nodeRepo->getNodeList());

       
// only list nodes that are forums or contain forums
       
$nodeTree = $nodeTree->filter(null, function($id, $node, $depth, $children, $tree)
        {
            return (
$children || $node->node_type_id == 'Forum');
        });

        return
$nodeTree;
    }

    protected function
getPrefixListData()
    {
       
/** @var \XF\Repository\ThreadPrefix $prefixRepo */
       
$prefixRepo = \XF::repository('XF:ThreadPrefix');
        return
$prefixRepo->getVisiblePrefixListData();
    }

    public function
applyTypeConstraintsFromInput(\XF\Search\Query\Query $query, \XF\Http\Request $request, array &$urlConstraints)
    {
       
$minReplyCount = $request->filter('c.min_reply_count', 'uint');
        if (
$minReplyCount)
        {
           
$query->withSql(new \XF\Search\Query\SqlConstraint(
               
'thread.reply_count >= %s',
               
$minReplyCount,
               
$this->getThreadQueryTableReference()
            ));
        }
        else
        {
            unset(
$urlConstraints['min_reply_count']);
        }

       
$prefixes = $request->filter('c.prefixes', 'array-uint');
       
$prefixes = array_unique($prefixes);
        if (
$prefixes && reset($prefixes))
        {
           
$query->withMetadata('prefix', $prefixes);
        }
        else
        {
            unset(
$urlConstraints['prefixes']);
        }

       
$threadId = $request->filter('c.thread', 'uint');
        if (
$threadId)
        {
           
$query->withMetadata('thread', $threadId);

            if (
$query instanceof \XF\Search\Query\KeywordQuery)
            {
               
$query->inTitleOnly(false);
            }
        }
        else
        {
            unset(
$urlConstraints['thread']);

           
$nodeIds = $request->filter('c.nodes', 'array-uint');
           
$nodeIds = array_values(array_unique($nodeIds));
            if (
$nodeIds && reset($nodeIds))
            {
                if (
$request->filter('c.child_nodes', 'bool'))
                {
                   
/** @var \XF\Repository\Node $nodeRepo */
                   
$nodeRepo = \XF::repository('XF:Node');
                   
$nodeTree = $nodeRepo->createNodeTree($nodeRepo->getFullNodeListWithTypeData()->filterViewable());

                   
$searchNodeIds = array_fill_keys($nodeIds, true);
                   
$nodeTree->traverse(function($id, $node) use (&$searchNodeIds)
                    {
                        if (isset(
$searchNodeIds[$id]) || isset($searchNodeIds[$node->parent_node_id]))
                        {
                           
// if we're in the search node list, the user selected the node explicitly
                            // if the parent is in the list, then that node was selected via traversal so we're included too
                           
$searchNodeIds[$id] = true;
                        }

                       
// we still need to traverse children though, as children may be selected
                   
});

                   
$nodeIds = array_unique(array_keys($searchNodeIds));
                }
                else
                {
                    unset(
$urlConstraints['child_nodes']);
                }

               
$query->withMetadata('node', $nodeIds);
            }
            else
            {
                unset(
$urlConstraints['nodes']);
                unset(
$urlConstraints['child_nodes']);
            }
        }

       
// this will implicitly limit results to just the thread record so it's not currently exposed to the UI
       
$threadType = $request->filter('c.thread_type', 'str');
        if (
$threadType)
        {
           
$query->withMetadata('thread_type', $threadType);
        }
        else
        {
            unset(
$urlConstraints['thread_type']);
        }
    }

    public function
getTypePermissionConstraints(\XF\Search\Query\Query $query, $isOnlyType)
    {
       
$skip = [];
       
$forums = \XF::em()->getFinder('XF:Forum')
            ->
with('Node.Permissions|' . \XF::visitor()->permission_combination_id)
            ->
fetch();

        foreach (
$forums AS $forum)
        {
            if (!
$forum->canView())
            {
               
$skip[] = $forum->node_id;
            }
        }

        if (
$skip)
        {
            return [
                new
MetadataConstraint('node', $skip, MetadataConstraint::MATCH_NONE)
            ];
        }
        else
        {
            return [];
        }
    }

    public function
getTypeOrder($order)
    {
        if (
$order == 'replies')
        {
            return new \
XF\Search\Query\SqlOrder('thread.reply_count DESC', $this->getThreadQueryTableReference());
        }
        else
        {
            return
null;
        }
    }

    protected function
getThreadQueryTableReference()
    {
        return new \
XF\Search\Query\TableReference(
           
'thread',
           
'xf_thread',
           
'thread.thread_id = search_index.discussion_id'
       
);
    }

    public function
getGroupByType()
    {
        return
'thread';
    }

    public function
canUseInlineModeration(Entity $entity, &$error = null)
    {
       
/** @var \XF\Entity\Post $entity */
       
return $entity->canUseInlineModeration($error);
    }
}