www.gusucode.com > Flarum PHP论坛 中文版 v0.1 beta7源码程序 > FlarumChina-master/vendor/flarum/core/src/Core/Search/Discussion/DiscussionSearcher.php
<?php /* * This file is part of Flarum. * * (c) Toby Zerner <toby.zerner@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Flarum\Core\Search\Discussion; use Flarum\Core\Discussion; use Flarum\Core\Repository\DiscussionRepository; use Flarum\Core\Repository\PostRepository; use Flarum\Core\Search\ApplySearchParametersTrait; use Flarum\Core\Search\GambitManager; use Flarum\Core\Search\SearchCriteria; use Flarum\Core\Search\SearchResults; use Flarum\Event\ConfigureDiscussionSearch; use Illuminate\Database\Eloquent\Collection; /** * Takes a DiscussionSearchCriteria object, performs a search using gambits, * and spits out a DiscussionSearchResults object. */ class DiscussionSearcher { use ApplySearchParametersTrait; /** * @var GambitManager */ protected $gambits; /** * @var DiscussionRepository */ protected $discussions; /** * @var PostRepository */ protected $posts; /** * @param GambitManager $gambits * @param DiscussionRepository $discussions * @param PostRepository $posts */ public function __construct( GambitManager $gambits, DiscussionRepository $discussions, PostRepository $posts ) { $this->gambits = $gambits; $this->discussions = $discussions; $this->posts = $posts; } /** * @param SearchCriteria $criteria * @param int|null $limit * @param int $offset * @param array $load An array of relationships to load on the results. * @return SearchResults */ public function search(SearchCriteria $criteria, $limit = null, $offset = 0, array $load = []) { $actor = $criteria->actor; $query = $this->discussions->query()->whereVisibleTo($actor); // Construct an object which represents this search for discussions. // Apply gambits to it, sort, and paging criteria. Also give extensions // an opportunity to modify it. $search = new DiscussionSearch($query->getQuery(), $actor); $this->gambits->apply($search, $criteria->query); $this->applySort($search, $criteria->sort); $this->applyOffset($search, $offset); $this->applyLimit($search, $limit + 1); // TODO: inject dispatcher event(new ConfigureDiscussionSearch($search, $criteria)); // Execute the search query and retrieve the results. We get one more // results than the user asked for, so that we can say if there are more // results. If there are, we will get rid of that extra result. $discussions = $query->get(); $areMoreResults = $limit > 0 && $discussions->count() > $limit; if ($areMoreResults) { $discussions->pop(); } // The relevant posts relationship isn't a typical Eloquent // relationship; rather, we need to extract that information from our // search object. We will delegate that task and prevent Eloquent // from trying to load it. if (in_array('relevantPosts', $load)) { $this->loadRelevantPosts($discussions, $search); $load = array_diff($load, ['relevantPosts', 'relevantPosts.discussion', 'relevantPosts.user']); } Discussion::setStateUser($actor); $discussions->load($load); return new SearchResults($discussions, $areMoreResults); } /** * Load relevant posts onto each discussion using information from the * search. * * @param Collection $discussions * @param DiscussionSearch $search */ protected function loadRelevantPosts(Collection $discussions, DiscussionSearch $search) { $postIds = []; foreach ($search->getRelevantPostIds() as $relevantPostIds) { $postIds = array_merge($postIds, array_slice($relevantPostIds, 0, 2)); } $posts = $postIds ? $this->posts->findByIds($postIds, $search->getActor())->load('user')->all() : []; foreach ($discussions as $discussion) { $discussion->relevantPosts = array_filter($posts, function ($post) use ($discussion) { return $post->discussion_id == $discussion->id; }); } } }