diff --git a/framework/core/ember/app/adapters/application.js b/framework/core/ember/app/adapters/application.js index 8487c2565..351aac8d8 100644 --- a/framework/core/ember/app/adapters/application.js +++ b/framework/core/ember/app/adapters/application.js @@ -7,6 +7,13 @@ import AlertMessage from 'flarum/components/ui/alert-message'; export default JsonApiAdapter.extend({ host: config.apiURL, + pathForType: function(type) { + if (type == 'activity') { + return type; + } + return this._super(type); + }, + ajaxError: function(jqXHR) { var errors = this._super(jqXHR); diff --git a/framework/core/ember/app/components/user/activity-item.js b/framework/core/ember/app/components/user/activity-item.js new file mode 100644 index 000000000..01428fd58 --- /dev/null +++ b/framework/core/ember/app/components/user/activity-item.js @@ -0,0 +1,12 @@ +import Ember from 'ember'; + +import FadeIn from 'flarum/mixins/fade-in'; + +export default Ember.Component.extend(FadeIn, { + layoutName: 'components/user/activity-item', + tagName: 'li', + + componentName: Ember.computed('activity.type', function() { + return 'user/activity-'+this.get('activity.type'); + }) +}); diff --git a/framework/core/ember/app/components/user/activity-post.js b/framework/core/ember/app/components/user/activity-post.js new file mode 100644 index 000000000..bbd26d1e4 --- /dev/null +++ b/framework/core/ember/app/components/user/activity-post.js @@ -0,0 +1,9 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + layoutName: 'components/user/activity-post', + + isFirstPost: Ember.computed('activity.post.number', function() { + return this.get('activity.post.number') === 1; + }) +}); diff --git a/framework/core/ember/app/controllers/user/activity.js b/framework/core/ember/app/controllers/user/activity.js new file mode 100644 index 000000000..6efe75ad0 --- /dev/null +++ b/framework/core/ember/app/controllers/user/activity.js @@ -0,0 +1,71 @@ +import Ember from 'ember'; + +export default Ember.Controller.extend({ + needs: ['user'], + + queryParams: ['filter'], + filter: '', + + resultsLoading: false, + + moreResults: true, + + loadCount: 10, + + getResults: function(start) { + var type; + switch (this.get('filter')) { + case 'discussions': + type = 'discussion'; + break; + + case 'posts': + type = 'post'; + break; + } + var controller = this; + return this.store.find('activity', { + users: this.get('controllers.user.model.id'), + type: type, + start: start, + count: this.get('loadCount') + }).then(function(results) { + controller.set('moreResults', results.get('length') >= controller.get('loadCount')); + return results; + }); + }, + + paramsDidChange: Ember.observer('filter', function() { + if (this.get('model') && !this.get('resultsLoading')) { + Ember.run.once(this, this.loadResults); + } + }), + + loadResults: function() { + this.send('loadResults'); + }, + + actions: { + loadResults: function() { + var controller = this; + controller.get('model').set('content', []); + controller.set('resultsLoading', true); + controller.getResults().then(function(results) { + controller + .set('resultsLoading', false) + .set('meta', results.get('meta')) + .set('model.content', results); + }); + }, + + loadMore: function() { + var controller = this; + this.set('resultsLoading', true); + this.getResults(this.get('model.length')).then(function(results) { + controller.get('model.content').addObjects(results); + controller.set('meta', results.get('meta')); + controller.set('resultsLoading', false); + }); + }, + } +}); diff --git a/framework/core/ember/app/models/activity.js b/framework/core/ember/app/models/activity.js new file mode 100644 index 000000000..bc6c9fc1b --- /dev/null +++ b/framework/core/ember/app/models/activity.js @@ -0,0 +1,11 @@ +import DS from 'ember-data'; + +export default DS.Model.extend({ + type: DS.attr('string'), + content: DS.attr('string'), + time: DS.attr('date'), + + user: DS.belongsTo('user'), + sender: DS.belongsTo('user'), + post: DS.belongsTo('post') +}); diff --git a/framework/core/ember/app/router.js b/framework/core/ember/app/router.js index 2f8398d42..89bd4f337 100644 --- a/framework/core/ember/app/router.js +++ b/framework/core/ember/app/router.js @@ -14,8 +14,6 @@ Router.map(function() { this.resource('user', {path: '/u/:username'}, function() { this.route('activity', {path: '/'}); - this.route('discussions'); - this.route('posts'); this.route('edit'); }); diff --git a/framework/core/ember/app/routes/user/activity.js b/framework/core/ember/app/routes/user/activity.js new file mode 100644 index 000000000..75e94045a --- /dev/null +++ b/framework/core/ember/app/routes/user/activity.js @@ -0,0 +1,12 @@ +import Ember from 'ember'; + +export default Ember.Route.extend({ + model: function() { + return Ember.RSVP.resolve(Ember.ArrayProxy.create()); + }, + + setupController: function(controller, model) { + controller.set('model', model); + controller.send('loadResults'); + } +}); diff --git a/framework/core/ember/app/styles/flarum/user.less b/framework/core/ember/app/styles/flarum/user.less index fa687b444..c001fd6f5 100644 --- a/framework/core/ember/app/styles/flarum/user.less +++ b/framework/core/ember/app/styles/flarum/user.less @@ -95,3 +95,76 @@ } } } + +.user-content .loading-indicator { + height: 46px; +} +.user-activity { + border-left: 3px solid @fl-body-secondary-color; + list-style: none; + margin: 0 0 0 16px; + padding: 0; + + & > li { + margin-bottom: 30px; + padding-left: 32px; + } + & .activity-icon { + .avatar-size(32px); + float: left; + margin-left: -49px; + .box-shadow(0 0 0 3px #fff); + margin-top: -5px; + } +} +.activity-info { + color: @fl-body-muted-color; + margin-bottom: 10px; + + & strong { + margin-right: 5px; + } +} +.activity-content { + display: block; + padding: 20px; + background: @fl-body-secondary-color; + border-radius: @border-radius-base; + color: @fl-body-muted-color; + + &, &:hover { + text-decoration: none; + } + & .discussion-summary { + margin: -20px 0; + padding-left: 0; + + & .author { + display: none; + } + } +} +.activity-post { + overflow: hidden; + + & .title { + margin: 0 0 10px; + font-size: 14px; + font-weight: bold; + + &, & a { + color: @fl-body-heading-color; + } + } + &:hover .title { + text-decoration: underline; + } + & .body { + color: @fl-body-muted-color; + line-height: 1.7em; + + & :last-child { + margin-bottom: 0; + } + } +} diff --git a/framework/core/ember/app/templates/components/user/activity-item.hbs b/framework/core/ember/app/templates/components/user/activity-item.hbs new file mode 100644 index 000000000..2311dacf6 --- /dev/null +++ b/framework/core/ember/app/templates/components/user/activity-item.hbs @@ -0,0 +1 @@ +{{component componentName activity=activity}} diff --git a/framework/core/ember/app/templates/components/user/activity-join.hbs b/framework/core/ember/app/templates/components/user/activity-join.hbs new file mode 100644 index 000000000..3ffafbfb8 --- /dev/null +++ b/framework/core/ember/app/templates/components/user/activity-join.hbs @@ -0,0 +1,6 @@ +{{user-avatar activity.user class="activity-icon"}} + +
+ Joined the forum + {{human-time activity.time}} +
diff --git a/framework/core/ember/app/templates/components/user/activity-post.hbs b/framework/core/ember/app/templates/components/user/activity-post.hbs new file mode 100644 index 000000000..f58019629 --- /dev/null +++ b/framework/core/ember/app/templates/components/user/activity-post.hbs @@ -0,0 +1,21 @@ +{{user-avatar activity.post.user class="activity-icon"}} + +
+ {{if isFirstPost "Started a discussion" "Posted a reply"}} + {{human-time activity.time}} +
+ +{{#if isFirstPost}} +
+ {{index/discussion-listing discussion=activity.post.discussion}} +
+{{else}} + {{#link-to "discussion" activity.post.discussion (query-params start=activity.post.number) class="activity-content activity-post"}} +

+ {{activity.post.discussion.title}} +

+
+ {{{activity.post.contentHtml}}} +
+ {{/link-to}} +{{/if}} diff --git a/framework/core/ember/app/templates/user.hbs b/framework/core/ember/app/templates/user.hbs index fdada9a5a..dea7c6a91 100644 --- a/framework/core/ember/app/templates/user.hbs +++ b/framework/core/ember/app/templates/user.hbs @@ -5,5 +5,7 @@ {{ui/item-list items=view.sidebar}} - {{outlet}} +
+ {{outlet}} +
diff --git a/framework/core/ember/app/templates/user/activity.hbs b/framework/core/ember/app/templates/user/activity.hbs new file mode 100644 index 000000000..c09debb2f --- /dev/null +++ b/framework/core/ember/app/templates/user/activity.hbs @@ -0,0 +1,13 @@ + + +{{#if resultsLoading}} + {{ui/loading-indicator size="small"}} +{{else if moreResults}} +
+ {{ui/action-button class="control-loadMore btn btn-default" action="loadMore" label="Load More"}} +
+{{/if}} diff --git a/framework/core/ember/app/views/user.js b/framework/core/ember/app/views/user.js index 77b7b9980..10036b422 100644 --- a/framework/core/ember/app/views/user.js +++ b/framework/core/ember/app/views/user.js @@ -9,6 +9,22 @@ var precompileTemplate = Ember.Handlebars.compile; export default Ember.View.extend(HasItemLists, { itemLists: ['sidebar'], + didInsertElement: function() { + // Affix the sidebar so that when the user scrolls down it will stick + // to the top of their viewport. + var $sidebar = this.$('.user-nav'); + $sidebar.find('> ul').affix({ + offset: { + top: function () { + return $sidebar.offset().top - $('#header').outerHeight(true) - parseInt($sidebar.css('margin-top')); + }, + bottom: function () { + return (this.bottom = $('#footer').outerHeight(true)); + } + } + }); + }, + populateSidebar: function(items) { var nav = this.populateItemList('nav'); items.pushObjectWithTag(DropdownSelect.extend({items: nav, listItemClass: 'title-control'}), 'nav'); @@ -18,7 +34,7 @@ export default Ember.View.extend(HasItemLists, { items.pushObjectWithTag(NavItem.extend({ label: 'Activity', icon: 'user', - layout: precompileTemplate('{{#link-to "user.activity"}}{{fa-icon icon}} {{label}}{{/link-to}}') + layout: precompileTemplate('{{#link-to "user.activity" (query-params filter="")}}{{fa-icon icon}} {{label}}{{/link-to}}') }), 'activity'); items.pushObjectWithTag(NavItem.extend({ @@ -26,7 +42,7 @@ export default Ember.View.extend(HasItemLists, { icon: 'reorder', badge: Ember.computed.alias('user.discussionsCount'), user: this.get('controller.model'), - layout: precompileTemplate('{{#link-to "user.discussions"}}{{fa-icon icon}} {{label}} {{badge}}{{/link-to}}') + layout: precompileTemplate('{{#link-to "user.activity" (query-params filter="discussions")}}{{fa-icon icon}} {{label}} {{badge}}{{/link-to}}') }), 'discussions'); items.pushObjectWithTag(NavItem.extend({ @@ -34,7 +50,7 @@ export default Ember.View.extend(HasItemLists, { icon: 'comment-o', badge: Ember.computed.alias('user.commentsCount'), user: this.get('controller.model'), - layout: precompileTemplate('{{#link-to "user.posts"}}{{fa-icon icon}} {{label}} {{badge}}{{/link-to}}') + layout: precompileTemplate('{{#link-to "user.activity" (query-params filter="posts")}}{{fa-icon icon}} {{label}} {{badge}}{{/link-to}}') }), 'posts'); } }); diff --git a/framework/core/migrations/2015_02_24_000000_create_activity_table.php b/framework/core/migrations/2015_02_24_000000_create_activity_table.php index 43169a606..401847afa 100644 --- a/framework/core/migrations/2015_02_24_000000_create_activity_table.php +++ b/framework/core/migrations/2015_02_24_000000_create_activity_table.php @@ -16,12 +16,10 @@ class CreateActivityTable extends Migration { { $table->increments('id'); $table->integer('user_id')->unsigned(); - $table->integer('from_user_id')->unsigned()->nullable(); - $table->string('subject'); - $table->integer('subject_id')->unsigned()->nullable(); + $table->integer('sender_id')->unsigned()->nullable(); + $table->string('type'); $table->binary('data')->nullable(); $table->dateTime('time'); - $table->boolean('is_read')->default(0); }); } diff --git a/framework/core/src/Api/Actions/Activity/IndexAction.php b/framework/core/src/Api/Actions/Activity/IndexAction.php new file mode 100644 index 000000000..7f658a7d0 --- /dev/null +++ b/framework/core/src/Api/Actions/Activity/IndexAction.php @@ -0,0 +1,47 @@ +actor = $actor; + $this->users = $users; + $this->activity = $activity; + } + + /** + * Show a user's activity feed. + * + * @return \Illuminate\Http\Response + */ + protected function run(ApiParams $params) + { + $start = $params->start(); + $count = $params->count(20, 50); + $type = $params->get('type'); + $id = $params->get('users'); + + $user = $this->users->findOrFail($id, $this->actor->getUser()); + + $activity = $this->activity->findByUser($user->id, $this->actor->getUser(), $count, $start, $type); + + // Finally, we can set up the activity serializer and use it to create + // a collection of activity results. + $serializer = new ActivitySerializer(['sender', 'post', 'post.discussion', 'post.user', 'post.discussion.startUser', 'post.discussion.lastUser'], ['user']); + $document = $this->document()->setPrimaryElement($serializer->collection($activity)); + + return $this->respondWithDocument($document); + } +} diff --git a/framework/core/src/Api/Actions/Discussions/ShowAction.php b/framework/core/src/Api/Actions/Discussions/ShowAction.php index 635fab3c2..e89aca139 100644 --- a/framework/core/src/Api/Actions/Discussions/ShowAction.php +++ b/framework/core/src/Api/Actions/Discussions/ShowAction.php @@ -5,12 +5,12 @@ use Flarum\Core\Repositories\DiscussionRepositoryInterface as DiscussionReposito use Flarum\Core\Repositories\PostRepositoryInterface as PostRepository; use Flarum\Api\Actions\BaseAction; use Flarum\Api\Actions\ApiParams; -use Flarum\Api\Actions\Posts\GetsPostsForDiscussion; +use Flarum\Api\Actions\Posts\GetsPosts; use Flarum\Api\Serializers\DiscussionSerializer; class ShowAction extends BaseAction { - use GetsPostsForDiscussion; + use GetsPosts; /** * The discussion repository. @@ -51,7 +51,7 @@ class ShowAction extends BaseAction if (in_array('posts', $include)) { $relations = ['user', 'user.groups', 'editUser', 'hideUser']; - $discussion->posts = $this->getPostsForDiscussion($params, $discussion->id)->load($relations); + $discussion->posts = $this->getPosts($params, ['discussion_id' => $discussion->id])->load($relations); $include = array_merge($include, array_map(function ($relation) { return 'posts.'.$relation; diff --git a/framework/core/src/Api/Actions/Posts/GetsPostsForDiscussion.php b/framework/core/src/Api/Actions/Posts/GetsPosts.php similarity index 60% rename from framework/core/src/Api/Actions/Posts/GetsPostsForDiscussion.php rename to framework/core/src/Api/Actions/Posts/GetsPosts.php index f4a096b70..89febc4b3 100644 --- a/framework/core/src/Api/Actions/Posts/GetsPostsForDiscussion.php +++ b/framework/core/src/Api/Actions/Posts/GetsPosts.php @@ -3,23 +3,23 @@ use Flarum\Core\Models\User; use Flarum\Api\Actions\ApiParams; -trait GetsPostsForDiscussion +trait GetsPosts { - protected function getPostsForDiscussion(ApiParams $params, $discussionId) + protected function getPosts(ApiParams $params, $where) { $sort = $params->sort(['time']); $count = $params->count(20, 50); $user = $this->actor->getUser(); - if (($near = $params->get('near')) > 1) { - $start = $this->posts->getIndexForNumber($discussionId, $near, $user); + if (isset($where['discussion_id']) && ($near = $params->get('near')) > 1) { + $start = $this->posts->getIndexForNumber($where['discussion_id'], $near, $user); $start = max(0, $start - $count / 2); } else { $start = 0; } - return $this->posts->findByDiscussion( - $discussionId, + return $this->posts->findWhere( + $where, $user, $sort['field'], $sort['order'] ?: 'asc', diff --git a/framework/core/src/Api/Actions/Posts/IndexAction.php b/framework/core/src/Api/Actions/Posts/IndexAction.php index 11f8685ba..45e465e23 100644 --- a/framework/core/src/Api/Actions/Posts/IndexAction.php +++ b/framework/core/src/Api/Actions/Posts/IndexAction.php @@ -9,7 +9,7 @@ use Flarum\Api\Serializers\PostSerializer; class IndexAction extends BaseAction { - use GetsPostsForDiscussion; + use GetsPosts; /** * The post repository. @@ -37,14 +37,19 @@ class IndexAction extends BaseAction protected function run(ApiParams $params) { $postIds = (array) $params->get('ids'); - $include = ['user', 'user.groups', 'editUser', 'hideUser']; + $include = ['user', 'user.groups', 'editUser', 'hideUser', 'discussion']; $user = $this->actor->getUser(); if (count($postIds)) { $posts = $this->posts->findByIds($postIds, $user); } else { - $discussionId = $params->get('discussions'); - $posts = $this->getPostsForDiscussion($params, $discussionId, $user); + if ($discussionId = $params->get('discussions')) { + $where['discussion_id'] = $discussionId; + } + if ($userId = $params->get('users')) { + $where['user_id'] = $userId; + } + $posts = $this->getPosts($params, $where, $user); } if (! count($posts)) { diff --git a/framework/core/src/Api/Serializers/ActivitySerializer.php b/framework/core/src/Api/Serializers/ActivitySerializer.php index 65c1369f1..271e2153b 100644 --- a/framework/core/src/Api/Serializers/ActivitySerializer.php +++ b/framework/core/src/Api/Serializers/ActivitySerializer.php @@ -1,19 +1,65 @@ (int) $activity->id - ]; +class ActivitySerializer extends BaseSerializer +{ + /** + * The resource type. + * @var string + */ + protected $type = 'activity'; - Event::fire('flarum.api.serialize.activity', [&$serialized]); + /** + * Serialize attributes of an Activity model for JSON output. + * + * @param Activity $activity The Activity model to serialize. + * @return array + */ + protected function attributes(Activity $activity) + { + $attributes = [ + 'id' => ((int) $activity->id) ?: str_random(5), + 'type' => $activity->type, + 'content' => json_encode($activity->data), + 'time' => $activity->time->toRFC3339String() + ]; - return $serialized; - } + return $this->attributesEvent($activity, $attributes); + } + /** + * Get a resource containing an activity's sender. + * + * @param Activity $activity + * @return Tobscure\JsonApi\Resource + */ + public function linkUser(Activity $activity) + { + return (new UserBasicSerializer)->resource($activity->user_id); + } + + /** + * Get a resource containing an activity's sender. + * + * @param Activity $activity + * @param array $relations + * @return Tobscure\JsonApi\Resource + */ + public function includeSender(Activity $activity, $relations) + { + return (new UserBasicSerializer($relations))->resource($activity->sender); + } + + /** + * Get a resource containing an activity's sender. + * + * @param Activity $activity + * @param array $relations + * @return Tobscure\JsonApi\Resource + */ + public function includePost(Activity $activity, $relations) + { + return (new PostSerializer($relations))->resource($activity->post); + } } diff --git a/framework/core/src/Api/Serializers/PostSerializer.php b/framework/core/src/Api/Serializers/PostSerializer.php index d903a3726..ab84ecdb7 100644 --- a/framework/core/src/Api/Serializers/PostSerializer.php +++ b/framework/core/src/Api/Serializers/PostSerializer.php @@ -79,7 +79,7 @@ class PostSerializer extends PostBasicSerializer */ public function includeDiscussion(Post $post, $relations = []) { - return (new DiscussionBasicSerializer($relations))->resource($post->discussion); + return (new DiscussionSerializer($relations))->resource($post->discussion); } /** diff --git a/framework/core/src/Core/CoreServiceProvider.php b/framework/core/src/Core/CoreServiceProvider.php index 8d507b67f..fb298a0b9 100644 --- a/framework/core/src/Core/CoreServiceProvider.php +++ b/framework/core/src/Core/CoreServiceProvider.php @@ -73,6 +73,14 @@ class CoreServiceProvider extends ServiceProvider 'Flarum\Core\Repositories\UserRepositoryInterface', 'Flarum\Core\Repositories\EloquentUserRepository' ); + $this->app->bind( + 'Flarum\Core\Repositories\ActivityRepositoryInterface', + 'Flarum\Core\Repositories\EloquentActivityRepository' + ); + $this->app->bind( + 'Flarum\Core\Repositories\NotificationRepositoryInterface', + 'Flarum\Core\Repositories\EloquentNotificationRepository' + ); } public function registerGambits() diff --git a/framework/core/src/Core/Models/Activity.php b/framework/core/src/Core/Models/Activity.php index d053c81d5..e75860b71 100644 --- a/framework/core/src/Core/Models/Activity.php +++ b/framework/core/src/Core/Models/Activity.php @@ -1,36 +1,69 @@ -attributes['data'] = json_encode($value); + } - public function fromUser() - { - return $this->belongsTo('Flarum\Core\Models\User', 'from_user_id'); - } + /** + * Define the relationship with the activity's recipient. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function user() + { + return $this->belongsTo('Flarum\Core\Models\User', 'user_id'); + } - public function permission($permission) - { - return User::current()->can($permission, 'activity', $this); - } - - public function editable() - { - return $this->permission('edit'); - } - - public function deletable() - { - return $this->permission('delete'); - } + /** + * Define the relationship with the activity's sender. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function sender() + { + return $this->belongsTo('Flarum\Core\Models\User', 'sender_id'); + } + /** + * Define the relationship with the activity's sender. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function post() + { + return $this->belongsTo('Flarum\Core\Models\Post', 'post_id'); + } } diff --git a/framework/core/src/Core/Repositories/ActivityRepositoryInterface.php b/framework/core/src/Core/Repositories/ActivityRepositoryInterface.php new file mode 100644 index 000000000..7687732e4 --- /dev/null +++ b/framework/core/src/Core/Repositories/ActivityRepositoryInterface.php @@ -0,0 +1,8 @@ +select('id', 'user_id', 'sender_id', 'type', 'data', 'time', \DB::raw('NULL as post_id'))->where('user_id', $userId); + + if ($type) { + $query->where('type', $type); + } + + $posts = Post::whereCan($viewer, 'view')->with('post', 'post.discussion', 'post.user', 'post.discussion.startUser', 'post.discussion.lastUser')->select(\DB::raw("CONCAT('post', id)"), 'user_id', $null, \DB::raw("'post'"), $null, 'time', 'id')->where('user_id', $userId); + + if ($type === 'post') { + $posts->where('number', '>', 1); + } elseif ($type === 'discussion') { + $posts->where('number', 1); + } + + if (!$type) { + $join = User::select(\DB::raw("CONCAT('join', id)"), 'id', 'id', \DB::raw("'join'"), $null, 'join_time', $null)->where('id', $userId); + $query->union($join->getQuery()); + } + + return $query->union($posts->getQuery()) + ->orderBy('time', 'desc') + ->skip($start) + ->take($count) + ->get(); + } +} diff --git a/framework/core/src/Core/Repositories/EloquentPostRepository.php b/framework/core/src/Core/Repositories/EloquentPostRepository.php index 5366e2d3a..493c04796 100644 --- a/framework/core/src/Core/Repositories/EloquentPostRepository.php +++ b/framework/core/src/Core/Repositories/EloquentPostRepository.php @@ -24,10 +24,10 @@ class EloquentPostRepository implements PostRepositoryInterface } /** - * Find posts in a discussion, optionally making sure they are visible to - * a certain user, and/or using other criteria. + * Find posts that match certain conditions, optionally making sure they + * are visible to a certain user, and/or using other criteria. * - * @param integer $discussionId + * @param array $where * @param \Flarum\Core\Models\User|null $user * @param string $sort * @param string $order @@ -35,9 +35,9 @@ class EloquentPostRepository implements PostRepositoryInterface * @param integer $start * @return \Illuminate\Database\Eloquent\Collection */ - public function findByDiscussion($discussionId, User $user = null, $sort = 'time', $order = 'asc', $count = null, $start = 0) + public function findWhere($where = [], User $user = null, $sort = 'time', $order = 'asc', $count = null, $start = 0) { - $query = Post::where('discussion_id', $discussionId) + $query = Post::where($where) ->orderBy($sort, $order) ->skip($start) ->take($count); diff --git a/framework/core/src/Core/Repositories/PostRepositoryInterface.php b/framework/core/src/Core/Repositories/PostRepositoryInterface.php index 8796e82ec..c37b68a49 100644 --- a/framework/core/src/Core/Repositories/PostRepositoryInterface.php +++ b/framework/core/src/Core/Repositories/PostRepositoryInterface.php @@ -17,10 +17,10 @@ interface PostRepositoryInterface public function findOrFail($id, User $user = null); /** - * Find posts in a discussion, optionally making sure they are visible to - * a certain user, and/or using other criteria. + * Find posts that match certain conditions, optionally making sure they + * are visible to a certain user, and/or using other criteria. * - * @param integer $discussionId + * @param array $where * @param \Flarum\Core\Models\User|null $user * @param string $sort * @param string $order @@ -28,7 +28,7 @@ interface PostRepositoryInterface * @param integer $start * @return \Illuminate\Database\Eloquent\Collection */ - public function findByDiscussion($discussionId, User $user = null, $sort = 'time', $order = 'asc', $count = null, $start = 0); + public function findWhere($where = [], User $user = null, $sort = 'time', $order = 'asc', $count = null, $start = 0); /** * Find posts by their IDs, optionally making sure they are visible to a