protected function stickyChanged(Discussion $discussion, User $user, $isSticky)
 {
     $post = DiscussionStickiedPost::reply($discussion->id, $user->id, $isSticky);
     $post = $discussion->mergePost($post);
     if ($discussion->start_user_id !== $user->id) {
         $notification = new DiscussionStickiedBlueprint($post);
         $this->notifications->sync($notification, $post->exists ? [$discussion->startUser] : []);
     }
 }
 /**
  * Bootstrap the application events.
  *
  * @return void
  */
 public function boot()
 {
     Discussion::setValidator($this->app->make('validator'));
     $events = $this->app->make('events');
     $settings = $this->app->make('Flarum\\Core\\Settings\\SettingsRepository');
     $events->subscribe('Flarum\\Core\\Discussions\\Listeners\\DiscussionMetadataUpdater');
     $events->listen(ModelAllow::class, function (ModelAllow $event) use($settings) {
         if ($event->model instanceof Discussion) {
             if ($event->actor->hasPermission('discussion.' . $event->action)) {
                 return true;
             }
             if (($event->action === 'rename' || $event->action === 'delete') && $event->model->start_user_id == $event->actor->id) {
                 $allowRenaming = $settings->get('allow_renaming');
                 if ($allowRenaming === '-1' || $allowRenaming === 'reply' && $event->model->participants_count <= 1 || $event->model->start_time->diffInMinutes(Carbon::now()) < $allowRenaming) {
                     return true;
                 }
             }
         }
     });
     $events->listen(ScopeModelVisibility::class, function (ScopeModelVisibility $event) {
         if ($event->model instanceof Discussion) {
             $user = $event->actor;
             if (!$user->hasPermission('discussion.hide')) {
                 $event->query->where(function ($query) use($user) {
                     $query->whereNull('discussions.hide_time')->where('comments_count', '>', 0)->orWhere('start_user_id', $user->id);
                     event(new ScopeHiddenDiscussionVisibility($query, $user, 'discussion.hide'));
                 });
             }
         }
     });
 }
 /**
  * @param StartDiscussion $command
  * @return mixed
  */
 public function handle(StartDiscussion $command)
 {
     $actor = $command->actor;
     $data = $command->data;
     $this->forum->assertCan($actor, 'startDiscussion');
     // Create a new Discussion entity, persist it, and dispatch domain
     // events. Before persistance, though, fire an event to give plugins
     // an opportunity to alter the discussion entity based on data in the
     // command they may have passed through in the controller.
     $discussion = Discussion::start(array_get($data, 'attributes.title'), $actor);
     event(new DiscussionWillBeSaved($discussion, $actor, $data));
     $discussion->save();
     // Now that the discussion has been created, we can add the first post.
     // We will do this by running the PostReply command.
     try {
         $post = $this->bus->dispatch(new PostReply($discussion->id, $actor, $data));
     } catch (Exception $e) {
         $discussion->delete();
         throw $e;
     }
     // Before we dispatch events, refresh our discussion instance's
     // attributes as posting the reply will have changed some of them (e.g.
     // last_time.)
     $discussion->setRawAttributes($post->discussion->getAttributes(), true);
     $discussion->setStartPost($post);
     $this->dispatchEventsFor($discussion);
     $discussion->save();
     return $discussion;
 }
Example #4
0
 /**
  * {@inheritdoc}
  */
 protected function getDefaultAttributes($discussion)
 {
     $attributes = parent::getDefaultAttributes($discussion) + ['commentsCount' => (int) $discussion->comments_count, 'participantsCount' => (int) $discussion->participants_count, 'startTime' => $discussion->start_time->toRFC3339String(), 'lastTime' => $discussion->last_time ? $discussion->last_time->toRFC3339String() : null, 'lastPostNumber' => $discussion->last_post_number, 'canReply' => $discussion->can($this->actor, 'reply'), 'canRename' => $discussion->can($this->actor, 'rename'), 'canDelete' => $discussion->can($this->actor, 'delete')];
     Discussion::setStateUser($this->actor);
     if ($state = $discussion->state) {
         $attributes += ['readTime' => $state->read_time ? $state->read_time->toRFC3339String() : null, 'readNumber' => (int) $state->read_number];
     }
     return $attributes;
 }
 /**
  * Bootstrap the application events.
  *
  * @return void
  */
 public function boot()
 {
     Discussion::setValidator($this->app->make('validator'));
     $events = $this->app->make('events');
     $settings = $this->app->make('Flarum\\Core\\Settings\\SettingsRepository');
     $events->subscribe('Flarum\\Core\\Discussions\\Listeners\\DiscussionMetadataUpdater');
     $events->listen(ModelAllow::class, function (ModelAllow $event) use($settings) {
         if ($event->model instanceof Discussion) {
             if ($event->actor->hasPermission('discussion.' . $event->action)) {
                 return true;
             }
             if (($event->action === 'rename' || $event->action === 'delete') && $event->model->start_user_id == $event->actor->id) {
                 $allowRenaming = $settings->get('allow_renaming');
                 if ($allowRenaming === '-1' || $allowRenaming === 'reply' && $event->model->participants_count == 1 || $event->model->start_time->diffInMinutes(Carbon::now()) < $allowRenaming) {
                     return true;
                 }
             }
         }
     });
 }
Example #6
0
 public function whenDiscussionWillBeSaved(DiscussionWillBeSaved $event)
 {
     if (isset($event->data['relationships']['tags']['data'])) {
         $discussion = $event->discussion;
         $actor = $event->actor;
         $linkage = (array) $event->data['relationships']['tags']['data'];
         $newTagIds = [];
         foreach ($linkage as $link) {
             $newTagIds[] = (int) $link['id'];
         }
         $newTags = Tag::whereIn('id', $newTagIds)->get();
         $primaryCount = 0;
         $secondaryCount = 0;
         foreach ($newTags as $tag) {
             if (!$tag->can($actor, 'startDiscussion')) {
                 throw new PermissionDeniedException();
             }
             if ($tag->position !== null && $tag->parent_id === null) {
                 $primaryCount++;
             } else {
                 $secondaryCount++;
             }
         }
         $this->validatePrimaryTagCount($primaryCount);
         $this->validateSecondaryTagCount($secondaryCount);
         $oldTags = [];
         if ($discussion->exists) {
             $oldTags = $discussion->tags()->get();
             $oldTagIds = $oldTags->lists('id');
             if ($oldTagIds == $newTagIds) {
                 return;
             }
             $discussion->raise(new DiscussionWasTagged($discussion, $actor, $oldTags->all()));
         }
         Discussion::saved(function ($discussion) use($newTagIds) {
             $discussion->tags()->sync($newTagIds);
         });
     }
 }
Example #7
0
 /**
  * Get the IDs of discussions which a user has read completely.
  *
  * @param User $user
  * @return array
  */
 public function getReadIds(User $user)
 {
     return Discussion::leftJoin('users_discussions', 'users_discussions.discussion_id', '=', 'discussions.id')->where('user_id', $user->id)->where('read_number', '<', 'last_post_number')->lists('id');
 }
 /**
  * @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);
     event(new DiscussionSearchWillBePerformed($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();
     if ($areMoreResults = $limit > 0 && $discussions->count() > $limit) {
         $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);
 }
Example #9
0
 protected function filterDiscussionVisibleTo($ids, User $actor)
 {
     // For each post ID, we need to make sure that the discussion it's in
     // is visible to the user.
     if ($actor) {
         $ids = Discussion::join('posts', 'discussions.id', '=', 'posts.discussion_id')->whereIn('posts.id', $ids)->whereVisibleTo($actor)->get(['posts.id'])->lists('id');
     }
     return $ids;
 }
Example #10
0
 protected function importDiscussions($from, $to)
 {
     $this->info('Importing discussions...');
     $to->table('discussions')->truncate();
     $to->table('discussions_tags')->truncate();
     $to->table('posts')->truncate();
     $to->table('notifications')->truncate();
     $to->table('users_discussions')->truncate();
     $to->table('activity')->truncate();
     $to->table('mentions_posts')->truncate();
     $to->table('mentions_users')->truncate();
     $conversations = $from->table('conversation')->where('private', 0)->get();
     $progress = new ProgressBar($this->output, count($conversations));
     foreach ($conversations as $c) {
         $discussion = new Discussion();
         $discussion->id = $c->conversationId;
         $discussion->title = $c->title;
         $discussion->is_sticky = $c->sticky;
         $discussion->start_user_id = $c->startMemberId;
         $discussion->start_time = $c->startTime;
         $discussion->last_user_id = $c->lastPostMemberId;
         $discussion->last_time = $c->lastPostTime;
         $discussion->save();
         $discussion->tags()->sync([$c->channelId]);
         foreach ($from->table('post')->where('conversationId', $c->conversationId)->get() as $p) {
             $post = new CommentPost();
             $post->id = $p->postId;
             $post->discussion_id = $p->conversationId;
             $post->user_id = $p->memberId;
             $post->time = $p->time;
             $post->edit_user_id = $p->editMemberId;
             $post->edit_time = $p->editTime;
             $post->hide_user_id = $p->deleteMemberId;
             $post->hide_time = $p->deleteTime;
             $post->content = $p->content;
             $this->formatPost($post);
             $post->save();
             if (!$post->hide_time) {
                 event(new PostWasPosted($post));
             }
         }
         $discussion->last_post_id = $p->postId;
         $discussion->last_post_number = $post->number;
         $discussion->comments_count = $post->number;
         $discussion->save();
         $states = $from->table('member_conversation')->where('conversationId', $c->conversationId)->where('type', 'member')->get();
         foreach ($states as $s) {
             $state = new DiscussionState();
             $state->discussion_id = $s->conversationId;
             $state->user_id = $s->id;
             $state->read_time = time();
             $state->read_number = $discussion->posts()->orderBy('time', 'asc')->skip(min($discussion->comments_count, $s->lastRead) - 1)->pluck('number');
             $state->save();
         }
         $progress->advance();
     }
     $progress->finish();
     $this->info("\n");
 }