Newer
Older

Yassine Doghri
committed

Yassine Doghri
committed
declare(strict_types=1);
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/

Yassine Doghri
committed
namespace App\Controllers;
use App\Entities\Podcast;

Yassine Doghri
committed
use App\Libraries\PodcastActor;
use App\Libraries\PodcastEpisode;
use App\Models\EpisodeModel;
use App\Models\PodcastModel;
use App\Models\PostModel;
use CodeIgniter\Exceptions\PageNotFoundException;

Yassine Doghri
committed
use CodeIgniter\HTTP\Response;

Yassine Doghri
committed
use Modules\Analytics\AnalyticsTrait;
use Modules\Fediverse\Objects\OrderedCollectionObject;
use Modules\Fediverse\Objects\OrderedCollectionPage;
class PodcastController extends BaseController
use AnalyticsTrait;
protected Podcast $podcast;
public function _remap(string $method, string ...$params): mixed
throw PageNotFoundException::forPageNotFound();

Yassine Doghri
committed
}
if (
! ($podcast = (new PodcastModel())->getPodcastByHandle($params[0])) instanceof Podcast

Yassine Doghri
committed
) {
throw PageNotFoundException::forPageNotFound();
$this->podcast = $podcast;
unset($params[0]);

Yassine Doghri
committed
return $this->{$method}(...$params);
public function podcastActor(): Response

Yassine Doghri
committed
{
$podcastActor = new PodcastActor($this->podcast);
return $this->response
->setContentType('application/activity+json')
->setBody($podcastActor->toJSON());
}
public function activity(): string
{
// Prevent analytics hit when authenticated

Yassine Doghri
committed
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$cacheName = implode(
'_',
array_filter([
'page',
"podcast#{$this->podcast->id}",
'activity',
service('request')
->getLocale(),

Yassine Doghri
committed
is_unlocked($this->podcast->handle) ? 'unlocked' : null,

Yassine Doghri
committed
auth()
->loggedIn() ? 'authenticated' : null,
]),
);
if (! ($cachedView = cache($cacheName))) {
$data = [

Yassine Doghri
committed
'metatags' => get_podcast_metatags($this->podcast, 'activity'),
'podcast' => $this->podcast,
'posts' => (new PostModel())->getActorPublishedPosts($this->podcast->actor_id),
];
// if user is logged in then send to the authenticated activity view

Yassine Doghri
committed
if (auth()->loggedIn()) {
helper('form');
return view('podcast/activity', $data);
}

Yassine Doghri
committed
$secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
$this->podcast->id,
);
return view('podcast/activity', $data, [
'cache' => $secondsToNextUnpublishedEpisode ?: DECADE,
'cache_name' => $cacheName,
]);
}
return $cachedView;
}
public function about(): string
{
// Prevent analytics hit when authenticated

Yassine Doghri
committed
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$cacheName = implode(
'_',
array_filter([
'page',
"podcast#{$this->podcast->id}",
'about',
service('request')
->getLocale(),

Yassine Doghri
committed
is_unlocked($this->podcast->handle) ? 'unlocked' : null,

Yassine Doghri
committed
auth()
->loggedIn() ? 'authenticated' : null,
]),
);
if (! ($cachedView = cache($cacheName))) {
$stats = (new EpisodeModel())->getPodcastStats($this->podcast->id);

Yassine Doghri
committed
'metatags' => get_podcast_metatags($this->podcast, 'about'),
'podcast' => $this->podcast,
'stats' => $stats,

Yassine Doghri
committed
// // if user is logged in then send to the authenticated activity view

Yassine Doghri
committed
if (auth()->loggedIn()) {
return view('podcast/about', $data);
}
$secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
$this->podcast->id,
);
return view('podcast/about', $data, [
'cache' => $secondsToNextUnpublishedEpisode ?: DECADE,
'cache_name' => $cacheName,
]);
}
return $cachedView;
}
public function episodes(): string
// Prevent analytics hit when authenticated

Yassine Doghri
committed
if (! auth()->loggedIn()) {
$this->registerPodcastWebpageHit($this->podcast->id);
}
$yearQuery = $this->request->getGet('year');
$seasonQuery = $this->request->getGet('season');
if (! $yearQuery && ! $seasonQuery) {

Yassine Doghri
committed
$defaultQuery = (new PodcastModel())->getDefaultQuery($this->podcast->id);

Yassine Doghri
committed
if ($defaultQuery) {
if ($defaultQuery['type'] === 'season') {

Yassine Doghri
committed
$seasonQuery = $defaultQuery['data']['season_number'];
} elseif ($defaultQuery['type'] === 'year') {

Yassine Doghri
committed
$yearQuery = $defaultQuery['data']['year'];
}
}
}
$cacheName = implode(
'_',
array_filter([
'page',
"podcast#{$this->podcast->id}",
'episodes',

Yassine Doghri
committed
$yearQuery ? 'year' . $yearQuery : null,
$seasonQuery ? 'season' . $seasonQuery : null,
service('request')
->getLocale(),

Yassine Doghri
committed
is_unlocked($this->podcast->handle) ? 'unlocked' : null,

Yassine Doghri
committed
auth()
->loggedIn() ? 'authenticated' : null,
]),
);
if (! ($cachedView = cache($cacheName))) {
// Build navigation array
$podcastModel = new PodcastModel();
$years = $podcastModel->getYears($this->podcast->id);
$seasons = $podcastModel->getSeasons($this->podcast->id);
$episodesNavigation = [];
$activeQuery = null;
foreach ($years as $year) {
$isActive = $yearQuery === $year['year'];
if ($isActive) {
$activeQuery = [
'type' => 'year',
'value' => $year['year'],
'label' => $year['year'],
'number_of_episodes' => $year['number_of_episodes'],
];
}
$episodesNavigation[] = [
'label' => $year['year'],
'number_of_episodes' => $year['number_of_episodes'],
'route' => route_to('podcast-episodes', $this->podcast->handle) .
'?year=' .
$year['year'],
'is_active' => $isActive,
}
foreach ($seasons as $season) {
$isActive = $seasonQuery === $season['season_number'];
if ($isActive) {
$activeQuery = [
'type' => 'season',
'value' => $season['season_number'],
'label' => lang('Podcast.season', [
'seasonNumber' => $season['season_number'],
]),
'number_of_episodes' => $season['number_of_episodes'],
];
}
$episodesNavigation[] = [
'label' => lang('Podcast.season', [
'seasonNumber' => $season['season_number'],
]),
'number_of_episodes' => $season['number_of_episodes'],
'route' => route_to('podcast-episodes', $this->podcast->handle) .
'?season=' .
$season['season_number'],
'is_active' => $isActive,
}
$data = [
'metatags' => get_podcast_metatags($this->podcast, 'episodes'),
'podcast' => $this->podcast,
'episodesNav' => $episodesNavigation,
'activeQuery' => $activeQuery,
'episodes' => (new EpisodeModel())->getPodcastEpisodes(
$this->podcast->id,
$this->podcast->type,
$yearQuery,
$seasonQuery,
),
];

Yassine Doghri
committed
if (auth()->loggedIn()) {
return view('podcast/episodes', $data);
}
$secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
$this->podcast->id,

Yassine Doghri
committed
);
return view('podcast/episodes', $data, [
'cache' => $secondsToNextUnpublishedEpisode ?: DECADE,
'cache_name' => $cacheName,
]);
}
return $cachedView;

Yassine Doghri
committed
public function episodeCollection(): Response
{
if ($this->podcast->type === 'serial') {
// podcast is serial
$episodes = model('EpisodeModel')

Yassine Doghri
committed
->where('`published_at` <= UTC_TIMESTAMP()', null, false)

Yassine Doghri
committed
->orderBy('season_number DESC, number ASC');
} else {
$episodes = model('EpisodeModel')

Yassine Doghri
committed
->where('`published_at` <= UTC_TIMESTAMP()', null, false)

Yassine Doghri
committed
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
->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());
}

Yassine Doghri
committed
public function links(): string
{
return view('podcast/links', [
'metatags' => get_podcast_metatags($this->podcast, 'links'),
'podcast' => $this->podcast,
]);
}