diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index 88d4be2e..e59d3389 100644
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -771,12 +771,24 @@ $routes->group('@(:podcastHandle)', function ($routes): void {
'controller-method' => 'EpisodeController::comments/$1/$2',
],
]);
- $routes->get('comments/(:uuid)', 'EpisodeController::comment/$1/$2/$3', [
+ $routes->get('comments/(:uuid)', 'EpisodeCommentController::view/$1/$2/$3', [
'as' => 'comment',
+ 'application/activity+json' => [
+ 'controller-method' => 'EpisodeController::commentObject/$1/$2',
+ ],
+ 'application/podcast-activity+json' => [
+ 'controller-method' => 'EpisodeController::commentObject/$1/$2',
+ ],
+ 'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
+ 'controller-method' => 'EpisodeController::commentObject/$1/$2',
+ ],
]);
- $routes->get('comments/(:uuid)/replies', 'EpisodeController::commentReplies/$1/$2/$3', [
+ $routes->get('comments/(:uuid)/replies', 'EpisodeCommentController::replies/$1/$2/$3', [
'as' => 'comment-replies',
]);
+ $routes->post('comments/(:uuid)/like', 'EpisodeCommentController::attemptLike/$1/$2/$3', [
+ 'as' => 'comment-attempt-like',
+ ]);
$routes->get('oembed.json', 'EpisodeController::oembedJSON/$1/$2', [
'as' => 'episode-oembed-json',
]);
diff --git a/app/Controllers/Admin/EpisodeController.php b/app/Controllers/Admin/EpisodeController.php
index fea2490d..665c8007 100644
--- a/app/Controllers/Admin/EpisodeController.php
+++ b/app/Controllers/Admin/EpisodeController.php
@@ -10,13 +10,13 @@ declare(strict_types=1);
namespace App\Controllers\Admin;
-use App\Entities\Comment;
use App\Entities\Episode;
+use App\Entities\EpisodeComment;
use App\Entities\Image;
use App\Entities\Location;
use App\Entities\Podcast;
use App\Entities\Post;
-use App\Models\CommentModel;
+use App\Models\EpisodeCommentModel;
use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use App\Models\PostModel;
@@ -800,7 +800,7 @@ class EpisodeController extends BaseController
$message = $this->request->getPost('message');
- $newComment = new Comment([
+ $newComment = new EpisodeComment([
'actor_id' => interact_as_actor_id(),
'episode_id' => $this->episode->id,
'message' => $message,
@@ -808,7 +808,7 @@ class EpisodeController extends BaseController
'created_by' => user_id(),
]);
- $commentModel = new CommentModel();
+ $commentModel = new EpisodeCommentModel();
if (
! $commentModel->addComment($newComment, true)
) {
diff --git a/app/Controllers/EpisodeCommentController.php b/app/Controllers/EpisodeCommentController.php
new file mode 100644
index 00000000..4f503d39
--- /dev/null
+++ b/app/Controllers/EpisodeCommentController.php
@@ -0,0 +1,173 @@
+getPodcastByHandle($params[0])) === null
+ ) {
+ throw PageNotFoundException::forPageNotFound();
+ }
+
+ $this->podcast = $podcast;
+ $this->actor = $podcast->actor;
+
+ if (
+ ($episode = (new EpisodeModel())->getEpisodeBySlug($params[0], $params[1])) === null
+ ) {
+ throw PageNotFoundException::forPageNotFound();
+ }
+
+ $this->episode = $episode;
+
+ if (
+ ($comment = (new EpisodeCommentModel())->getCommentById($params[2])) === null
+ ) {
+ throw PageNotFoundException::forPageNotFound();
+ }
+
+ $this->comment = $comment;
+
+ unset($params[2]);
+ unset($params[1]);
+ unset($params[0]);
+
+ return $this->{$method}(...$params);
+ }
+
+ public function view(): string
+ {
+ // Prevent analytics hit when authenticated
+ if (! can_user_interact()) {
+ $this->registerPodcastWebpageHit($this->podcast->id);
+ }
+
+ $cacheName = implode(
+ '_',
+ array_filter([
+ 'page',
+ "comment#{$this->comment->id}",
+ service('request')
+ ->getLocale(),
+ can_user_interact() ? '_authenticated' : null,
+ ]),
+ );
+
+ if (! ($cachedView = cache($cacheName))) {
+ $data = [
+ 'podcast' => $this->podcast,
+ 'actor' => $this->actor,
+ 'episode' => $this->episode,
+ 'comment' => $this->comment,
+ ];
+
+ // if user is logged in then send to the authenticated activity view
+ if (can_user_interact()) {
+ helper('form');
+ return view('podcast/comment_authenticated', $data);
+ }
+ return view('podcast/comment', $data, [
+ 'cache' => DECADE,
+ 'cache_name' => $cacheName,
+ ]);
+ }
+
+ return $cachedView;
+ }
+
+ /**
+ * @noRector ReturnTypeDeclarationRector
+ */
+ public function commentObject(): Response
+ {
+ $commentObject = new CommentObject($this->comment);
+
+ return $this->response
+ ->setContentType('application/json')
+ ->setBody($commentObject->toJSON());
+ }
+
+ public function replies(): Response
+ {
+ /**
+ * get comment replies
+ */
+ $commentReplies = model('CommentModel', false)
+ ->where('in_reply_to_id', service('uuid')->fromString($this->comment->id)->getBytes())
+ ->orderBy('created_at', 'ASC');
+
+ $pageNumber = (int) $this->request->getGet('page');
+
+ if ($pageNumber < 1) {
+ $commentReplies->paginate(12);
+ $pager = $commentReplies->pager;
+ $collection = new OrderedCollectionObject(null, $pager);
+ } else {
+ $paginatedReplies = $commentReplies->paginate(12, 'default', $pageNumber);
+ $pager = $commentReplies->pager;
+
+ $orderedItems = [];
+ if ($paginatedReplies !== null) {
+ foreach ($paginatedReplies as $reply) {
+ $replyObject = new CommentObject($reply);
+ $orderedItems[] = $replyObject;
+ }
+ }
+
+ $collection = new OrderedCollectionPage($pager, $orderedItems);
+ }
+
+ return $this->response
+ ->setContentType('application/activity+json')
+ ->setBody($collection->toJSON());
+ }
+
+ public function attemptLike(): RedirectResponse
+ {
+ model('LikeModel')
+ ->toggleLike(interact_as_actor(), $this->comment);
+
+ return redirect()->back();
+ }
+}
diff --git a/app/Controllers/EpisodeController.php b/app/Controllers/EpisodeController.php
index 4e44af57..c721fb6f 100644
--- a/app/Controllers/EpisodeController.php
+++ b/app/Controllers/EpisodeController.php
@@ -15,10 +15,8 @@ use ActivityPub\Objects\OrderedCollectionPage;
use Analytics\AnalyticsTrait;
use App\Entities\Episode;
use App\Entities\Podcast;
-use App\Libraries\CommentObject;
use App\Libraries\NoteObject;
use App\Libraries\PodcastEpisode;
-use App\Models\CommentModel;
use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use CodeIgniter\Database\BaseBuilder;
@@ -256,57 +254,4 @@ class EpisodeController extends BaseController
->setHeader('Access-Control-Allow-Origin', '*')
->setBody($collection->toJSON());
}
-
- /**
- * @noRector ReturnTypeDeclarationRector
- */
- public function comment(string $commentId): Response
- {
- if (
- ($comment = (new CommentModel())->getCommentById($commentId)) === null
- ) {
- throw PageNotFoundException::forPageNotFound();
- }
-
- $commentObject = new CommentObject($comment);
-
- return $this->response
- ->setContentType('application/json')
- ->setBody($commentObject->toJSON());
- }
-
- public function commentReplies(string $commentId): Response
- {
- /**
- * get comment replies
- */
- $commentReplies = model('CommentModel', false)
- ->where('in_reply_to_id', service('uuid')->fromString($commentId)->getBytes())
- ->orderBy('created_at', 'ASC');
-
- $pageNumber = (int) $this->request->getGet('page');
-
- if ($pageNumber < 1) {
- $commentReplies->paginate(12);
- $pager = $commentReplies->pager;
- $collection = new OrderedCollectionObject(null, $pager);
- } else {
- $paginatedReplies = $commentReplies->paginate(12, 'default', $pageNumber);
- $pager = $commentReplies->pager;
-
- $orderedItems = [];
- if ($paginatedReplies !== null) {
- foreach ($paginatedReplies as $reply) {
- $replyObject = new CommentObject($reply);
- $orderedItems[] = $replyObject;
- }
- }
-
- $collection = new OrderedCollectionPage($pager, $orderedItems);
- }
-
- return $this->response
- ->setContentType('application/activity+json')
- ->setBody($collection->toJSON());
- }
}
diff --git a/app/Database/Migrations/2021-08-12-150000_add_comments.php b/app/Database/Migrations/2021-08-12-150000_add_episode_comments.php
similarity index 79%
rename from app/Database/Migrations/2021-08-12-150000_add_comments.php
rename to app/Database/Migrations/2021-08-12-150000_add_episode_comments.php
index 612d9f63..1524d456 100644
--- a/app/Database/Migrations/2021-08-12-150000_add_comments.php
+++ b/app/Database/Migrations/2021-08-12-150000_add_episode_comments.php
@@ -3,9 +3,9 @@
declare(strict_types=1);
/**
- * Class AddComments creates comments table in database
+ * Class AddEpisodeComments creates episode_comments table in database
*
- * @copyright 2020 Podlibre
+ * @copyright 2021 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
@@ -14,7 +14,7 @@ namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
-class AddComments extends Migration
+class AddEpisodeComments extends Migration
{
public function up(): void
{
@@ -42,22 +42,16 @@ class AddComments extends Migration
],
'message' => [
'type' => 'VARCHAR',
- 'constraint' => 500,
- 'null' => true,
+ 'constraint' => 5000,
],
'message_html' => [
'type' => 'VARCHAR',
- 'constraint' => 600,
- 'null' => true,
+ 'constraint' => 6000,
],
'likes_count' => [
'type' => 'INT',
'unsigned' => true,
],
- 'dislikes_count' => [
- 'type' => 'INT',
- 'unsigned' => true,
- ],
'replies_count' => [
'type' => 'INT',
'unsigned' => true,
@@ -75,11 +69,11 @@ class AddComments extends Migration
$this->forge->addForeignKey('episode_id', 'episodes', 'id', '', 'CASCADE');
$this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
$this->forge->addForeignKey('created_by', 'users', 'id');
- $this->forge->createTable('comments');
+ $this->forge->createTable('episode_comments');
}
public function down(): void
{
- $this->forge->dropTable('comments');
+ $this->forge->dropTable('episode_comments');
}
}
diff --git a/app/Database/Migrations/2021-08-12-160000_add_likes.php b/app/Database/Migrations/2021-08-12-160000_add_likes.php
new file mode 100644
index 00000000..a32dc75e
--- /dev/null
+++ b/app/Database/Migrations/2021-08-12-160000_add_likes.php
@@ -0,0 +1,42 @@
+forge->addField([
+ 'actor_id' => [
+ 'type' => 'INT',
+ 'unsigned' => true,
+ ],
+ 'comment_id' => [
+ 'type' => 'BINARY',
+ 'constraint' => 16,
+ ],
+ ]);
+ $this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()');
+ $this->forge->addPrimaryKey(['actor_id', 'comment_id']);
+ $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
+ $this->forge->addForeignKey('comment_id', 'episode_comments', 'id', '', 'CASCADE');
+ $this->forge->createTable('likes');
+ }
+
+ public function down(): void
+ {
+ $this->forge->dropTable('likes');
+ }
+}
diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php
index 7b976a2e..c01219dd 100644
--- a/app/Entities/Episode.php
+++ b/app/Entities/Episode.php
@@ -11,7 +11,7 @@ declare(strict_types=1);
namespace App\Entities;
use App\Libraries\SimpleRSSElement;
-use App\Models\CommentModel;
+use App\Models\EpisodeCommentModel;
use App\Models\PersonModel;
use App\Models\PodcastModel;
use App\Models\PostModel;
@@ -122,7 +122,7 @@ class Episode extends Entity
protected ?array $posts = null;
/**
- * @var Comment[]|null
+ * @var EpisodeComment[]|null
*/
protected ?array $comments = null;
@@ -402,7 +402,7 @@ class Episode extends Entity
}
/**
- * @return Comment[]
+ * @return EpisodeComment[]
*/
public function getComments(): array
{
@@ -411,7 +411,7 @@ class Episode extends Entity
}
if ($this->comments === null) {
- $this->comments = (new CommentModel())->getEpisodeComments($this->id);
+ $this->comments = (new EpisodeCommentModel())->getEpisodeComments($this->id);
}
return $this->comments;
diff --git a/app/Entities/Comment.php b/app/Entities/EpisodeComment.php
similarity index 77%
rename from app/Entities/Comment.php
rename to app/Entities/EpisodeComment.php
index 6235802f..db2622c1 100644
--- a/app/Entities/Comment.php
+++ b/app/Entities/EpisodeComment.php
@@ -10,6 +10,7 @@ declare(strict_types=1);
namespace App\Entities;
+use App\Models\EpisodeCommentModel;
use App\Models\EpisodeModel;
use CodeIgniter\I18n\Time;
use Michalsn\Uuid\UuidEntity;
@@ -23,22 +24,28 @@ use RuntimeException;
* @property int $actor_id
* @property Actor|null $actor
* @property string $in_reply_to_id
- * @property Comment|null $reply_to_comment
+ * @property EpisodeComment|null $reply_to_comment
* @property string $message
* @property string $message_html
* @property int $likes_count
- * @property int $dislikes_count
* @property int $replies_count
* @property Time $created_at
* @property int $created_by
+ *
+ * @property EpisodeComment[] $replies
*/
-class Comment extends UuidEntity
+class EpisodeComment extends UuidEntity
{
protected ?Episode $episode = null;
protected ?Actor $actor = null;
- protected ?Comment $reply_to_comment = null;
+ protected ?EpisodeComment $reply_to_comment = null;
+
+ /**
+ * @var EpisodeComment[]|null
+ */
+ protected ?array $replies = null;
/**
* @var string[]
@@ -57,7 +64,6 @@ class Comment extends UuidEntity
'message' => 'string',
'message_html' => 'string',
'likes_count' => 'integer',
- 'dislikes_count' => 'integer',
'replies_count' => 'integer',
'created_by' => 'integer',
'is_from_post' => 'boolean',
@@ -96,6 +102,22 @@ class Comment extends UuidEntity
return $this->actor;
}
+ /**
+ * @return EpisodeComment[]
+ */
+ public function getReplies(): array
+ {
+ if ($this->id === null) {
+ throw new RuntimeException('Comment must be created before getting replies.');
+ }
+
+ if ($this->replies === null) {
+ $this->replies = (new EpisodeCommentModel())->getCommentReplies($this->id);
+ }
+
+ return $this->replies;
+ }
+
public function setMessage(string $message): static
{
helper('activitypub');
diff --git a/app/Entities/Like.php b/app/Entities/Like.php
new file mode 100644
index 00000000..ab9f3893
--- /dev/null
+++ b/app/Entities/Like.php
@@ -0,0 +1,33 @@
+
+ */
+ protected $casts = [
+ 'actor_id' => 'integer',
+ 'comment_id' => 'string',
+ ];
+}
diff --git a/app/Language/en/Comment.php b/app/Language/en/Comment.php
index 7073865a..d3677dc7 100644
--- a/app/Language/en/Comment.php
+++ b/app/Language/en/Comment.php
@@ -16,11 +16,8 @@ return [
'submit_reply' => 'Reply',
],
'like' => 'Like',
- 'dislike' => 'Dislike',
- 'replies' => '{numberOfReplies, plural,
- one {# reply}
- other {# replies}
- }',
+ 'reply' => 'Reply',
+ 'view_replies' => 'View replies ({numberOfReplies})',
'block_actor' => 'Block user @{actorUsername}',
'block_domain' => 'Block domain @{actorDomain}',
'delete' => 'Delete comment',
diff --git a/app/Language/fr/Comment.php b/app/Language/fr/Comment.php
new file mode 100644
index 00000000..ce5fab4f
--- /dev/null
+++ b/app/Language/fr/Comment.php
@@ -0,0 +1,27 @@
+ [
+ 'episode_message_placeholder' => 'Saisissez un commentaire...',
+ 'reply_to_placeholder' => 'Répondre à @{actorUsername}',
+ 'submit' => 'Envoyer !',
+ 'submit_reply' => 'Répondre',
+ ],
+ 'like' => 'J’aime',
+ 'reply' => 'Répondre',
+ 'replies' => '{numberOfReplies, plural,
+ one {# réponse}
+ other {# réponses}
+ }',
+ 'block_actor' => 'Bloquer l’utilisateur @{actorUsername}',
+ 'block_domain' => 'Bloquer le domaine @{actorDomain}',
+ 'delete' => 'Supprimer le commentaire',
+];
diff --git a/app/Language/fr/Post.php b/app/Language/fr/Post.php
index a12bdd6f..2981a4be 100644
--- a/app/Language/fr/Post.php
+++ b/app/Language/fr/Post.php
@@ -19,7 +19,7 @@ return [
'Écrivez votre message pour l’épisode...',
'episode_url_placeholder' => 'URL de l’épisode',
'reply_to_placeholder' => 'Répondre à @{actorUsername}',
- 'submit' => 'Envoyer!',
+ 'submit' => 'Envoyer !',
'submit_reply' => 'Répondre',
],
'favourites' => '{numberOfFavourites, plural,
diff --git a/app/Libraries/ActivityPub/Models/FavouriteModel.php b/app/Libraries/ActivityPub/Models/FavouriteModel.php
index 3e22785b..c0c4e9f1 100644
--- a/app/Libraries/ActivityPub/Models/FavouriteModel.php
+++ b/app/Libraries/ActivityPub/Models/FavouriteModel.php
@@ -100,14 +100,12 @@ class FavouriteModel extends UuidModel
->where('id', service('uuid') ->fromString($post->id) ->getBytes())
->decrement('favourites_count');
- $this->db
- ->table('activitypub_favourites')
- ->where([
- 'actor_id' => $actor->id,
- 'post_id' => service('uuid')
- ->fromString($post->id)
- ->getBytes(),
- ])
+ $this->where([
+ 'actor_id' => $actor->id,
+ 'post_id' => service('uuid')
+ ->fromString($post->id)
+ ->getBytes(),
+ ])
->delete();
if ($registerActivity) {
@@ -161,7 +159,7 @@ class FavouriteModel extends UuidModel
}
/**
- * Adds or removes favourite from database and increments count
+ * Adds or removes favourite from database
*/
public function toggleFavourite(Actor $actor, Post $post): void
{
diff --git a/app/Libraries/CommentObject.php b/app/Libraries/CommentObject.php
index d127bcc2..0cbd3962 100644
--- a/app/Libraries/CommentObject.php
+++ b/app/Libraries/CommentObject.php
@@ -11,7 +11,7 @@ declare(strict_types=1);
namespace App\Libraries;
use ActivityPub\Core\ObjectType;
-use App\Entities\Comment;
+use App\Entities\EpisodeComment;
class CommentObject extends ObjectType
{
@@ -23,7 +23,7 @@ class CommentObject extends ObjectType
protected string $replies;
- public function __construct(Comment $comment)
+ public function __construct(EpisodeComment $comment)
{
$this->id = $comment->uri;
diff --git a/app/Models/CommentModel.php b/app/Models/EpisodeCommentModel.php
similarity index 81%
rename from app/Models/CommentModel.php
rename to app/Models/EpisodeCommentModel.php
index ba7215fa..794dab0e 100644
--- a/app/Models/CommentModel.php
+++ b/app/Models/EpisodeCommentModel.php
@@ -11,22 +11,22 @@ declare(strict_types=1);
namespace App\Models;
use ActivityPub\Activities\CreateActivity;
-use App\Entities\Comment;
+use App\Entities\EpisodeComment;
use App\Libraries\CommentObject;
use CodeIgniter\Database\BaseBuilder;
use Michalsn\Uuid\UuidModel;
-class CommentModel extends UuidModel
+class EpisodeCommentModel extends UuidModel
{
/**
* @var string
*/
- protected $returnType = Comment::class;
+ protected $returnType = EpisodeComment::class;
/**
* @var string
*/
- protected $table = 'comments';
+ protected $table = 'episode_comments';
/**
* @var string[]
@@ -45,7 +45,6 @@ class CommentModel extends UuidModel
'message',
'message_html',
'likes_count',
- 'dislikes_count',
'replies_count',
'created_at',
'created_by',
@@ -56,7 +55,7 @@ class CommentModel extends UuidModel
*/
protected $beforeInsert = ['setCommentId'];
- public function getCommentById(string $commentId): ?Comment
+ public function getCommentById(string $commentId): ?EpisodeComment
{
$cacheName = "comment#{$commentId}";
if (! ($found = cache($cacheName))) {
@@ -69,7 +68,7 @@ class CommentModel extends UuidModel
return $found;
}
- public function addComment(Comment $comment, bool $registerActivity = false): string | false
+ public function addComment(EpisodeComment $comment, bool $registerActivity = false): string | false
{
$this->db->transStart();
// increment Episode's comments_count
@@ -122,7 +121,9 @@ class CommentModel extends UuidModel
/**
* Retrieves all published posts for a given episode ordered by publication date
*
- * @return Comment[]
+ * @return EpisodeComment[]
+ *
+ * @noRector ReturnTypeDeclarationRector
*/
public function getEpisodeComments(int $episodeId): array
{
@@ -133,7 +134,7 @@ class CommentModel extends UuidModel
$episodePostsReplies = $this->db->table('activitypub_posts')
->select(
- 'id, uri, episode_id, actor_id, in_reply_to_id, message, message_html, favourites_count as likes_count, 0 as dislikes_count, replies_count, published_at as created_at, created_by, 1 as is_from_post'
+ 'id, uri, episode_id, actor_id, in_reply_to_id, message, message_html, favourites_count as likes_count, replies_count, published_at as created_at, created_by, 1 as is_from_post'
)
->whereIn('in_reply_to_id', function (BaseBuilder $builder) use (&$episodeId): BaseBuilder {
return $builder->select('id')
@@ -147,18 +148,25 @@ class CommentModel extends UuidModel
$episodeComments . ' UNION ' . $episodePostsReplies . ' ORDER BY created_at ASC'
);
- return $allEpisodeComments->getCustomResultObject($this->returnType);
+ // FIXME:?
+ // @phpstan-ignore-next-line
+ return $this->convertUuidFieldsToStrings(
+ $allEpisodeComments->getCustomResultObject($this->tempReturnType),
+ $this->tempReturnType
+ );
}
/**
* Retrieves all replies for a given comment
*
- * @return Comment[]
+ * @return EpisodeComment[]
*/
- public function getCommentReplies(int $episodeId, string $commentId): array
+ public function getCommentReplies(string $commentId): array
{
// TODO: get all replies for a given comment
- return $this->findAll();
+ return $this->where('in_reply_to_id', $this->uuid->fromString($commentId)->getBytes())
+ ->orderBy('created_at', 'ASC')
+ ->findAll();
}
/**
diff --git a/app/Models/LikeModel.php b/app/Models/LikeModel.php
new file mode 100644
index 00000000..01d49d1b
--- /dev/null
+++ b/app/Models/LikeModel.php
@@ -0,0 +1,165 @@
+db->transStart();
+
+ $this->insert([
+ 'actor_id' => $actor->id,
+ 'comment_id' => $comment->id,
+ ]);
+
+ (new EpisodeCommentModel())
+ ->where('id', service('uuid')->fromString($comment->id)->getBytes())
+ ->increment('likes_count');
+
+ if ($registerActivity) {
+ $likeActivity = new LikeActivity();
+ $likeActivity->set('actor', $actor->uri)
+ ->set('object', $comment->uri);
+
+ $activityId = model('ActivityModel')
+ ->newActivity(
+ 'Like',
+ $actor->id,
+ null,
+ null,
+ $likeActivity->toJSON(),
+ $comment->created_at,
+ 'queued',
+ );
+
+ $likeActivity->set('id', url_to('activity', $actor->username, $activityId));
+
+ model('ActivityModel')
+ ->update($activityId, [
+ 'payload' => $likeActivity->toJSON(),
+ ]);
+ }
+
+ $this->db->transComplete();
+ }
+
+ public function removeLike(Actor $actor, EpisodeComment $comment, bool $registerActivity = true): void
+ {
+ $this->db->transStart();
+
+ (new EpisodeCommentModel())
+ ->where('id', service('uuid') ->fromString($comment->id) ->getBytes())
+ ->decrement('likes_count');
+
+ $this->where([
+ 'actor_id' => $actor->id,
+ 'comment_id' => service('uuid')
+ ->fromString($comment->id)
+ ->getBytes(),
+ ])
+ ->delete();
+
+ if ($registerActivity) {
+ $undoActivity = new UndoActivity();
+ // FIXME: get like activity associated with the deleted like
+ $activity = model('ActivityModel')
+ ->where([
+ 'type' => 'Like',
+ 'actor_id' => $actor->id,
+ ])
+ ->first();
+
+ $likeActivity = new LikeActivity();
+ $likeActivity
+ ->set('id', url_to('activity', $actor->username, $activity->id))
+ ->set('actor', $actor->uri)
+ ->set('object', $comment->uri);
+
+ $undoActivity
+ ->set('actor', $actor->uri)
+ ->set('object', $likeActivity);
+
+ $activityId = model('ActivityModel')
+ ->newActivity(
+ 'Undo',
+ $actor->id,
+ null,
+ null,
+ $undoActivity->toJSON(),
+ $comment->created_at,
+ 'queued',
+ );
+
+ $undoActivity->set('id', url_to('activity', $actor->username, $activityId));
+
+ model('ActivityModel')
+ ->update($activityId, [
+ 'payload' => $undoActivity->toJSON(),
+ ]);
+ }
+
+ $this->db->transComplete();
+ }
+
+ /**
+ * Adds or removes likes from database
+ */
+ public function toggleLike(Actor $actor, EpisodeComment $comment): void
+ {
+ if (
+ $this->where([
+ 'actor_id' => $actor->id,
+ 'comment_id' => service('uuid')
+ ->fromString($comment->id)
+ ->getBytes(),
+ ])->first()
+ ) {
+ $this->removeLike($actor, $comment);
+ } else {
+ $this->addLike($actor, $comment);
+ }
+ }
+}
diff --git a/app/Resources/icons/thumb-down.svg b/app/Resources/icons/thumb-down.svg
deleted file mode 100644
index ff06be8a..00000000
--- a/app/Resources/icons/thumb-down.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/app/Resources/icons/thumb-up.svg b/app/Resources/icons/thumb-up.svg
deleted file mode 100644
index f0d66702..00000000
--- a/app/Resources/icons/thumb-up.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/app/Views/podcast/_partials/comment.php b/app/Views/podcast/_partials/comment.php
index 587df069..89ae7700 100644
--- a/app/Views/podcast/_partials/comment.php
+++ b/app/Views/podcast/_partials/comment.php
@@ -1,7 +1,7 @@
+
+