Loading app/Config/Routes.php +14 −2 Original line number Diff line number Diff line Loading @@ -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', ]); Loading app/Controllers/Admin/EpisodeController.php +4 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading @@ -808,7 +808,7 @@ class EpisodeController extends BaseController 'created_by' => user_id(), ]); $commentModel = new CommentModel(); $commentModel = new EpisodeCommentModel(); if ( ! $commentModel->addComment($newComment, true) ) { Loading app/Controllers/EpisodeCommentController.php 0 → 100644 +173 −0 Original line number Diff line number Diff line <?php declare(strict_types=1); /** * @copyright 2020 Podlibre * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @link https://castopod.org/ */ namespace App\Controllers; use ActivityPub\Entities\Actor; use ActivityPub\Objects\OrderedCollectionObject; use ActivityPub\Objects\OrderedCollectionPage; use Analytics\AnalyticsTrait; use App\Controllers\Admin\BaseController; use App\Entities\Episode; use App\Entities\EpisodeComment; use App\Entities\Podcast; use App\Libraries\CommentObject; use App\Models\EpisodeCommentModel; use App\Models\EpisodeModel; use App\Models\PodcastModel; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\Response; class EpisodeCommentController extends BaseController { use AnalyticsTrait; protected Podcast $podcast; protected Actor $actor; protected Episode $episode; protected EpisodeComment $comment; public function _remap(string $method, string ...$params): mixed { if (count($params) < 3) { throw PageNotFoundException::forPageNotFound(); } if ( ($podcast = (new PodcastModel())->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(); } } app/Controllers/EpisodeController.php +0 −55 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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()); } } app/Database/Migrations/2021-08-12-150000_add_comments.php→app/Database/Migrations/2021-08-12-150000_add_episode_comments.php +7 −13 Original line number Diff line number Diff line Loading @@ -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/ */ Loading @@ -14,7 +14,7 @@ namespace App\Database\Migrations; use CodeIgniter\Database\Migration; class AddComments extends Migration class AddEpisodeComments extends Migration { public function up(): void { Loading Loading @@ -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, Loading @@ -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'); } } Loading
app/Config/Routes.php +14 −2 Original line number Diff line number Diff line Loading @@ -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', ]); Loading
app/Controllers/Admin/EpisodeController.php +4 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading @@ -808,7 +808,7 @@ class EpisodeController extends BaseController 'created_by' => user_id(), ]); $commentModel = new CommentModel(); $commentModel = new EpisodeCommentModel(); if ( ! $commentModel->addComment($newComment, true) ) { Loading
app/Controllers/EpisodeCommentController.php 0 → 100644 +173 −0 Original line number Diff line number Diff line <?php declare(strict_types=1); /** * @copyright 2020 Podlibre * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @link https://castopod.org/ */ namespace App\Controllers; use ActivityPub\Entities\Actor; use ActivityPub\Objects\OrderedCollectionObject; use ActivityPub\Objects\OrderedCollectionPage; use Analytics\AnalyticsTrait; use App\Controllers\Admin\BaseController; use App\Entities\Episode; use App\Entities\EpisodeComment; use App\Entities\Podcast; use App\Libraries\CommentObject; use App\Models\EpisodeCommentModel; use App\Models\EpisodeModel; use App\Models\PodcastModel; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\Response; class EpisodeCommentController extends BaseController { use AnalyticsTrait; protected Podcast $podcast; protected Actor $actor; protected Episode $episode; protected EpisodeComment $comment; public function _remap(string $method, string ...$params): mixed { if (count($params) < 3) { throw PageNotFoundException::forPageNotFound(); } if ( ($podcast = (new PodcastModel())->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(); } }
app/Controllers/EpisodeController.php +0 −55 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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()); } }
app/Database/Migrations/2021-08-12-150000_add_comments.php→app/Database/Migrations/2021-08-12-150000_add_episode_comments.php +7 −13 Original line number Diff line number Diff line Loading @@ -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/ */ Loading @@ -14,7 +14,7 @@ namespace App\Database\Migrations; use CodeIgniter\Database\Migration; class AddComments extends Migration class AddEpisodeComments extends Migration { public function up(): void { Loading Loading @@ -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, Loading @@ -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'); } }