Skip to content

Commit

Permalink
Fix Last Posted Discussion, Improve DiscussionCount (#78)
Browse files Browse the repository at this point in the history
The calculation/caching of the last posted discsussion is currently not very good. This PR adds fixes for:

Ensuring that private and hidden discussions aren't returned
Hiding and restoring discussions (hidden discussions shouldn't be returned)
Editing tags on a discussion (previously the discussion wasn't removed from the old tags).
  • Loading branch information
askvortsov1 authored Jun 28, 2020
1 parent b85d1c5 commit 164d67b
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 29 deletions.
79 changes: 55 additions & 24 deletions src/Listener/UpdateTagMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@

namespace Flarum\Tags\Listener;

use Flarum\Discussion\Discussion;
use Flarum\Discussion\Event\Deleted;
use Flarum\Discussion\Event\Hidden;
use Flarum\Discussion\Event\Restored;
use Flarum\Discussion\Event\Started;
use Flarum\Post\Event\Deleted as PostDeleted;
use Flarum\Post\Event\Hidden;
use Flarum\Post\Event\Hidden as PostHidden;
use Flarum\Post\Event\Posted;
use Flarum\Post\Event\Restored;
use Flarum\Post\Event\Restored as PostRestored;
use Flarum\Tags\Event\DiscussionWasTagged;
use Flarum\Tags\Tag;
use Illuminate\Contracts\Events\Dispatcher;
Expand All @@ -29,11 +32,13 @@ public function subscribe(Dispatcher $events)
$events->listen(Started::class, [$this, 'whenDiscussionIsStarted']);
$events->listen(DiscussionWasTagged::class, [$this, 'whenDiscussionWasTagged']);
$events->listen(Deleted::class, [$this, 'whenDiscussionIsDeleted']);
$events->listen(Hidden::class, [$this, 'whenDiscussionIsHidden']);
$events->listen(Restored::class, [$this, 'whenDiscussionIsRestored']);

$events->listen(Posted::class, [$this, 'whenPostIsPosted']);
$events->listen(PostDeleted::class, [$this, 'whenPostIsDeleted']);
$events->listen(Hidden::class, [$this, 'whenPostIsHidden']);
$events->listen(Restored::class, [$this, 'whenPostIsRestored']);
$events->listen(PostHidden::class, [$this, 'whenPostIsHidden']);
$events->listen(PostRestored::class, [$this, 'whenPostIsRestored']);
}

/**
Expand All @@ -49,7 +54,7 @@ public function whenDiscussionIsStarted(Started $event)
*/
public function whenDiscussionWasTagged(DiscussionWasTagged $event)
{
$oldTags = Tag::whereIn('id', array_pluck($event->oldTags, 'id'));
$oldTags = Tag::whereIn('id', array_pluck($event->oldTags, 'id'))->get();

$this->updateTags($event->discussion, -1, $oldTags);
$this->updateTags($event->discussion, 1);
Expand All @@ -65,6 +70,22 @@ public function whenDiscussionIsDeleted(Deleted $event)
$event->discussion->tags()->detach();
}

/**
* @param Hidden $event
*/
public function whenDiscussionIsHidden(Hidden $event)
{
$this->updateTags($event->discussion, -1);
}

/**
* @param Restored $event
*/
public function whenDiscussionIsRestored(Restored $event)
{
$this->updateTags($event->discussion, 1);
}

/**
* @param Posted $event
*/
Expand All @@ -74,55 +95,65 @@ public function whenPostIsPosted(Posted $event)
}

/**
* @param Deleted $event
* @param PostDeleted $event
*/
public function whenPostIsDeleted(PostDeleted $event)
{
$this->updateTags($event->post->discussion);
}

/**
* @param Hidden $event
* @param PostHidden $event
*/
public function whenPostIsHidden(Hidden $event)
public function whenPostIsHidden(PostHidden $event)
{
$this->updateTags($event->post->discussion);
$this->updateTags($event->post->discussion, 0, null, $event->post);
}

/**
* @param Restored $event
* @param PostRestored $event
*/
public function whenPostIsRestored(Restored $event)
public function whenPostIsRestored(PostRestored $event)
{
$this->updateTags($event->post->discussion);
$this->updateTags($event->post->discussion, 0, null, $event->post);
}

/**
* @param \Flarum\Discussion\Discussion $discussion
* @param int $delta
* @param Tag[]|null $tags
* @param Post $post: This is only used when a post has been hidden
*/
protected function updateTags($discussion, $delta = 0, $tags = null)
protected function updateTags(Discussion $discussion, $delta = 0, $tags = null, $post = null)
{
if (! $discussion) {
return;
}

// We do not count private discussions in tags
if ($discussion->is_private) {
return;
}

if (! $tags) {
$tags = $discussion->tags;
}

// If we've just hidden or restored a post, the discussion's last posted at metadata might not have updated yet.
// Therefore, we must refresh the last post, even though that might be repeated in the future.
if ($post) {
$discussion->refreshLastPost();
}

foreach ($tags as $tag) {
$tag->discussion_count += $delta;
// We do not count private discussions or hidden discussions in tags
if (! $discussion->is_private) {
$tag->discussion_count += $delta;
}

if ($discussion->last_posted_at > $tag->last_posted_at) {
// If this is a new / restored discussion, it isn't private, it isn't null,
// and it's more recent than what we have now, set it as last posted discussion.
if ($delta >= 0 && ! $discussion->is_private && $discussion->hidden_at == null && ($discussion->last_posted_at >= $tag->last_posted_at)) {
$tag->setLastPostedDiscussion($discussion);
} elseif ($discussion->id == $tag->last_posted_discussion_id) {
// This is to persist refreshLastPost above. It is here instead of there so that
// if it's not necessary, we save a DB query.
if ($post) {
$discussion->save();
}
// This discussion is currently the last posted discussion, but since it didn't qualify for the above check,
// it should not be the last posted discussion. Therefore, we should refresh the last posted discussion..
$tag->refreshLastPostedDiscussion();
}

Expand Down
12 changes: 7 additions & 5 deletions src/Tag.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,20 @@ public function discussions()

public function refreshLastPostedDiscussion()
{
if ($lastPostedDiscussion = $this->discussions()->latest('last_posted_at')->first()) {
if ($lastPostedDiscussion = $this->discussions()->where('is_private', false)->whereNull('hidden_at')->latest('last_posted_at')->first()) {
$this->setLastPostedDiscussion($lastPostedDiscussion);
} else {
$this->setLastPostedDiscussion(null);
}

return $this;
}

public function setLastPostedDiscussion(Discussion $discussion)
public function setLastPostedDiscussion(Discussion $discussion = null)
{
$this->last_posted_at = $discussion->last_posted_at;
$this->last_posted_discussion_id = $discussion->id;
$this->last_posted_user_id = $discussion->last_posted_user_id;
$this->last_posted_at = optional($discussion)->last_posted_at;
$this->last_posted_discussion_id = optional($discussion)->id;
$this->last_posted_user_id = optional($discussion)->last_posted_user_id;

return $this;
}
Expand Down

0 comments on commit 164d67b

Please sign in to comment.