public function handle($command)
 {
     $command->forum->assertCan($command->user, '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($command->data, 'title'), $command->user);
     event(new DiscussionWillBeSaved($discussion, $command));
     $discussion->save();
     $this->dispatchEventsFor($discussion);
     // Now that the discussion has been created, we can add the first post.
     // For now we will do this by running the PostReply command, but as this
     // will trigger a domain event that is slightly semantically incorrect
     // in this situation (PostWasPosted), we may need to reconsider someday.
     $post = $this->bus->dispatch(new PostReplyCommand($discussion->id, $command->user, $command->data));
     return $post->discussion;
 }
Example #2
0
 public function search(DiscussionSearchCriteria $criteria, $limit = null, $offset = 0, $load = [])
 {
     $this->user = $criteria->user;
     $this->query = $this->discussions->query()->whereCan($criteria->user, 'view');
     $this->gambits->apply($criteria->query, $this);
     $total = $this->query->count();
     $sort = $criteria->sort ?: $this->defaultSort;
     foreach ($sort as $field => $order) {
         if (is_array($order)) {
             foreach ($order as $value) {
                 $this->query->orderByRaw(snake_case($field) . ' != ?', [$value]);
             }
         } else {
             $this->query->orderBy(snake_case($field), $order);
         }
     }
     if ($offset > 0) {
         $this->query->skip($offset);
     }
     if ($limit > 0) {
         $this->query->take($limit + 1);
     }
     event(new DiscussionSearchWillBePerformed($this, $criteria));
     $discussions = $this->query->get();
     if ($limit > 0 && ($areMoreResults = $discussions->count() > $limit)) {
         $discussions->pop();
     }
     if (in_array('relevantPosts', $load) && count($this->relevantPosts)) {
         $load = array_diff($load, ['relevantPosts']);
         $postIds = [];
         foreach ($this->relevantPosts as $id => $posts) {
             $postIds = array_merge($postIds, array_slice($posts, 0, 2));
         }
         $posts = $this->posts->findByIds($postIds, $this->user)->load('user');
         foreach ($discussions as $discussion) {
             $discussion->relevantPosts = $posts->filter(function ($post) use($discussion) {
                 return $post->discussion_id == $discussion->id;
             })->each(function ($post) {
                 $pos = strpos(strtolower($post->content), strtolower($this->fulltext));
                 // TODO: make clipping more intelligent (full words only)
                 $start = max(0, $pos - 50);
                 $post->content = ($start > 0 ? '...' : '') . str_limit(substr($post->content, $start), 300);
             });
         }
     }
     // @todo make instance rather than static and set on all discussions
     Discussion::setStateUser($this->user);
     $discussions->load($load);
     return new DiscussionSearchResults($discussions, $areMoreResults, $total);
 }
 /**
  * Run the database seeds.
  *
  * @return void
  */
 public function run()
 {
     Discussion::unguard();
     Post::unguard();
     $faker = \Faker\Factory::create();
     $users = User::count();
     for ($i = 0; $i < 100; $i++) {
         $posts_count = $i == 1 ? 400 : rand(1, rand(1, rand(1, 100)));
         $discussion = Discussion::create(['title' => str_replace("'", '', rtrim($faker->realText(rand(20, 80)), '.')), 'start_time' => $faker->dateTimeThisYear, 'start_user_id' => rand(1, $users)]);
         $discussion->comments_count = $posts_count;
         $post = CommentPost::create(['discussion_id' => $discussion->id, 'number' => 1, 'time' => $discussion->start_time, 'user_id' => $discussion->start_user_id, 'content' => $faker->realText(rand(100, 1000))]);
         $discussion->start_post_id = $post->id;
         $discussion->last_time = $post->time;
         $discussion->last_user_id = $post->user_id;
         $discussion->last_post_id = $post->id;
         $discussion->last_post_number = $post->number;
         $discussion->number_index = $post->number;
         $lastPost = null;
         $count = $posts_count;
         $posts = [];
         $startTime = $discussion->start_time;
         $numberOffset = 0;
         for ($j = 0; $j < $count - 1; $j++) {
             if (rand(1, 100) == 1) {
                 $discussion->comments_count--;
                 $post = DiscussionRenamedPost::create(['discussion_id' => $discussion->id, 'time' => $startTime = date_add($startTime, date_interval_create_from_date_string('1 second')), 'user_id' => rand(1, $users), 'content' => json_encode(array($faker->realText(rand(20, 40)), $discussion->title))]);
             } else {
                 $edited = rand(1, 20) == 1;
                 $hidden = rand(1, 100) == 1;
                 if ($hidden) {
                     $discussion->comments_count--;
                 }
                 $post = CommentPost::create(['discussion_id' => $discussion->id, 'number' => $j + 2 + $numberOffset, 'time' => $startTime = date_add($startTime, date_interval_create_from_date_string('1 second')), 'user_id' => rand(1, $users), 'content' => $faker->realText(rand(50, 500)), 'edit_time' => $edited ? $startTime = date_add($startTime, date_interval_create_from_date_string('1 second')) : null, 'edit_user_id' => $edited ? rand(1, $users) : null, 'hide_time' => $hidden ? $startTime = date_add($startTime, date_interval_create_from_date_string('1 second')) : null, 'hide_user_id' => $hidden ? rand(1, $users) : null]);
                 $posts[] = $post;
                 if (!$lastPost or $post->time >= $lastPost->time) {
                     $lastPost = $post;
                 }
             }
             if (rand(1, 20) == 1) {
                 $numberOffset += rand(0, 3);
             }
         }
         // Update the discussion's last post details.
         if ($lastPost) {
             $discussion->last_time = $lastPost->time;
             $discussion->last_user_id = $lastPost->user_id;
             $discussion->last_post_id = $lastPost->id;
             $discussion->last_post_number = $lastPost->number;
         }
         $discussion->number_index = $j + 1 + $numberOffset;
         $discussion->save();
         // Give some users some random discussion state data.
         for ($j = rand(0, 100); $j < 100; $j++) {
             try {
                 DiscussionState::create(['discussion_id' => $discussion->id, 'user_id' => rand(1, $users), 'read_number' => rand(0, $posts_count - 1), 'read_time' => $faker->dateTimeBetween($discussion->start_time, 'now')]);
             } catch (\Illuminate\Database\QueryException $e) {
             }
         }
     }
     // Update user post and discussion counts.
     $prefix = DB::getTablePrefix();
     DB::table('users')->update(['discussions_count' => DB::raw('(SELECT COUNT(id) FROM ' . $prefix . 'discussions WHERE start_user_id = ' . $prefix . 'users.id)'), 'comments_count' => DB::raw('(SELECT COUNT(id) FROM ' . $prefix . 'posts WHERE user_id = ' . $prefix . 'users.id and type = \'comment\')')]);
 }
Example #4
0
 public function registerPermissions()
 {
     $this->extend(new Permission('forum.view'), new Permission('forum.startDiscussion'), new Permission('discussion.rename'), new Permission('discussion.delete'), new Permission('discussion.reply'), new Permission('post.edit'), new Permission('post.delete'));
     Forum::grantPermission(function ($grant, $user, $permission) {
         return $user->hasPermission('forum.' . $permission);
     });
     Post::grantPermission(function ($grant, $user, $permission) {
         return $user->hasPermission('post' . $permission);
     });
     // Grant view access to a post only if the user can also view the
     // discussion which the post is in. Also, the if the post is hidden,
     // the user must have edit permissions too.
     Post::grantPermission('view', function ($grant) {
         $grant->whereCan('view', 'discussion');
     });
     Post::demandPermission('view', function ($demand) {
         $demand->whereNull('hide_user_id')->orWhereCan('edit');
     });
     // Allow a user to edit their own post, unless it has been hidden by
     // someone else.
     Post::grantPermission('edit', function ($grant, $user) {
         $grant->where('user_id', $user->id)->where(function ($query) use($user) {
             $query->whereNull('hide_user_id')->orWhere('hide_user_id', $user->id);
         });
         // @todo add limitations to time etc. according to a config setting
     });
     User::grantPermission(function ($grant, $user, $permission) {
         return $user->hasPermission('user.' . $permission);
     });
     // Grant view access to a user if the user can view the forum.
     User::grantPermission('view', function ($grant, $user) {
         $grant->whereCan('view', 'forum');
     });
     // Allow a user to edit their own account.
     User::grantPermission(['edit', 'delete'], function ($grant, $user) {
         $grant->where('id', $user->id);
     });
     Discussion::grantPermission(function ($grant, $user, $permission) {
         return $user->hasPermission('discussion.' . $permission);
     });
     // Grant view access to a discussion if the user can view the forum.
     Discussion::grantPermission('view', function ($grant, $user) {
         $grant->whereCan('view', 'forum');
     });
     // Allow a user to rename their own discussion.
     Discussion::grantPermission('rename', function ($grant, $user) {
         $grant->where('start_user_id', $user->id);
         // @todo add limitations to time etc. according to a config setting
     });
 }
 /**
  * Get the IDs of discussions which a user has read completely.
  *
  * @param  \Flarum\Core\Models\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');
 }