Rewire public controllers to support playlist sourced media.

This commit is contained in:
Buster Neece 2024-02-22 14:51:29 -06:00
parent d08235a8da
commit b0ab0916ae
No known key found for this signature in database
5 changed files with 68 additions and 27 deletions

View File

@ -8,6 +8,7 @@ use App\Container\EntityManagerAwareTrait;
use App\Controller\Api\Traits\CanSearchResults;
use App\Controller\SingleActionInterface;
use App\Entity\ApiGenerator\PodcastEpisodeApiGenerator;
use App\Entity\Enums\PodcastSources;
use App\Entity\PodcastEpisode;
use App\Http\Response;
use App\Http\ServerRequest;
@ -33,11 +34,16 @@ final class ListEpisodesAction implements SingleActionInterface
->from(PodcastEpisode::class, 'e')
->join('e.podcast', 'p')
->leftJoin('e.media', 'pm')
->leftJoin('e.playlist_media', 'sm')
->where('e.podcast = :podcast')
->setParameter('podcast', $podcast)
->andWhere('e.publish_at IS NULL OR e.publish_at <= :publishTime')
->setParameter('publishTime', time())
->andWhere('pm.id IS NOT NULL')
->andWhere(
'(p.source = :sourceManual AND pm.id IS NOT NULL) OR (p.source = :sourcePlaylist AND sm.id IS NOT NULL)'
)
->setParameter('sourceManual', PodcastSources::Manual->value)
->setParameter('sourcePlaylist', PodcastSources::Playlist->value)
->orderBy('e.publish_at', 'DESC');
$queryBuilder = $this->searchQueryBuilder(

View File

@ -7,6 +7,7 @@ namespace App\Controller\Api\Stations\Podcasts\Episodes\Media;
use App\Controller\SingleActionInterface;
use App\Entity\Api\Error;
use App\Entity\Api\Status;
use App\Entity\Enums\PodcastSources;
use App\Entity\PodcastEpisode;
use App\Entity\PodcastMedia;
use App\Entity\Repository\PodcastEpisodeRepository;
@ -14,6 +15,7 @@ use App\Http\Response;
use App\Http\ServerRequest;
use App\OpenApi;
use App\Utilities\Types;
use InvalidArgumentException;
use OpenApi\Attributes as OA;
use Psr\Http\Message\ResponseInterface;
@ -59,12 +61,14 @@ final class DeleteMediaAction implements SingleActionInterface
Response $response,
array $params
): ResponseInterface {
$episodeId = Types::string($params['episode_id'] ?? null);
$podcast = $request->getPodcast();
$episode = $this->episodeRepo->fetchEpisodeForPodcast(
$request->getPodcast(),
$episodeId
);
if ($podcast->getSource() !== PodcastSources::Manual) {
throw new InvalidArgumentException('Media cannot be manually set on this podcast.');
}
$episodeId = Types::string($params['episode_id'] ?? null);
$episode = $this->episodeRepo->fetchEpisodeForPodcast($podcast, $episodeId);
if (!($episode instanceof PodcastEpisode)) {
return $response->withStatus(404)

View File

@ -6,9 +6,11 @@ namespace App\Controller\Api\Stations\Podcasts\Episodes\Media;
use App\Controller\SingleActionInterface;
use App\Entity\Api\Error;
use App\Entity\Enums\PodcastSources;
use App\Entity\PodcastEpisode;
use App\Entity\PodcastMedia;
use App\Entity\Repository\PodcastEpisodeRepository;
use App\Entity\StationMedia;
use App\Flysystem\StationFilesystems;
use App\Http\Response;
use App\Http\ServerRequest;
@ -68,26 +70,46 @@ final class GetMediaAction implements SingleActionInterface
$episodeId = Types::string($params['episode_id'] ?? null);
$station = $request->getStation();
$podcast = $request->getPodcast();
$episode = $this->episodeRepo->fetchEpisodeForPodcast(
$request->getPodcast(),
$podcast,
$episodeId
);
if ($episode instanceof PodcastEpisode) {
$podcastMedia = $episode->getMedia();
switch ($podcast->getSource()) {
case PodcastSources::Playlist:
$playlistMedia = $episode->getPlaylistMedia();
if ($podcastMedia instanceof PodcastMedia) {
$fsPodcasts = $this->stationFilesystems->getPodcastsFilesystem($station);
if ($playlistMedia instanceof StationMedia) {
$fsMedia = $this->stationFilesystems->getMediaFilesystem($station);
$path = $podcastMedia->getPath();
set_time_limit(600);
return $response->streamFilesystemFile(
$fsMedia,
$playlistMedia->getPath()
);
}
break;
if ($fsPodcasts->fileExists($path)) {
return $response->streamFilesystemFile(
$fsPodcasts,
$path,
$podcastMedia->getOriginalName()
);
}
case PodcastSources::Manual:
$podcastMedia = $episode->getMedia();
if ($podcastMedia instanceof PodcastMedia) {
$fsPodcasts = $this->stationFilesystems->getPodcastsFilesystem($station);
$path = $podcastMedia->getPath();
if ($fsPodcasts->fileExists($path)) {
return $response->streamFilesystemFile(
$fsPodcasts,
$path,
$podcastMedia->getOriginalName()
);
}
}
break;
}
}

View File

@ -7,6 +7,7 @@ namespace App\Controller\Api\Stations\Podcasts\Episodes\Media;
use App\Controller\SingleActionInterface;
use App\Entity\Api\Error;
use App\Entity\Api\Status;
use App\Entity\Enums\PodcastSources;
use App\Entity\Repository\PodcastEpisodeRepository;
use App\Flysystem\StationFilesystems;
use App\Http\Response;
@ -14,6 +15,7 @@ use App\Http\ServerRequest;
use App\OpenApi;
use App\Service\Flow;
use App\Utilities\Types;
use InvalidArgumentException;
use OpenApi\Attributes as OA;
use Psr\Http\Message\ResponseInterface;
@ -60,20 +62,22 @@ final class PostMediaAction implements SingleActionInterface
Response $response,
array $params
): ResponseInterface {
$episodeId = Types::stringOrNull($params['episode_id'] ?? null, true);
$podcast = $request->getPodcast();
$station = $request->getStation();
if ($podcast->getSource() !== PodcastSources::Manual) {
throw new InvalidArgumentException('Media cannot be manually set on this podcast.');
}
$episodeId = Types::stringOrNull($params['episode_id'] ?? null, true);
$flowResponse = Flow::process($request, $response, $station->getRadioTempDir());
if ($flowResponse instanceof ResponseInterface) {
return $flowResponse;
}
if (null !== $episodeId) {
$episode = $this->episodeRepo->fetchEpisodeForPodcast(
$request->getPodcast(),
$episodeId
);
$episode = $this->episodeRepo->fetchEpisodeForPodcast($podcast, $episodeId);
if (null === $episode) {
return $response->withStatus(404)

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Entity\Repository;
use App\Doctrine\Repository;
use App\Entity\Enums\PodcastSources;
use App\Entity\Podcast;
use App\Entity\Station;
use App\Exception\StorageLocationFullException;
@ -47,11 +48,15 @@ final class PodcastRepository extends Repository
SELECT DISTINCT p.id
FROM App\Entity\PodcastEpisode pe
JOIN pe.podcast p
JOIN pe.media pm
WHERE pm.id IS NOT NULL
AND (pe.publish_at IS NULL OR pe.publish_at <= :time)
LEFT JOIN pe.media pm
LEFT JOIN pe.playlist_media sm
WHERE
((p.source = :sourceManual AND pm.id IS NOT NULL) OR (p.source = :sourcePlaylist AND sm.id IS NOT NULL))
AND (pe.publish_at IS NULL OR pe.publish_at <= :time)
DQL
)->setParameter('time', time())
->setParameter('sourceManual', PodcastSources::Manual->value)
->setParameter('sourcePlaylist', PodcastSources::Playlist->value)
->enableResultCache(60, 'podcast_ids_' . $station->getIdRequired())
->getSingleColumnResult();
}