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])) === null

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

Yassine Doghri
committed
return $this->{$method}(...$params);
/**
* @noRector ReturnTypeDeclarationRector
*/
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, [

Yassine Doghri
committed
'cache' => $secondsToNextUnpublishedEpisode
? $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,

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
? $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 = [

Yassine Doghri
committed
'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
? $secondsToNextUnpublishedEpisode
: DECADE,
'cache_name' => $cacheName,
]);
}
return $cachedView;

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

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

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

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

Yassine Doghri
committed
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
->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());
}