diff --git a/app/Config/Routes.php b/app/Config/Routes.php index e59d3389..27c5ab80 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -426,6 +426,14 @@ $routes->group( 'filter' => 'permission:podcast-manage_publications', ] ); + $routes->post( + '(:uuid)/reply', + 'EpisodeController::attemptCommentReply/$1/$2/$3', + [ + 'as' => 'comment-attempt-reply', + 'filter' => 'permission:podcast-manage_publications', + ] + ); $routes->post( 'delete', 'EpisodeController::attemptCommentDelete/$1/$2', diff --git a/app/Controllers/Admin/EpisodeController.php b/app/Controllers/Admin/EpisodeController.php index 665c8007..fce864bd 100644 --- a/app/Controllers/Admin/EpisodeController.php +++ b/app/Controllers/Admin/EpisodeController.php @@ -821,4 +821,45 @@ class EpisodeController extends BaseController // Comment has been successfully created return redirect()->back(); } + + public function attemptCommentReply(string $commentId): RedirectResponse + { + // var_dump($commentId); + // die(); + + $rules = [ + 'message' => 'required|max_length[500]', + ]; + + if (! $this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $this->validator->getErrors()); + } + + $message = $this->request->getPost('message'); + + $newReply = new EpisodeComment([ + 'actor_id' => interact_as_actor_id(), + 'episode_id' => $this->episode->id, + 'message' => $message, + 'in_reply_to_id' => $commentId, + 'created_at' => new Time('now'), + 'created_by' => user_id(), + ]); + + $commentModel = new EpisodeCommentModel(); + if ( + ! $commentModel->addComment($newReply, true) + ) { + return redirect() + ->back() + ->withInput() + ->with('errors', $commentModel->errors()); + } + + // Reply has been successfully created + return redirect()->back(); + } } diff --git a/app/Controllers/EpisodeCommentController.php b/app/Controllers/EpisodeCommentController.php index 4f503d39..12ccf9d6 100644 --- a/app/Controllers/EpisodeCommentController.php +++ b/app/Controllers/EpisodeCommentController.php @@ -170,4 +170,12 @@ class EpisodeCommentController extends BaseController return redirect()->back(); } + + public function attemptReply(): RedirectResponse + { + model('LikeModel') + ->toggleLike(interact_as_actor(), $this->comment); + + return redirect()->back(); + } } diff --git a/app/Entities/EpisodeComment.php b/app/Entities/EpisodeComment.php index db2622c1..a6fa1420 100644 --- a/app/Entities/EpisodeComment.php +++ b/app/Entities/EpisodeComment.php @@ -118,6 +118,20 @@ class EpisodeComment extends UuidEntity return $this->replies; } + public function getReplyToComment(): ?self + { + if ($this->in_reply_to_id === null) { + throw new RuntimeException('Comment is not a reply.'); + } + + if ($this->reply_to_comment === null) { + $this->reply_to_comment = model('EpisodeCommentModel', false) + ->getCommentById($this->in_reply_to_id); + } + + return $this->reply_to_comment; + } + public function setMessage(string $message): static { helper('activitypub'); diff --git a/app/Language/en/Comment.php b/app/Language/en/Comment.php index d3677dc7..aff97d5e 100644 --- a/app/Language/en/Comment.php +++ b/app/Language/en/Comment.php @@ -9,12 +9,22 @@ declare(strict_types=1); */ return [ + 'title' => "{actorDisplayName}'s comment for {episodeTitle}", + 'back_to_episode' => 'Back to {episodeTitle}', 'form' => [ 'episode_message_placeholder' => 'Write a comment...', 'reply_to_placeholder' => 'Reply to @{actorUsername}', 'submit' => 'Send!', 'submit_reply' => 'Reply', ], + 'likes' => '{numberOfLikes, plural, + one {# like} + other {# likes} + }', + 'replies' => '{numberOfReplies, plural, + one {# reply} + other {# replies} + }', 'like' => 'Like', 'reply' => 'Reply', 'view_replies' => 'View replies ({numberOfReplies})', diff --git a/app/Models/EpisodeCommentModel.php b/app/Models/EpisodeCommentModel.php index 794dab0e..a5e4abf0 100644 --- a/app/Models/EpisodeCommentModel.php +++ b/app/Models/EpisodeCommentModel.php @@ -80,9 +80,15 @@ class EpisodeCommentModel extends UuidModel return false; } - (new EpisodeModel()) - ->where('id', $comment->episode_id) - ->increment('comments_count'); + if ($comment->in_reply_to_id === null) { + (new EpisodeModel()) + ->where('id', $comment->episode_id) + ->increment('comments_count'); + } else { + (new self()) + ->where('id', service('uuid')->fromString($comment->in_reply_to_id)->getBytes()) + ->increment('replies_count'); + } if ($registerActivity) { // set post id and uri to construct NoteObject @@ -129,7 +135,10 @@ class EpisodeCommentModel extends UuidModel { // TODO: merge with replies from posts linked to episode linked $episodeComments = $this->select('*, 0 as is_from_post') - ->where('episode_id', $episodeId) + ->where([ + 'episode_id' => $episodeId, + 'in_reply_to_id' => null, + ]) ->getCompiledSelect(); $episodePostsReplies = $this->db->table('activitypub_posts') diff --git a/app/Views/podcast/_partials/comment.php b/app/Views/podcast/_partials/comment.php index 89ae7700..252914c4 100644 --- a/app/Views/podcast/_partials/comment.php +++ b/app/Views/podcast/_partials/comment.php @@ -20,7 +20,7 @@ is_from_post): ?> include('podcast/_partials/comment_actions_from_post') ?> - include('podcast/_partials/comment_actions') ?> + include('podcast/_partials/comment_actions') ?> diff --git a/app/Views/podcast/_partials/comment_actions.php b/app/Views/podcast/_partials/comment_actions.php index cb92fda5..3be76625 100644 --- a/app/Views/podcast/_partials/comment_actions.php +++ b/app/Views/podcast/_partials/comment_actions.php @@ -1,19 +1,10 @@