www.gusucode.com > Flarum PHP论坛 中文版 v0.1 beta7源码程序 > FlarumChina-master/vendor/flagrow/split/src/Api/Commands/SplitDiscussionHandler.php
<?php /* * This file is part of flagrow/flarum-ext-split. * * Copyright (c) Flagrow. * * http://flagrow.github.io * * For the full copyright and license information, please view the license.md * file that was distributed with this source code. */ namespace Flagrow\Split\Api\Commands; use Flagrow\Split\Events\DiscussionWasSplit; use Flagrow\Split\Validators\SplitDiscussionValidator; use Flarum\Core\Access\AssertPermissionTrait; use Flarum\Core\Discussion; use Flarum\Core\Post; use Flarum\Core\Repository\PostRepository; use Flarum\Core\Repository\UserRepository; use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Events\Dispatcher; class SplitDiscussionHandler { use AssertPermissionTrait; /** * @var UserRepository */ protected $users; /** * @var PostRepository */ protected $posts; /** * @var SettingsRepositoryInterface */ protected $settings; /** * @var SplitDiscussionValidator */ protected $validator; /** * @var Dispatcher */ protected $events; /** * @param UserRepository $users * @param PostRepository $posts * @param SettingsRepositoryInterface $settings * @param Dispatcher $events * @param SplitDiscussionValidator $validator */ public function __construct( UserRepository $users, PostRepository $posts, SettingsRepositoryInterface $settings, Dispatcher $events, SplitDiscussionValidator $validator ) { $this->users = $users; $this->posts = $posts; $this->settings = $settings; $this->events = $events; $this->validator = $validator; } /** * @param SplitDiscussion $command * @return \Flarum\Core\Discussion */ public function handle(SplitDiscussion $command) { $this->assertCan($command->actor, 'split'); $this->validator->assertValid([ 'start_post_id' => $command->start_post_id, 'end_post_number' => $command->end_post_number, 'title' => $command->title ]); // load the first selected post to split. $startPost = $this->posts->findOrFail($command->start_post_id, $command->actor); /** @var Discussion $originalDiscussion */ $originalDiscussion = $startPost->discussion; // create a new discussion for the user of the first splitted reply. $discussion = Discussion::start($command->title, $startPost->user); $discussion->setStartPost($startPost); // persist the new discussion. $discussion->save(); $this->assignTagsToDiscussion($originalDiscussion, $discussion); // update all posts that are split. $affectedPosts = $this->assignPostsToDiscussion( $originalDiscussion, $discussion, $startPost->number, $command->end_post_number ); $originalDiscussion = $this->refreshDiscussion($originalDiscussion); $this->renumberDiscussion($discussion); $discussion = $this->refreshDiscussion($discussion); $this->events->fire( new DiscussionWasSplit($command->actor, $affectedPosts, $originalDiscussion, $discussion) ); return $discussion; } /** * Assign the specific range to a new Discussion without resetting post numbers. * * @param Discussion $originalDiscussion * @param Discussion $discussion * @param $start_post_number * @param $end_post_number * @return \Illuminate\Database\Eloquent\Collection */ protected function assignPostsToDiscussion( Discussion $originalDiscussion, Discussion $discussion, $start_post_number, $end_post_number ) { $this->posts ->query() ->where('discussion_id', $originalDiscussion->id) ->whereBetween('number', [$start_post_number, $end_post_number]) ->update(['discussion_id' => $discussion->id]); $discussion->number_index = $end_post_number; $discussion->save(); // Update relationship posts on new discussion. $discussion->load('posts'); return $discussion->posts; } /** * Re-assign numbers starting from one to a discussion. * * @param Discussion $discussion */ protected function renumberDiscussion(Discussion $discussion) { $discussion->load('posts'); $number = 0; $discussion->posts->sortBy('time')->each(function (Post $post) use (&$number) { $number++; $post->number = $number; $post->save(); }); $discussion->number_index = $number; $discussion->save(); } /** * Refreshes count and last Post for the discussion. * * @param Discussion $discussion */ protected function refreshDiscussion(Discussion $discussion) { $discussion->refreshLastPost(); $discussion->refreshCommentsCount(); $discussion->refreshParticipantsCount(); // Persist the new statistics. $discussion->save(); return Discussion::find($discussion->id); } /** * Sets the tags for the new discussion based on the old one. * * @param $originalDiscussion * @param $discussion */ protected function assignTagsToDiscussion($originalDiscussion, $discussion) { if ($originalDiscussion->tags) { $discussion->tags()->sync($originalDiscussion->tags); } } }