Add concept of "mergeable" activity posts

For example: when you rename a discussion, DiscussionRenamedPost is
created. If you rename it again immediately afterwards, then a new
DiscussionRenamedPost can be merged into the old one. This will either
result in the old one being updated with the new title, or it being
deleted all together if it was renamed back to the old title.
This commit is contained in:
Toby Zerner 2015-05-04 12:19:25 +09:30
parent 45ab262547
commit 56ef42f931
6 changed files with 100 additions and 23 deletions

View File

@ -27,7 +27,7 @@ class DiscussionRenamedNotifier
{
$post = $this->createPost($event);
$event->discussion->postWasAdded($post);
$event->discussion->addPost($post);
if ($event->discussion->start_user_id !== $event->user->id) {
$this->sendNotification($event, $post);
@ -36,16 +36,12 @@ class DiscussionRenamedNotifier
protected function createPost(DiscussionWasRenamed $event)
{
$post = DiscussionRenamedPost::reply(
return DiscussionRenamedPost::reply(
$event->discussion->id,
$event->user->id,
$event->oldTitle,
$event->discussion->title
);
$post->save();
return $post;
}
protected function sendNotification(DiscussionWasRenamed $event, DiscussionRenamedPost $post)

View File

@ -0,0 +1,27 @@
<?php namespace Flarum\Core\Models;
abstract class ActivityPost extends Post implements MergeableInterface
{
use MergeableTrait;
/**
* Unserialize the content attribute.
*
* @param string $value
* @return string
*/
public function getContentAttribute($value)
{
return json_decode($value);
}
/**
* Serialize the content attribute.
*
* @param string $value
*/
public function setContentAttribute($value)
{
$this->attributes['content'] = json_encode($value);
}
}

View File

@ -185,6 +185,24 @@ class Discussion extends Model
$this->removedPosts[] = $post->id;
}
public function addPost(Post $post)
{
if ($post instanceof MergeableInterface) {
$lastPost = $this->posts()->orderBy('time', 'desc')->first();
$post = $post->saveAfter($lastPost);
} else {
$post->save();
}
if ($post->exists) {
$this->postWasAdded($post);
} else {
$this->postWasRemoved($post);
}
return $post->exists;
}
/**
* Define the relationship with the discussion's posts.
*

View File

@ -1,7 +1,23 @@
<?php namespace Flarum\Core\Models;
class DiscussionRenamedPost extends Post
class DiscussionRenamedPost extends ActivityPost
{
/**
* Merge the post into another post of the same type.
*
* @param \Flarum\Core\Models\DiscussionRenamedPost $previous
* @return boolean true if the post was merged, false if it was deleted.
*/
protected function mergeInto(Model $previous)
{
if ($previous->content[0] == $this->content[1]) {
return false;
}
$previous->content = static::buildContent($previous->content[0], $this->content[1]);
return true;
}
/**
* Create a new instance in reply to a discussion.
*
@ -15,7 +31,7 @@ class DiscussionRenamedPost extends Post
{
$post = new static;
$post->content = [$oldTitle, $newTitle];
$post->content = static::buildContent($oldTitle, $newTitle);
$post->time = time();
$post->discussion_id = $discussionId;
$post->user_id = $userId;
@ -25,23 +41,14 @@ class DiscussionRenamedPost extends Post
}
/**
* Unserialize the content attribute.
* Build the content attribute.
*
* @param string $value
* @return string
* @param boolean $oldTitle The old title of the discussion.
* @param boolean $newTitle The new title of the discussion.
* @return array
*/
public function getContentAttribute($value)
public static function buildContent($oldTitle, $newTitle)
{
return json_decode($value);
}
/**
* Serialize the content attribute.
*
* @param string $value
*/
public function setContentAttribute($value)
{
$this->attributes['content'] = json_encode($value);
return [$oldTitle, $newTitle];
}
}

View File

@ -0,0 +1,6 @@
<?php namespace Flarum\Core\Models;
interface MergeableInterface
{
public function saveAfter(Model $previous);
}

View File

@ -0,0 +1,23 @@
<?php namespace Flarum\Core\Models;
trait MergeableTrait
{
public function saveAfter(Model $previous)
{
if ($previous instanceof static) {
if ($this->mergeInto($previous)) {
$previous->save();
} else {
$previous->delete();
}
return $previous;
}
$this->save();
return $this;
}
abstract protected function mergeInto(Model $previous);
}