Loading app/Config/ActivityPub.php +0 −3 Original line number Diff line number Diff line Loading @@ -6,7 +6,6 @@ namespace Config; use ActivityPub\Config\ActivityPub as ActivityPubBase; use App\Libraries\NoteObject; use App\Libraries\PodcastActor; class ActivityPub extends ActivityPubBase { Loading @@ -15,8 +14,6 @@ class ActivityPub extends ActivityPubBase * ActivityPub Objects * -------------------------------------------------------------------- */ public string $actorObject = PodcastActor::class; public string $noteObject = NoteObject::class; /** Loading app/Config/Routes.php +38 −0 Original line number Diff line number Diff line Loading @@ -697,6 +697,10 @@ $routes->group('@(:podcastName)', function ($routes): void { 'namespace' => 'ActivityPub\Controllers', 'controller-method' => 'ActorController/$1', ], 'application/podcast-activity+json' => [ 'namespace' => 'App\Controllers', 'controller-method' => 'PodcastController::podcastActor/$1', ], 'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [ 'namespace' => 'ActivityPub\Controllers', 'controller-method' => 'ActorController/$1', Loading @@ -705,10 +709,44 @@ $routes->group('@(:podcastName)', function ($routes): void { ]); $routes->get('episodes', 'PodcastController::episodes/$1', [ 'as' => 'podcast-episodes', 'alternate-content' => [ 'application/activity+json' => [ 'controller-method' => 'PodcastController::episodeCollection/$1', ], 'application/podcast-activity+json' => [ 'controller-method' => 'PodcastController::episodeCollection/$1', ], 'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [ 'controller-method' => 'PodcastController::episodeCollection/$1', ], ], ]); $routes->group('episodes/(:slug)', function ($routes): void { $routes->get('/', 'EpisodeController/$1/$2', [ 'as' => 'episode', 'alternate-content' => [ 'application/activity+json' => [ 'controller-method' => 'EpisodeController::episodeObject/$1/$2', ], 'application/podcast-activity+json' => [ 'controller-method' => 'EpisodeController::episodeObject/$1/$2', ], 'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [ 'controller-method' => 'EpisodeController::episodeObject/$1/$2', ], ], ]); $routes->get('comments', 'EpisodeController::comments/$1/$2', [ 'as' => 'episode-comments', 'application/activity+json' => [ 'controller-method' => 'EpisodeController::comments/$1/$2', ], 'application/podcast-activity+json' => [ 'controller-method' => 'EpisodeController::comments/$1/$2', ], 'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [ 'controller-method' => 'EpisodeController::comments/$1/$2', ], ]); $routes->get('oembed.json', 'EpisodeController::oembedJSON/$1/$2', [ 'as' => 'episode-oembed-json', Loading app/Controllers/EpisodeController.php +61 −0 Original line number Diff line number Diff line Loading @@ -10,12 +10,18 @@ declare(strict_types=1); namespace App\Controllers; use ActivityPub\Objects\OrderedCollectionObject; use ActivityPub\Objects\OrderedCollectionPage; use Analytics\AnalyticsTrait; use App\Entities\Episode; use App\Entities\Podcast; use App\Libraries\NoteObject; use App\Libraries\PodcastEpisode; use App\Models\EpisodeModel; use App\Models\PodcastModel; use CodeIgniter\Database\BaseBuilder; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\Response; use CodeIgniter\HTTP\ResponseInterface; use Config\Services; use SimpleXMLElement; Loading Loading @@ -191,4 +197,59 @@ class EpisodeController extends BaseController return $this->response->setXML((string) $oembed); } /** * @noRector ReturnTypeDeclarationRector */ public function episodeObject(): Response { $podcastObject = new PodcastEpisode($this->episode); return $this->response ->setContentType('application/json') ->setBody($podcastObject->toJSON()); } /** * @noRector ReturnTypeDeclarationRector */ public function comments(): Response { /** * get comments: aggregated replies from posts referring to the episode */ $episodeComments = model('StatusModel') ->whereIn('in_reply_to_id', function (BaseBuilder $builder): BaseBuilder { return $builder->select('id') ->from('activitypub_statuses') ->where('episode_id', $this->episode->id); }) ->where('`published_at` <= NOW()', null, false) ->orderBy('published_at', 'ASC'); $pageNumber = (int) $this->request->getGet('page'); if ($pageNumber < 1) { $episodeComments->paginate(12); $pager = $episodeComments->pager; $collection = new OrderedCollectionObject(null, $pager); } else { $paginatedComments = $episodeComments->paginate(12, 'default', $pageNumber); $pager = $episodeComments->pager; $orderedItems = []; if ($paginatedComments !== null) { foreach ($paginatedComments as $comment) { $orderedItems[] = (new NoteObject($comment))->toArray(); } } // @phpstan-ignore-next-line $collection = new OrderedCollectionPage($pager, $orderedItems); } return $this->response ->setContentType('application/activity+json') ->setBody($collection->toJSON()); } } app/Controllers/PodcastController.php +57 −0 Original line number Diff line number Diff line Loading @@ -10,12 +10,18 @@ declare(strict_types=1); namespace App\Controllers; use ActivityPub\Objects\OrderedCollectionObject; use ActivityPub\Objects\OrderedCollectionPage; use Analytics\AnalyticsTrait; use App\Entities\Podcast; use App\Libraries\PodcastActor; use App\Libraries\PodcastEpisode; use App\Models\EpisodeModel; use App\Models\PodcastModel; use App\Models\StatusModel; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\Response; class PodcastController extends BaseController { Loading @@ -42,6 +48,15 @@ class PodcastController extends BaseController return $this->{$method}(...$params); } public function podcastActor(): RedirectResponse { $podcastActor = new PodcastActor($this->podcast); return $this->response ->setContentType('application/activity+json') ->setBody($podcastActor->toJSON()); } public function activity(): string { // Prevent analytics hit when authenticated Loading Loading @@ -209,4 +224,46 @@ class PodcastController extends BaseController return $cachedView; } /** * @noRector ReturnTypeDeclarationRector */ public function episodeCollection(): Response { if ($this->podcast->type === 'serial') { // podcast is serial $episodes = model('EpisodeModel') ->where('`published_at` <= NOW()', null, false) ->orderBy('season_number DESC, number ASC'); } else { $episodes = model('EpisodeModel') ->where('`published_at` <= NOW()', null, false) ->orderBy('published_at', 'DESC'); } $pageNumber = (int) $this->request->getGet('page'); if ($pageNumber < 1) { $episodes->paginate(12); $pager = $episodes->pager; $collection = new OrderedCollectionObject(null, $pager); } else { $paginatedEpisodes = $episodes->paginate(12, 'default', $pageNumber); $pager = $episodes->pager; $orderedItems = []; if ($paginatedEpisodes !== null) { foreach ($paginatedEpisodes as $episode) { $orderedItems[] = (new PodcastEpisode($episode))->toArray(); } } // @phpstan-ignore-next-line $collection = new OrderedCollectionPage($pager, $orderedItems); } return $this->response ->setContentType('application/activity+json') ->setBody($collection->toJSON()); } } app/Entities/Episode.php +22 −1 Original line number Diff line number Diff line Loading @@ -121,6 +121,11 @@ class Episode extends Entity */ protected ?array $statuses = null; /** * @var Status[]|null */ protected ?array $comments = null; protected ?Location $location = null; protected string $custom_rss_string; Loading Loading @@ -387,7 +392,7 @@ class Episode extends Entity public function getStatuses(): array { if ($this->id === null) { throw new RuntimeException('Episode must be created before getting soundbites.'); throw new RuntimeException('Episode must be created before getting statuses.'); } if ($this->statuses === null) { Loading @@ -397,6 +402,22 @@ class Episode extends Entity return $this->statuses; } /** * @return Status[] */ public function getComments(): array { if ($this->id === null) { throw new RuntimeException('Episode must be created before getting comments.'); } if ($this->comments === null) { $this->comments = (new StatusModel())->getEpisodeComments($this->id); } return $this->comments; } public function getLink(): string { return base_url(route_to('episode', $this->getPodcast() ->name, $this->attributes['slug'])); Loading Loading
app/Config/ActivityPub.php +0 −3 Original line number Diff line number Diff line Loading @@ -6,7 +6,6 @@ namespace Config; use ActivityPub\Config\ActivityPub as ActivityPubBase; use App\Libraries\NoteObject; use App\Libraries\PodcastActor; class ActivityPub extends ActivityPubBase { Loading @@ -15,8 +14,6 @@ class ActivityPub extends ActivityPubBase * ActivityPub Objects * -------------------------------------------------------------------- */ public string $actorObject = PodcastActor::class; public string $noteObject = NoteObject::class; /** Loading
app/Config/Routes.php +38 −0 Original line number Diff line number Diff line Loading @@ -697,6 +697,10 @@ $routes->group('@(:podcastName)', function ($routes): void { 'namespace' => 'ActivityPub\Controllers', 'controller-method' => 'ActorController/$1', ], 'application/podcast-activity+json' => [ 'namespace' => 'App\Controllers', 'controller-method' => 'PodcastController::podcastActor/$1', ], 'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [ 'namespace' => 'ActivityPub\Controllers', 'controller-method' => 'ActorController/$1', Loading @@ -705,10 +709,44 @@ $routes->group('@(:podcastName)', function ($routes): void { ]); $routes->get('episodes', 'PodcastController::episodes/$1', [ 'as' => 'podcast-episodes', 'alternate-content' => [ 'application/activity+json' => [ 'controller-method' => 'PodcastController::episodeCollection/$1', ], 'application/podcast-activity+json' => [ 'controller-method' => 'PodcastController::episodeCollection/$1', ], 'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [ 'controller-method' => 'PodcastController::episodeCollection/$1', ], ], ]); $routes->group('episodes/(:slug)', function ($routes): void { $routes->get('/', 'EpisodeController/$1/$2', [ 'as' => 'episode', 'alternate-content' => [ 'application/activity+json' => [ 'controller-method' => 'EpisodeController::episodeObject/$1/$2', ], 'application/podcast-activity+json' => [ 'controller-method' => 'EpisodeController::episodeObject/$1/$2', ], 'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [ 'controller-method' => 'EpisodeController::episodeObject/$1/$2', ], ], ]); $routes->get('comments', 'EpisodeController::comments/$1/$2', [ 'as' => 'episode-comments', 'application/activity+json' => [ 'controller-method' => 'EpisodeController::comments/$1/$2', ], 'application/podcast-activity+json' => [ 'controller-method' => 'EpisodeController::comments/$1/$2', ], 'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [ 'controller-method' => 'EpisodeController::comments/$1/$2', ], ]); $routes->get('oembed.json', 'EpisodeController::oembedJSON/$1/$2', [ 'as' => 'episode-oembed-json', Loading
app/Controllers/EpisodeController.php +61 −0 Original line number Diff line number Diff line Loading @@ -10,12 +10,18 @@ declare(strict_types=1); namespace App\Controllers; use ActivityPub\Objects\OrderedCollectionObject; use ActivityPub\Objects\OrderedCollectionPage; use Analytics\AnalyticsTrait; use App\Entities\Episode; use App\Entities\Podcast; use App\Libraries\NoteObject; use App\Libraries\PodcastEpisode; use App\Models\EpisodeModel; use App\Models\PodcastModel; use CodeIgniter\Database\BaseBuilder; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\Response; use CodeIgniter\HTTP\ResponseInterface; use Config\Services; use SimpleXMLElement; Loading Loading @@ -191,4 +197,59 @@ class EpisodeController extends BaseController return $this->response->setXML((string) $oembed); } /** * @noRector ReturnTypeDeclarationRector */ public function episodeObject(): Response { $podcastObject = new PodcastEpisode($this->episode); return $this->response ->setContentType('application/json') ->setBody($podcastObject->toJSON()); } /** * @noRector ReturnTypeDeclarationRector */ public function comments(): Response { /** * get comments: aggregated replies from posts referring to the episode */ $episodeComments = model('StatusModel') ->whereIn('in_reply_to_id', function (BaseBuilder $builder): BaseBuilder { return $builder->select('id') ->from('activitypub_statuses') ->where('episode_id', $this->episode->id); }) ->where('`published_at` <= NOW()', null, false) ->orderBy('published_at', 'ASC'); $pageNumber = (int) $this->request->getGet('page'); if ($pageNumber < 1) { $episodeComments->paginate(12); $pager = $episodeComments->pager; $collection = new OrderedCollectionObject(null, $pager); } else { $paginatedComments = $episodeComments->paginate(12, 'default', $pageNumber); $pager = $episodeComments->pager; $orderedItems = []; if ($paginatedComments !== null) { foreach ($paginatedComments as $comment) { $orderedItems[] = (new NoteObject($comment))->toArray(); } } // @phpstan-ignore-next-line $collection = new OrderedCollectionPage($pager, $orderedItems); } return $this->response ->setContentType('application/activity+json') ->setBody($collection->toJSON()); } }
app/Controllers/PodcastController.php +57 −0 Original line number Diff line number Diff line Loading @@ -10,12 +10,18 @@ declare(strict_types=1); namespace App\Controllers; use ActivityPub\Objects\OrderedCollectionObject; use ActivityPub\Objects\OrderedCollectionPage; use Analytics\AnalyticsTrait; use App\Entities\Podcast; use App\Libraries\PodcastActor; use App\Libraries\PodcastEpisode; use App\Models\EpisodeModel; use App\Models\PodcastModel; use App\Models\StatusModel; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\Response; class PodcastController extends BaseController { Loading @@ -42,6 +48,15 @@ class PodcastController extends BaseController return $this->{$method}(...$params); } public function podcastActor(): RedirectResponse { $podcastActor = new PodcastActor($this->podcast); return $this->response ->setContentType('application/activity+json') ->setBody($podcastActor->toJSON()); } public function activity(): string { // Prevent analytics hit when authenticated Loading Loading @@ -209,4 +224,46 @@ class PodcastController extends BaseController return $cachedView; } /** * @noRector ReturnTypeDeclarationRector */ public function episodeCollection(): Response { if ($this->podcast->type === 'serial') { // podcast is serial $episodes = model('EpisodeModel') ->where('`published_at` <= NOW()', null, false) ->orderBy('season_number DESC, number ASC'); } else { $episodes = model('EpisodeModel') ->where('`published_at` <= NOW()', null, false) ->orderBy('published_at', 'DESC'); } $pageNumber = (int) $this->request->getGet('page'); if ($pageNumber < 1) { $episodes->paginate(12); $pager = $episodes->pager; $collection = new OrderedCollectionObject(null, $pager); } else { $paginatedEpisodes = $episodes->paginate(12, 'default', $pageNumber); $pager = $episodes->pager; $orderedItems = []; if ($paginatedEpisodes !== null) { foreach ($paginatedEpisodes as $episode) { $orderedItems[] = (new PodcastEpisode($episode))->toArray(); } } // @phpstan-ignore-next-line $collection = new OrderedCollectionPage($pager, $orderedItems); } return $this->response ->setContentType('application/activity+json') ->setBody($collection->toJSON()); } }
app/Entities/Episode.php +22 −1 Original line number Diff line number Diff line Loading @@ -121,6 +121,11 @@ class Episode extends Entity */ protected ?array $statuses = null; /** * @var Status[]|null */ protected ?array $comments = null; protected ?Location $location = null; protected string $custom_rss_string; Loading Loading @@ -387,7 +392,7 @@ class Episode extends Entity public function getStatuses(): array { if ($this->id === null) { throw new RuntimeException('Episode must be created before getting soundbites.'); throw new RuntimeException('Episode must be created before getting statuses.'); } if ($this->statuses === null) { Loading @@ -397,6 +402,22 @@ class Episode extends Entity return $this->statuses; } /** * @return Status[] */ public function getComments(): array { if ($this->id === null) { throw new RuntimeException('Episode must be created before getting comments.'); } if ($this->comments === null) { $this->comments = (new StatusModel())->getEpisodeComments($this->id); } return $this->comments; } public function getLink(): string { return base_url(route_to('episode', $this->getPodcast() ->name, $this->attributes['slug'])); Loading