Skip to content
Snippets Groups Projects
PodcastController.php 10.7 KiB
Newer Older
  • Learn to ignore specific revisions
  •  * @copyright  2020 Ad Aures
    
     * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
     * @link       https://castopod.org/
     */
    
    namespace App\Controllers;
    
    use App\Libraries\PodcastActor;
    use App\Libraries\PodcastEpisode;
    
    use CodeIgniter\Exceptions\PageNotFoundException;
    
    use Modules\Analytics\AnalyticsTrait;
    use Modules\Fediverse\Objects\OrderedCollectionObject;
    use Modules\Fediverse\Objects\OrderedCollectionPage;
    
    class PodcastController extends BaseController
    
        public function _remap(string $method, string ...$params): mixed
    
            if ($params === []) {
    
                throw PageNotFoundException::forPageNotFound();
    
                ! ($podcast = (new PodcastModel())->getPodcastByHandle($params[0])) instanceof Podcast
    
                throw PageNotFoundException::forPageNotFound();
    
            $this->podcast = $podcast;
    
            unset($params[0]);
    
            return $this->{$method}(...$params);
    
        public function podcastActor(): Response
    
        {
            $podcastActor = new PodcastActor($this->podcast);
    
            return $this->response
                ->setContentType('application/activity+json')
                ->setBody($podcastActor->toJSON());
        }
    
    
        public function activity(): string
    
            // Prevent analytics hit when authenticated
    
                $this->registerPodcastWebpageHit($this->podcast->id);
            }
    
            $cacheName = implode(
                '_',
                array_filter([
                    'page',
                    "podcast#{$this->podcast->id}",
                    'activity',
    
                    is_unlocked($this->podcast->handle) ? 'unlocked' : null,
    
                    auth()
                        ->loggedIn() ? 'authenticated' : null,
    
            if (! ($cachedView = cache($cacheName))) {
    
                    '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
    
    
                    return view('podcast/activity', $data);
    
    
                $secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
                    $this->podcast->id,
                );
    
    
                return view('podcast/activity', $data, [
    
                    'cache'      => $secondsToNextUnpublishedEpisode ?: DECADE,
    
    
            return $cachedView;
        }
    
        public function about(): string
        {
            // Prevent analytics hit when authenticated
    
                $this->registerPodcastWebpageHit($this->podcast->id);
            }
    
            $cacheName = implode(
                '_',
                array_filter([
                    'page',
                    "podcast#{$this->podcast->id}",
                    'about',
                    service('request')
                        ->getLocale(),
    
                    is_unlocked($this->podcast->handle) ? 'unlocked' : null,
    
                    auth()
                        ->loggedIn() ? 'authenticated' : null,
    
                ]),
            );
    
            if (! ($cachedView = cache($cacheName))) {
    
                $stats = (new EpisodeModel())->getPodcastStats($this->podcast->id);
    
    
                    'metatags' => get_podcast_metatags($this->podcast, 'about'),
    
                    'podcast'  => $this->podcast,
                    'stats'    => $stats,
    
                // // if user is logged in then send to the authenticated activity view
    
                }
    
                $secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
                    $this->podcast->id,
                );
    
                return view('podcast/about', $data, [
    
                    'cache'      => $secondsToNextUnpublishedEpisode ?: DECADE,
    
                    'cache_name' => $cacheName,
                ]);
            }
    
        public function episodes(): string
    
            // Prevent analytics hit when authenticated
    
                $this->registerPodcastWebpageHit($this->podcast->id);
            }
    
            $yearQuery = $this->request->getGet('year');
            $seasonQuery = $this->request->getGet('season');
    
    
                $defaultQuery = (new PodcastModel())->getDefaultQuery($this->podcast->id);
    
                    if ($defaultQuery['type'] === 'season') {
    
                        $seasonQuery = $defaultQuery['data']['season_number'];
    
                    } elseif ($defaultQuery['type'] === 'year') {
    
                        $yearQuery = $defaultQuery['data']['year'];
                    }
    
                    "podcast#{$this->podcast->id}",
    
                    $yearQuery ? 'year' . $yearQuery : null,
    
                    $seasonQuery ? 'season' . $seasonQuery : null,
    
                    is_unlocked($this->podcast->handle) ? 'unlocked' : null,
    
                    auth()
                        ->loggedIn() ? 'authenticated' : null,
    
            if (! ($cachedView = cache($cacheName))) {
    
                $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'];
    
                            'type'               => 'year',
                            'value'              => $year['year'],
                            'label'              => $year['year'],
    
                            'number_of_episodes' => $year['number_of_episodes'],
                        ];
    
                        'number_of_episodes' => $year['number_of_episodes'],
    
                        'route'              => route_to('podcast-episodes', $this->podcast->handle) .
    
                            '?year=' .
                            $year['year'],
                        'is_active' => $isActive,
    
                    $isActive = $seasonQuery === $season['season_number'];
    
                            'value' => $season['season_number'],
    
                            'label' => lang('Podcast.season', [
                                'seasonNumber' => $season['season_number'],
                            ]),
                            'number_of_episodes' => $season['number_of_episodes'],
    
                        '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,
    
                    '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,
    
                $secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
    
                return view('podcast/episodes', $data, [
    
                    'cache'      => $secondsToNextUnpublishedEpisode ?: DECADE,
    
    
        public function episodeCollection(): Response
        {
            if ($this->podcast->type === 'serial') {
                // podcast is serial
    
                $episodes = model('EpisodeModel')
    
                    ->where('`published_at` <= UTC_TIMESTAMP()', null, false)
    
                    ->orderBy('season_number DESC, number ASC');
            } else {
    
                $episodes = model('EpisodeModel')
    
                    ->where('`published_at` <= UTC_TIMESTAMP()', 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());
        }
    
    
        public function links(): string
        {
            return view('podcast/links', [
                'metatags' => get_podcast_metatags($this->podcast, 'links'),
                'podcast'  => $this->podcast,
            ]);
        }