feat(episode-unpublish): remove episode comments upon unpublish

This commit is contained in:
Yassine Doghri 2022-07-21 16:21:26 +00:00
parent 8acdafd260
commit 78acd7f5c0
17 changed files with 124 additions and 40 deletions

View File

@ -219,11 +219,15 @@ Events::on('on_post_undo_reblog', function ($reblogPost): void {
Events::on('on_post_reply', function ($reply): void {
$post = $reply->reply_to_post;
model(EpisodeModel::class, false)->builder()
->where('id', $post->episode_id)
->increment('comments_count');
if ($post->in_reply_to_id === null) {
model(EpisodeModel::class, false)->builder()
->where('id', $post->episode_id)
->increment('comments_count');
}
if ($post->actor->is_podcast) {
cache()
->deleteMatching("podcast-{$post->actor->podcast->handle}*");
cache()
->deleteMatching("podcast#{$post->actor->podcast->id}*");
cache()
@ -240,11 +244,15 @@ Events::on('on_post_reply', function ($reply): void {
Events::on('on_reply_remove', function ($reply): void {
$post = $reply->reply_to_post;
model(EpisodeModel::class, false)->builder()
->where('id', $post->episode_id)
->decrement('comments_count');
if ($post->in_reply_to_id === null) {
model(EpisodeModel::class, false)->builder()
->where('id', $post->episode_id)
->decrement('comments_count');
}
if ($post->actor->is_podcast) {
cache()
->deleteMatching("podcast-{$post->actor->podcast->handle}*");
cache()
->deleteMatching("page_podcast#{$post->actor->podcast->id}*");
cache()

View File

@ -72,6 +72,7 @@ use RuntimeException;
* @property bool $is_published_on_hubs
* @property int $posts_count
* @property int $comments_count
* @property EpisodeComment[]|null $comments
* @property int $created_by
* @property int $updated_by
* @property string $publication_status;

View File

@ -14,9 +14,12 @@ use App\Entities\EpisodeComment;
use App\Libraries\CommentObject;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\BaseResult;
use CodeIgniter\I18n\Time;
use Michalsn\Uuid\UuidModel;
use Modules\Fediverse\Activities\CreateActivity;
use Modules\Fediverse\Activities\DeleteActivity;
use Modules\Fediverse\Models\ActivityModel;
use Modules\Fediverse\Objects\TombstoneObject;
class EpisodeCommentModel extends UuidModel
{
@ -70,10 +73,9 @@ class EpisodeCommentModel extends UuidModel
return $found;
}
public function addComment(EpisodeComment $comment, bool $registerActivity = false): string | false
public function addComment(EpisodeComment $comment, bool $registerActivity = true): string | false
{
$this->db->transStart();
// increment Episode's comments_count
if (! ($newCommentId = $this->insert($comment, true))) {
$this->db->transRollback();
@ -128,15 +130,67 @@ class EpisodeCommentModel extends UuidModel
$this->db->transComplete();
// delete podcast and episode pages cache
cache()
->deleteMatching('page_podcast#' . $comment->episode->podcast_id . '*');
cache()
->deleteMatching('page_episode#' . $comment->episode_id . '*');
$this->clearCache($comment);
return $newCommentId;
}
public function removeComment(EpisodeComment $comment, bool $registerActivity = true): BaseResult | bool
{
$this->db->transStart();
// remove all replies
foreach ($comment->replies as $reply) {
$this->removeComment($reply);
}
if ($registerActivity) {
$deleteActivity = new DeleteActivity();
$tombstoneObject = new TombstoneObject();
$tombstoneObject->set('id', $comment->uri);
$deleteActivity
->set('actor', $comment->actor->uri)
->set('object', $tombstoneObject);
$activityId = model(ActivityModel::class, false)
->newActivity(
'Delete',
$comment->actor_id,
null,
null,
$deleteActivity->toJSON(),
Time::now(),
'queued',
);
$deleteActivity->set('id', url_to('activity', esc($comment->actor->username), $activityId));
model(ActivityModel::class, false)
->update($activityId, [
'payload' => $deleteActivity->toJSON(),
]);
}
$result = model(self::class, false)
->delete($comment->id);
if ($comment->in_reply_to_id === null) {
model(EpisodeModel::class, false)->builder()
->where('id', $comment->episode_id)
->decrement('comments_count');
} else {
(new self())->builder()
->where('id', service('uuid')->fromString($comment->in_reply_to_id)->getBytes())
->decrement('replies_count');
}
$this->clearCache($comment);
$this->db->transComplete();
return $result;
}
/**
* Retrieves all published posts for a given episode ordered by publication date
*
@ -250,4 +304,18 @@ class EpisodeCommentModel extends UuidModel
return $data;
}
protected function clearCache(EpisodeComment $comment): void
{
cache()
->deleteMatching("comment#{$comment->id}*");
// delete podcast and episode pages cache
cache()
->deleteMatching("podcast-{$comment->episode->podcast->handle}*");
cache()
->deleteMatching('page_podcast#' . $comment->episode->podcast_id . '*');
cache()
->deleteMatching('page_episode#' . $comment->episode_id . '*');
}
}

View File

@ -337,33 +337,30 @@ class EpisodeModel extends Model
public function resetCommentsCount(): int | false
{
$episodeCommentsCount = $this->builder()
->select('episodes.id, COUNT(*) as `comments_count`')
->join('episode_comments', 'episodes.id = episode_comments.episode_id')
$episodeCommentsCount = (new EpisodeCommentModel())->builder()
->select('episode_id, COUNT(*) as `comments_count`')
->where('in_reply_to_id', null)
->groupBy('episodes.id')
->groupBy('episode_id')
->getCompiledSelect();
$episodePostsRepliesCount = $this->builder()
->select('episodes.id, COUNT(*) as `comments_count`')
->join(
config('Fediverse')
->tablesPrefix . 'posts',
'episodes.id = ' . config('Fediverse')->tablesPrefix . 'posts.episode_id'
)
->where('in_reply_to_id IS NOT', null)
->groupBy('episodes.id')
$postsTable = config('Fediverse')
->tablesPrefix . 'posts';
$episodePostsRepliesCount = (new PostModel())->builder()
->select($postsTable . '.episode_id as episode_id, COUNT(*) as `comments_count`')
->join($postsTable . ' as fp', $postsTable . '.id = fp.in_reply_to_id')
->where($postsTable . '.in_reply_to_id', null)
->groupBy($postsTable . '.episode_id')
->getCompiledSelect();
/** @var BaseResult $query */
$query = $this->db->query(
'SELECT `id`, SUM(`comments_count`) as `comments_count` FROM (' . $episodeCommentsCount . ' UNION ALL ' . $episodePostsRepliesCount . ') x GROUP BY `id`'
'SELECT `episode_id` as `id`, SUM(`comments_count`) as `comments_count` FROM (' . $episodeCommentsCount . ' UNION ALL ' . $episodePostsRepliesCount . ') x GROUP BY `episode_id`'
);
$countsPerEpisodeId = $query->getResultArray();
if ($countsPerEpisodeId !== []) {
return $this->updateBatch($countsPerEpisodeId, 'id');
return (new self())->updateBatch($countsPerEpisodeId, 'id');
}
return 0;

View File

@ -722,6 +722,16 @@ class EpisodeController extends BaseController
(new PostModel())->removePost($post);
}
$allCommentsLinkedToEpisode = (new EpisodeCommentModel())
->where([
'episode_id' => $this->episode->id,
'in_reply_to_id' => null,
])
->findAll();
foreach ($allCommentsLinkedToEpisode as $comment) {
(new EpisodeCommentModel())->removeComment($comment);
}
// set episode published_at to null to unpublish
$this->episode->published_at = null;

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'إلغاء النشر',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],

View File

@ -178,7 +178,7 @@ return [
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the posts associated with it and remove it from the podcast's RSS feed.",
"Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],