mirror of
https://github.com/flarum/core.git
synced 2025-07-23 17:51:24 +02:00
Implement hard deletion and rename soft delete to hide
This commit is contained in:
@@ -21,8 +21,8 @@ export default Ember.Component.extend(FadeIn, HasItemLists, UseComposer, {
|
||||
tagName: 'article',
|
||||
classNames: ['post', 'post-comment'],
|
||||
classNameBindings: [
|
||||
'post.isHidden:deleted',
|
||||
'post.isEdited:edited',
|
||||
'post.isHidden:is-hidden',
|
||||
'post.isEdited:is-edited',
|
||||
'revealContent:reveal-content'
|
||||
],
|
||||
itemLists: ['controls', 'header', 'footer'],
|
||||
@@ -35,7 +35,7 @@ export default Ember.Component.extend(FadeIn, HasItemLists, UseComposer, {
|
||||
populateControls: function(items) {
|
||||
if (this.get('post.isHidden')) {
|
||||
this.addActionItem(items, 'restore', 'Restore', 'reply', 'post.canEdit');
|
||||
this.addActionItem(items, 'delete', 'Delete', 'times', 'post.canDelete');
|
||||
this.addActionItem(items, 'delete', 'Delete Forever', 'times', 'post.canDelete');
|
||||
} else {
|
||||
this.addActionItem(items, 'edit', 'Edit', 'pencil', 'post.canEdit');
|
||||
this.addActionItem(items, 'hide', 'Delete', 'times', 'post.canEdit');
|
||||
@@ -88,8 +88,8 @@ export default Ember.Component.extend(FadeIn, HasItemLists, UseComposer, {
|
||||
var post = this.get('post');
|
||||
post.setProperties({
|
||||
isHidden: true,
|
||||
deleteTime: new Date,
|
||||
deleteUser: this.get('session.user')
|
||||
hideTime: new Date,
|
||||
hideUser: this.get('session.user')
|
||||
});
|
||||
post.save();
|
||||
},
|
||||
@@ -98,10 +98,16 @@ export default Ember.Component.extend(FadeIn, HasItemLists, UseComposer, {
|
||||
var post = this.get('post');
|
||||
post.setProperties({
|
||||
isHidden: false,
|
||||
deleteTime: null,
|
||||
deleteUser: null
|
||||
hideTime: null,
|
||||
hideUser: null
|
||||
});
|
||||
post.save();
|
||||
},
|
||||
|
||||
delete: function() {
|
||||
var post = this.get('post');
|
||||
post.destroyRecord();
|
||||
this.sendAction('postRemoved', post);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -288,6 +288,10 @@ export default Ember.Component.extend({
|
||||
|
||||
loadRange: function(start, end, backwards) {
|
||||
this.get('stream').loadRange(start, end, backwards);
|
||||
},
|
||||
|
||||
postRemoved: function(post) {
|
||||
this.sendAction('postRemoved', post);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -98,6 +98,10 @@ export default Ember.Controller.extend(Ember.Evented, UseComposerMixin, {
|
||||
discussion.set('readNumber', endNumber);
|
||||
discussion.save();
|
||||
}
|
||||
},
|
||||
|
||||
postRemoved: function(post) {
|
||||
this.get('stream').removePost(post);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -168,6 +168,12 @@ export default Ember.ArrayProxy.extend(Ember.Evented, {
|
||||
this.get('content').pushObject(this.makeItem(index, index, post));
|
||||
},
|
||||
|
||||
removePost: function(post) {
|
||||
this.get('ids').removeObject(post.get('id'));
|
||||
var content = this.get('content');
|
||||
content.removeObject(content.findBy('content', post));
|
||||
},
|
||||
|
||||
makeItem: function(indexStart, indexEnd, post) {
|
||||
var item = Ember.Object.create({
|
||||
indexStart: indexStart,
|
||||
|
@@ -15,9 +15,9 @@ export default DS.Model.extend({
|
||||
editUser: DS.belongsTo('user'),
|
||||
isEdited: Ember.computed.notEmpty('editTime'),
|
||||
|
||||
hideTime: DS.attr('date'),
|
||||
hideUser: DS.belongsTo('user'),
|
||||
isHidden: DS.attr('boolean'),
|
||||
deleteTime: DS.attr('date'),
|
||||
deleteUser: DS.belongsTo('user'),
|
||||
|
||||
canEdit: DS.attr('boolean'),
|
||||
canDelete: DS.attr('boolean')
|
||||
|
16
ember/app/serializers/post.js
Normal file
16
ember/app/serializers/post.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import ApplicationSerializer from 'flarum/serializers/application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
number: {serialize: false},
|
||||
time: {serialize: false},
|
||||
type: {serialize: false},
|
||||
contentHtml: {serialize: false},
|
||||
editTime: {serialize: false},
|
||||
editUser: {serialize: false},
|
||||
hideTime: {serialize: false},
|
||||
hideUser: {serialize: false},
|
||||
canEdit: {serialize: false},
|
||||
canDelete: {serialize: false}
|
||||
}
|
||||
});
|
@@ -103,7 +103,6 @@
|
||||
float: right;
|
||||
margin: -2px 0 0 10px;
|
||||
visibility: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
&:hover .contextual-controls, & .contextual-controls.open {
|
||||
visibility: visible;
|
||||
@@ -159,7 +158,7 @@
|
||||
text-align: center;
|
||||
font-size: 22px;
|
||||
}
|
||||
.post.deleted {
|
||||
.post.is-hidden {
|
||||
& .post-user, & .post-header > ul, & .post-header > ul a:not(.btn) {
|
||||
color: @fl-body-muted-more-color;
|
||||
}
|
||||
@@ -173,6 +172,10 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
& .btn-more {
|
||||
background: #eee;
|
||||
color: @fl-body-muted-more-color;
|
||||
}
|
||||
}
|
||||
.post-meta {
|
||||
width: 400px;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{{#each item in stream}}
|
||||
{{#discussion/stream-item item=item stream=stream loadRange="loadRange"}}
|
||||
{{#if item.content}}
|
||||
{{component item.component content=item.content}}
|
||||
{{component item.component content=item.content postRemoved="postRemoved"}}
|
||||
{{/if}}
|
||||
{{/discussion/stream-item}}
|
||||
{{/each}}
|
||||
|
@@ -13,5 +13,6 @@
|
||||
viewName="streamContent"
|
||||
stream=stream
|
||||
class="discussion-posts posts"
|
||||
positionChanged="positionChanged"}}
|
||||
positionChanged="positionChanged"
|
||||
postRemoved="postRemoved"}}
|
||||
</div>
|
||||
|
@@ -12,7 +12,7 @@ class Show extends Base
|
||||
|
||||
/**
|
||||
* The post repository.
|
||||
*
|
||||
*
|
||||
* @var PostRepository
|
||||
*/
|
||||
protected $posts;
|
||||
@@ -39,7 +39,7 @@ class Show extends Base
|
||||
$discussion = Discussion::whereCanView()->findOrFail($this->param('id'));
|
||||
|
||||
if (in_array('posts', $include)) {
|
||||
$relations = ['user', 'user.groups', 'editUser', 'deleteUser'];
|
||||
$relations = ['user', 'user.groups', 'editUser', 'hideUser'];
|
||||
$discussion->posts = $this->getPostsForDiscussion($this->posts, $discussion->id, $relations);
|
||||
|
||||
$include = array_merge($include, array_map(function ($relation) {
|
||||
|
@@ -12,7 +12,7 @@ class Index extends Base
|
||||
|
||||
/**
|
||||
* The post repository.
|
||||
*
|
||||
*
|
||||
* @var PostRepository
|
||||
*/
|
||||
protected $posts;
|
||||
@@ -35,7 +35,7 @@ class Index extends Base
|
||||
protected function run()
|
||||
{
|
||||
$postIds = (array) $this->input('ids');
|
||||
$include = ['user', 'user.groups', 'editUser', 'deleteUser'];
|
||||
$include = ['user', 'user.groups', 'editUser', 'hideUser'];
|
||||
|
||||
if (count($postIds)) {
|
||||
$posts = $this->posts->findMany($postIds, $include);
|
||||
|
@@ -23,7 +23,7 @@ class Show extends Base
|
||||
}
|
||||
|
||||
$include = $this->included(['discussion', 'replyTo']);
|
||||
$relations = array_merge(['user', 'editUser', 'deleteUser'], $include);
|
||||
$relations = array_merge(['user', 'editUser', 'hideUser'], $include);
|
||||
$posts->load($relations);
|
||||
|
||||
// Finally, we can set up the post serializer and use it to create
|
||||
|
@@ -21,7 +21,7 @@ class PostSerializer extends PostBasicSerializer
|
||||
* Default relations to include.
|
||||
* @var array
|
||||
*/
|
||||
protected $include = ['user', 'editUser', 'deleteUser'];
|
||||
protected $include = ['user', 'editUser', 'hideUser'];
|
||||
|
||||
/**
|
||||
* Serialize attributes of a Post model for JSON output.
|
||||
@@ -51,9 +51,9 @@ class PostSerializer extends PostBasicSerializer
|
||||
$attributes['editTime'] = $post->edit_time->toRFC3339String();
|
||||
}
|
||||
|
||||
if ($post->delete_time) {
|
||||
if ($post->hide_time) {
|
||||
$attributes['isHidden'] = true;
|
||||
$attributes['deleteTime'] = $post->delete_time->toRFC3339String();
|
||||
$attributes['hideTime'] = $post->hide_time->toRFC3339String();
|
||||
}
|
||||
|
||||
$attributes += [
|
||||
@@ -66,7 +66,7 @@ class PostSerializer extends PostBasicSerializer
|
||||
|
||||
/**
|
||||
* Get a resource containing a post's user.
|
||||
*
|
||||
*
|
||||
* @param Post $post
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
@@ -78,7 +78,7 @@ class PostSerializer extends PostBasicSerializer
|
||||
|
||||
/**
|
||||
* Get a resource containing a post's discussion.
|
||||
*
|
||||
*
|
||||
* @param Post $post
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
@@ -90,7 +90,7 @@ class PostSerializer extends PostBasicSerializer
|
||||
|
||||
/**
|
||||
* Get a resource containing a post's edit user.
|
||||
*
|
||||
*
|
||||
* @param Post $post
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
@@ -101,14 +101,14 @@ class PostSerializer extends PostBasicSerializer
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource containing a post's delete user.
|
||||
*
|
||||
* Get a resource containing a post's hide user.
|
||||
*
|
||||
* @param Post $post
|
||||
* @param array $relations
|
||||
* @return Tobscure\JsonApi\Resource
|
||||
*/
|
||||
public function includeDeleteUser(Post $post, $relations = [])
|
||||
public function includeHideUser(Post $post, $relations = [])
|
||||
{
|
||||
return (new UserBasicSerializer($relations))->resource($post->deleteUser);
|
||||
return (new UserBasicSerializer($relations))->resource($post->hideUser);
|
||||
}
|
||||
}
|
||||
|
@@ -111,7 +111,7 @@ class Discussion extends Entity
|
||||
|
||||
public function comments()
|
||||
{
|
||||
return $this->posts()->where('type', 'comment')->whereNull('delete_time');
|
||||
return $this->posts()->where('type', 'comment')->whereNull('hide_time');
|
||||
}
|
||||
|
||||
public function startPost()
|
||||
|
@@ -54,24 +54,24 @@ class CommentPost extends Post
|
||||
|
||||
public function hide($user)
|
||||
{
|
||||
if ($this->delete_time) {
|
||||
if ($this->hide_time) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->delete_time = time();
|
||||
$this->delete_user_id = $user->id;
|
||||
$this->hide_time = time();
|
||||
$this->hide_user_id = $user->id;
|
||||
|
||||
$this->raise(new Events\PostWasHidden($this));
|
||||
}
|
||||
|
||||
public function restore($user)
|
||||
{
|
||||
if ($this->delete_time === null) {
|
||||
if ($this->hide_time === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->delete_time = null;
|
||||
$this->delete_user_id = null;
|
||||
$this->hide_time = null;
|
||||
$this->hide_user_id = null;
|
||||
|
||||
$this->raise(new Events\PostWasRestored($this));
|
||||
}
|
||||
|
@@ -23,8 +23,8 @@ class Post extends Entity
|
||||
'user_id' => 'integer',
|
||||
'edit_time' => 'date',
|
||||
'edit_user_id' => 'integer',
|
||||
'delete_time' => 'date',
|
||||
'delete_user_id' => 'integer',
|
||||
'hide_time' => 'date',
|
||||
'hide_user_id' => 'integer',
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
@@ -43,7 +43,7 @@ class Post extends Entity
|
||||
});
|
||||
|
||||
static::check('view', function ($check, $user) {
|
||||
$check->whereNull('delete_user_id')
|
||||
$check->whereNull('hide_user_id')
|
||||
->orWhereCan('edit');
|
||||
});
|
||||
|
||||
@@ -55,8 +55,8 @@ class Post extends Entity
|
||||
});
|
||||
|
||||
static::check('editOwn', function ($check, $user) {
|
||||
$check->whereNull('delete_user_id')
|
||||
->orWhere('delete_user_id', $user->id);
|
||||
$check->whereNull('hide_user_id')
|
||||
->orWhere('hide_user_id', $user->id);
|
||||
});
|
||||
|
||||
static::deleted(function ($post) {
|
||||
@@ -79,14 +79,14 @@ class Post extends Entity
|
||||
return $this->belongsTo('Flarum\Core\Users\User', 'edit_user_id');
|
||||
}
|
||||
|
||||
public function deleteUser()
|
||||
public function hideUser()
|
||||
{
|
||||
return $this->belongsTo('Flarum\Core\Users\User', 'delete_user_id');
|
||||
return $this->belongsTo('Flarum\Core\Users\User', 'hide_user_id');
|
||||
}
|
||||
|
||||
public function getDates()
|
||||
{
|
||||
return ['time', 'edit_time', 'delete_time'];
|
||||
return ['time', 'edit_time', 'hide_time'];
|
||||
}
|
||||
|
||||
// Terminates the query and returns an array of matching IDs.
|
||||
@@ -122,7 +122,7 @@ class Post extends Entity
|
||||
return $instance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return parent::newFromBuilder($attributes);
|
||||
}
|
||||
}
|
||||
|
@@ -67,9 +67,9 @@ class DiscussionTableSeeder extends Seeder
|
||||
]);
|
||||
} else {
|
||||
$edited = rand(1, 20) == 1;
|
||||
$deleted = rand(1, 100) == 1;
|
||||
$hidden = rand(1, 100) == 1;
|
||||
|
||||
if ($deleted) {
|
||||
if ($hidden) {
|
||||
$discussion->comments_count--;
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ class DiscussionTableSeeder extends Seeder
|
||||
'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,
|
||||
'delete_time' => $deleted ? $startTime = date_add($startTime, date_interval_create_from_date_string('1 second')) : null,
|
||||
'delete_user_id' => $deleted ? 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;
|
||||
|
@@ -26,8 +26,8 @@ class CreatePostsTable extends Migration {
|
||||
|
||||
$table->dateTime('edit_time')->nullable();
|
||||
$table->integer('edit_user_id')->unsigned()->nullable();
|
||||
$table->dateTime('delete_time')->nullable();
|
||||
$table->integer('delete_user_id')->unsigned()->nullable();
|
||||
$table->dateTime('hide_time')->nullable();
|
||||
$table->integer('hide_user_id')->unsigned()->nullable();
|
||||
});
|
||||
|
||||
// add fulltext index to content (and title?)
|
||||
|
Reference in New Issue
Block a user