Fixes #6804 -- Clean up exceptions:
- Make more exceptions translated - Consolidate duplicate exception classes - Make public-facing exceptions friendlier (don't show "Exception on File LXX" except in console log)
This commit is contained in:
parent
afc1f2fde9
commit
c90b217e73
|
@ -40,10 +40,12 @@ return static function (RouteCollectorProxy $group) {
|
|||
|
||||
// On-Demand Streaming
|
||||
$group->get('/ondemand', Controller\Api\Stations\OnDemand\ListAction::class)
|
||||
->setName('api:stations:ondemand:list');
|
||||
->setName('api:stations:ondemand:list')
|
||||
->add(new Middleware\StationSupportsFeature(StationFeatures::OnDemand));
|
||||
|
||||
$group->get('/ondemand/download/{media_id}', Controller\Api\Stations\OnDemand\DownloadAction::class)
|
||||
->setName('api:stations:ondemand:download')
|
||||
->add(new Middleware\StationSupportsFeature(StationFeatures::OnDemand))
|
||||
->add(new Middleware\RateLimit('ondemand', 1, 2));
|
||||
|
||||
// Podcast Public Pages
|
||||
|
|
|
@ -38,7 +38,8 @@ return static function (RouteCollectorProxy $app) {
|
|||
->setName('public:manifest');
|
||||
|
||||
$group->get('/embed-requests', Controller\Frontend\PublicPages\RequestsAction::class)
|
||||
->setName('public:embedrequests');
|
||||
->setName('public:embedrequests')
|
||||
->add(new Middleware\StationSupportsFeature(App\Enums\StationFeatures::Requests));
|
||||
|
||||
$group->get('/playlist[.{format}]', Controller\Frontend\PublicPages\PlaylistAction::class)
|
||||
->setName('public:playlist');
|
||||
|
@ -50,7 +51,8 @@ return static function (RouteCollectorProxy $app) {
|
|||
->setName('public:dj');
|
||||
|
||||
$group->get('/ondemand[/{embed:embed}]', Controller\Frontend\PublicPages\OnDemandAction::class)
|
||||
->setName('public:ondemand');
|
||||
->setName('public:ondemand')
|
||||
->add(new Middleware\StationSupportsFeature(App\Enums\StationFeatures::OnDemand));
|
||||
|
||||
$group->get('/schedule[/{embed:embed}]', Controller\Frontend\PublicPages\ScheduleAction::class)
|
||||
->setName('public:schedule');
|
||||
|
|
|
@ -37,8 +37,9 @@ export default function installAxios(vueApp: App) {
|
|||
let notifyMessage = $gettext('An error occurred and your request could not be completed.');
|
||||
if (error.response) {
|
||||
// Request made and server responded
|
||||
notifyMessage = error.response.data.message;
|
||||
console.error(notifyMessage);
|
||||
const responseJson = error.response.data ?? {};
|
||||
notifyMessage = responseJson.message ?? notifyMessage;
|
||||
console.error(responseJson);
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received
|
||||
console.error(error.request);
|
||||
|
|
|
@ -36,7 +36,7 @@ abstract class AbstractFileAction implements SingleActionInterface
|
|||
->getFilesystem();
|
||||
|
||||
if (!$fs->fileExists($path)) {
|
||||
throw new NotFoundException(__('Backup not found.'));
|
||||
throw NotFoundException::file();
|
||||
}
|
||||
|
||||
return [$path, $fs];
|
||||
|
|
|
@ -6,7 +6,6 @@ namespace App\Controller\Api\Admin\Debug;
|
|||
|
||||
use App\Container\LoggerAwareTrait;
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Exception\StationUnsupportedException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Radio\Adapters;
|
||||
|
@ -32,11 +31,7 @@ final class TelnetAction implements SingleActionInterface
|
|||
$this->logger->pushHandler($testHandler);
|
||||
|
||||
$station = $request->getStation();
|
||||
$backend = $this->adapters->getBackendAdapter($station);
|
||||
|
||||
if (null === $backend) {
|
||||
throw new StationUnsupportedException();
|
||||
}
|
||||
$backend = $this->adapters->requireBackendAdapter($station);
|
||||
|
||||
$command = $request->getParam('command');
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ use App\Entity\StationMedia;
|
|||
use App\Http\ServerRequest;
|
||||
use App\Paginator;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use RuntimeException;
|
||||
|
||||
abstract class AbstractSearchableListAction implements SingleActionInterface
|
||||
{
|
||||
|
@ -31,10 +30,6 @@ abstract class AbstractSearchableListAction implements SingleActionInterface
|
|||
ServerRequest $request,
|
||||
array $playlists
|
||||
): Paginator {
|
||||
if (empty($playlists)) {
|
||||
throw new RuntimeException('This station has no qualifying playlists for this feature.');
|
||||
}
|
||||
|
||||
$station = $request->getStation();
|
||||
|
||||
$queryParams = $request->getQueryParams();
|
||||
|
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
|||
namespace App\Controller\Api\Stations\OnDemand;
|
||||
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Entity\Api\Error;
|
||||
use App\Entity\Repository\StationMediaRepository;
|
||||
use App\Flysystem\StationFilesystems;
|
||||
use App\Http\Response;
|
||||
|
@ -30,12 +29,6 @@ final class DownloadAction implements SingleActionInterface
|
|||
|
||||
$station = $request->getStation();
|
||||
|
||||
// Verify that the station supports on-demand streaming.
|
||||
if (!$station->getEnableOnDemand()) {
|
||||
return $response->withStatus(403)
|
||||
->withJson(new Error(403, __('This station does not support on-demand streaming.')));
|
||||
}
|
||||
|
||||
$media = $this->mediaRepo->requireByUniqueId($mediaId, $station);
|
||||
|
||||
$fsMedia = $this->stationFilesystems->getMediaFilesystem($station);
|
||||
|
|
|
@ -5,10 +5,10 @@ declare(strict_types=1);
|
|||
namespace App\Controller\Api\Stations\OnDemand;
|
||||
|
||||
use App\Controller\Api\Stations\AbstractSearchableListAction;
|
||||
use App\Entity\Api\Error;
|
||||
use App\Entity\Api\StationOnDemand;
|
||||
use App\Entity\Station;
|
||||
use App\Entity\StationMedia;
|
||||
use App\Exception\StationUnsupportedException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
@ -22,16 +22,12 @@ final class ListAction extends AbstractSearchableListAction
|
|||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
|
||||
// Verify that the station supports on-demand streaming.
|
||||
if (!$station->getEnableOnDemand()) {
|
||||
return $response->withStatus(403)
|
||||
->withJson(new Error(403, __('This station does not support on-demand streaming.')));
|
||||
$playlists = $this->getPlaylists($station);
|
||||
if (empty($playlists)) {
|
||||
throw StationUnsupportedException::onDemand();
|
||||
}
|
||||
|
||||
$paginator = $this->getPaginator(
|
||||
$request,
|
||||
$this->getPlaylists($station)
|
||||
);
|
||||
$paginator = $this->getPaginator($request, $playlists);
|
||||
|
||||
$router = $request->getRouter();
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@ declare(strict_types=1);
|
|||
namespace App\Controller\Api\Stations\Requests;
|
||||
|
||||
use App\Controller\Api\Stations\AbstractSearchableListAction;
|
||||
use App\Entity\Api\Error;
|
||||
use App\Entity\Api\StationRequest;
|
||||
use App\Entity\ApiGenerator\SongApiGenerator;
|
||||
use App\Entity\Station;
|
||||
use App\Entity\StationMedia;
|
||||
use App\Entity\StationPlaylist;
|
||||
use App\Exception\StationUnsupportedException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\OpenApi;
|
||||
|
@ -61,16 +61,12 @@ final class ListAction extends AbstractSearchableListAction
|
|||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
|
||||
// Verify that the station supports on-demand streaming.
|
||||
if (!$station->getEnableRequests()) {
|
||||
return $response->withStatus(403)
|
||||
->withJson(new Error(403, __('This station does not support requests.')));
|
||||
$playlists = $this->getPlaylists($station);
|
||||
if (empty($playlists)) {
|
||||
throw StationUnsupportedException::requests();
|
||||
}
|
||||
|
||||
$paginator = $this->getPaginator(
|
||||
$request,
|
||||
$this->getPlaylists($station)
|
||||
);
|
||||
$paginator = $this->getPaginator($request, $playlists);
|
||||
|
||||
$router = $request->getRouter();
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ use App\Controller\SingleActionInterface;
|
|||
use App\Entity\Api\Status;
|
||||
use App\Entity\Repository\StationRequestRepository;
|
||||
use App\Entity\User;
|
||||
use App\Exception;
|
||||
use App\Exception\InvalidRequestAttribute;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
|
@ -66,25 +65,18 @@ final class SubmitAction implements SingleActionInterface
|
|||
$user = null;
|
||||
}
|
||||
|
||||
$isAuthenticated = ($user instanceof User);
|
||||
$ip = $this->readSettings()->getIp($request);
|
||||
|
||||
try {
|
||||
$ip = $this->readSettings()->getIp($request);
|
||||
$this->requestRepo->submit(
|
||||
$station,
|
||||
$mediaId,
|
||||
($user instanceof User),
|
||||
$ip,
|
||||
$request->getHeaderLine('User-Agent')
|
||||
);
|
||||
|
||||
$this->requestRepo->submit(
|
||||
$station,
|
||||
$mediaId,
|
||||
$isAuthenticated,
|
||||
$ip,
|
||||
$request->getHeaderLine('User-Agent')
|
||||
);
|
||||
|
||||
return $response->withJson(
|
||||
new Status(true, __('Your request has been submitted and will be played soon.'))
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
return $response->withStatus(400)
|
||||
->withJson(new Status(false, $e->getMessage()));
|
||||
}
|
||||
return $response->withJson(
|
||||
new Status(true, __('Your request has been submitted and will be played soon.'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ use App\Container\EntityManagerAwareTrait;
|
|||
use App\Entity\Api\Error;
|
||||
use App\Entity\Api\StationServiceStatus;
|
||||
use App\Entity\Api\Status;
|
||||
use App\Exception\StationUnsupportedException;
|
||||
use App\Exception\Supervisor\NotRunningException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
|
@ -196,11 +195,7 @@ final class ServicesController
|
|||
$do = $params['do'] ?? 'restart';
|
||||
|
||||
$station = $request->getStation();
|
||||
$frontend = $this->adapters->getFrontendAdapter($station);
|
||||
|
||||
if (null === $frontend) {
|
||||
throw new StationUnsupportedException();
|
||||
}
|
||||
$frontend = $this->adapters->requireFrontendAdapter($station);
|
||||
|
||||
switch ($do) {
|
||||
case 'stop':
|
||||
|
@ -242,11 +237,7 @@ final class ServicesController
|
|||
$do = $params['do'] ?? 'restart';
|
||||
|
||||
$station = $request->getStation();
|
||||
$backend = $this->adapters->getBackendAdapter($station);
|
||||
|
||||
if (null === $backend) {
|
||||
throw new StationUnsupportedException();
|
||||
}
|
||||
$backend = $this->adapters->requireBackendAdapter($station);
|
||||
|
||||
switch ($do) {
|
||||
case 'skip':
|
||||
|
|
|
@ -6,7 +6,6 @@ namespace App\Controller\Api\Stations;
|
|||
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Entity\Api\Status;
|
||||
use App\Exception\StationUnsupportedException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Radio\Adapters;
|
||||
|
@ -28,11 +27,7 @@ final class UpdateMetadataAction implements SingleActionInterface
|
|||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
|
||||
$backend = $this->adapters->getBackendAdapter($station);
|
||||
|
||||
if (null === $backend) {
|
||||
throw new StationUnsupportedException();
|
||||
}
|
||||
$backend = $this->adapters->requireBackendAdapter($station);
|
||||
|
||||
$allowedMetaFields = [
|
||||
'title',
|
||||
|
|
|
@ -24,7 +24,7 @@ trait HasLogViewer
|
|||
clearstatcache();
|
||||
|
||||
if (!is_file($logPath)) {
|
||||
throw new NotFoundException('Log file not found!');
|
||||
throw NotFoundException::file();
|
||||
}
|
||||
|
||||
if (!$tailFile) {
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace App\Controller\Frontend\PWA;
|
|||
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Enums\SupportedThemes;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
@ -21,7 +21,7 @@ final class AppManifestAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
$customization = $request->getCustomization();
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Controller\Frontend\PublicPages;
|
||||
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\VueComponent\NowPlayingComponent;
|
||||
|
@ -26,7 +26,7 @@ final class HistoryAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
$view = $request->getView();
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Controller\Frontend\PublicPages;
|
||||
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Xml\Writer;
|
||||
|
@ -21,7 +21,7 @@ final class OEmbedAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
$format = $params['format'] ?? 'json';
|
||||
|
|
|
@ -6,8 +6,7 @@ namespace App\Controller\Frontend\PublicPages;
|
|||
|
||||
use App\Container\EntityManagerAwareTrait;
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\StationUnsupportedException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
@ -27,11 +26,7 @@ final class OnDemandAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
}
|
||||
|
||||
if (!$station->getEnableOnDemand()) {
|
||||
throw new StationUnsupportedException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
// Get list of custom fields.
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace App\Controller\Frontend\PublicPages;
|
|||
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Entity\Repository\CustomFieldRepository;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\VueComponent\NowPlayingComponent;
|
||||
|
@ -35,7 +35,7 @@ final class PlayerAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
// Build Vue props.
|
||||
|
|
|
@ -8,8 +8,7 @@ use App\Controller\SingleActionInterface;
|
|||
use App\Entity\PodcastEpisode;
|
||||
use App\Entity\Repository\PodcastEpisodeRepository;
|
||||
use App\Entity\Repository\PodcastRepository;
|
||||
use App\Exception\PodcastNotFoundException;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
@ -37,13 +36,13 @@ final class PodcastEpisodeAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
$podcast = $this->podcastRepository->fetchPodcastForStation($station, $podcastId);
|
||||
|
||||
if ($podcast === null) {
|
||||
throw new PodcastNotFoundException();
|
||||
throw NotFoundException::podcast();
|
||||
}
|
||||
|
||||
$episode = $this->episodeRepository->fetchEpisodeForStation($station, $episodeId);
|
||||
|
|
|
@ -8,8 +8,7 @@ use App\Controller\SingleActionInterface;
|
|||
use App\Entity\PodcastEpisode;
|
||||
use App\Entity\Repository\PodcastEpisodeRepository;
|
||||
use App\Entity\Repository\PodcastRepository;
|
||||
use App\Exception\PodcastNotFoundException;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
@ -34,13 +33,13 @@ final class PodcastEpisodesAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
$podcast = $this->podcastRepository->fetchPodcastForStation($station, $podcastId);
|
||||
|
||||
if ($podcast === null) {
|
||||
throw new PodcastNotFoundException();
|
||||
throw NotFoundException::podcast();
|
||||
}
|
||||
|
||||
$publishedEpisodes = $this->episodeRepository->fetchPublishedEpisodesForPodcast($podcast);
|
||||
|
|
|
@ -11,8 +11,7 @@ use App\Entity\PodcastEpisode;
|
|||
use App\Entity\Repository\PodcastRepository;
|
||||
use App\Entity\Repository\StationRepository;
|
||||
use App\Entity\Station;
|
||||
use App\Exception\PodcastNotFoundException;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Flysystem\StationFilesystems;
|
||||
use App\Http\Response;
|
||||
use App\Http\RouterInterface;
|
||||
|
@ -65,17 +64,17 @@ final class PodcastFeedAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
$podcast = $this->podcastRepository->fetchPodcastForStation($station, $podcastId);
|
||||
|
||||
if ($podcast === null) {
|
||||
throw new PodcastNotFoundException();
|
||||
throw NotFoundException::podcast();
|
||||
}
|
||||
|
||||
if (!$this->checkHasPublishedEpisodes($podcast)) {
|
||||
throw new PodcastNotFoundException();
|
||||
throw NotFoundException::podcast();
|
||||
}
|
||||
|
||||
$generatedRss = $this->generateRssFeed($podcast, $station, $request);
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace App\Controller\Frontend\PublicPages;
|
|||
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Entity\Repository\PodcastRepository;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
@ -26,7 +26,7 @@ final class PodcastsAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
$publishedPodcasts = $this->podcastRepository->fetchPublishedPodcastsForStation($station);
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace App\Controller\Frontend\PublicPages;
|
|||
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Entity\Repository\CustomFieldRepository;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
@ -26,7 +26,7 @@ final class RequestsAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
$router = $request->getRouter();
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Controller\Frontend\PublicPages;
|
||||
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
@ -23,7 +23,7 @@ final class ScheduleAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
$router = $request->getRouter();
|
||||
|
|
|
@ -5,8 +5,8 @@ declare(strict_types=1);
|
|||
namespace App\Controller\Frontend\PublicPages;
|
||||
|
||||
use App\Controller\SingleActionInterface;
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\StationUnsupportedException;
|
||||
use App\Enums\StationFeatures;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Radio\Adapters;
|
||||
|
@ -27,17 +27,12 @@ final class WebDjAction implements SingleActionInterface
|
|||
$station = $request->getStation();
|
||||
|
||||
if (!$station->getEnablePublicPage()) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
if (!$station->getEnableStreamers()) {
|
||||
throw new StationUnsupportedException();
|
||||
}
|
||||
StationFeatures::Streamers->assertSupportedForStation($station);
|
||||
|
||||
$backend = $this->adapters->getBackendAdapter($station);
|
||||
if (null === $backend) {
|
||||
throw new StationUnsupportedException();
|
||||
}
|
||||
$backend = $this->adapters->requireBackendAdapter($station);
|
||||
|
||||
$wssUrl = (string)$backend->getWebStreamingUrl($station, $request->getRouter()->getBaseUrl());
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ class Repository
|
|||
{
|
||||
$record = $this->find($id);
|
||||
if (null === $record) {
|
||||
throw new NotFoundException();
|
||||
throw NotFoundException::generic();
|
||||
}
|
||||
return $record;
|
||||
}
|
||||
|
|
|
@ -96,21 +96,22 @@ final class Error
|
|||
|
||||
$className = (new ReflectionClass($e))->getShortName();
|
||||
|
||||
$errorHeader = $className . ' at ' . $e->getFile() . ' L' . $e->getLine();
|
||||
$message = $errorHeader . ': ' . $e->getMessage();
|
||||
|
||||
if ($e instanceof Exception) {
|
||||
$messageFormatted = '<b>' . $errorHeader . ':</b> ' . $e->getFormattedMessage();
|
||||
$messageFormatted = $e->getFormattedMessage();
|
||||
$extraData = $e->getExtraData();
|
||||
} else {
|
||||
$messageFormatted = '<b>' . $errorHeader . ':</b> ' . $e->getMessage();
|
||||
$messageFormatted = $e->getMessage();
|
||||
$extraData = [];
|
||||
}
|
||||
|
||||
$extraData['class'] = $className;
|
||||
$extraData['file'] = $e->getFile();
|
||||
$extraData['line'] = $e->getLine();
|
||||
|
||||
if ($includeTrace) {
|
||||
$extraData['trace'] = $e->getTrace();
|
||||
}
|
||||
|
||||
return new self($code, $message, $messageFormatted, $extraData, $className);
|
||||
return new self($code, $e->getMessage(), $messageFormatted, $extraData, $className);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ abstract class AbstractStationBasedRepository extends Repository
|
|||
{
|
||||
$record = $this->findForStation($id, $station);
|
||||
if (null === $record) {
|
||||
throw new NotFoundException();
|
||||
throw NotFoundException::generic();
|
||||
}
|
||||
return $record;
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@ use App\Entity\PodcastEpisode;
|
|||
use App\Entity\PodcastMedia;
|
||||
use App\Entity\Station;
|
||||
use App\Entity\StorageLocation;
|
||||
use App\Exception\InvalidPodcastMediaFileException;
|
||||
use App\Exception\StorageLocationFullException;
|
||||
use App\Flysystem\ExtendedFilesystemInterface;
|
||||
use App\Media\AlbumArt;
|
||||
use App\Media\MetadataManager;
|
||||
use http\Exception\InvalidArgumentException;
|
||||
use League\Flysystem\UnableToDeleteFile;
|
||||
use League\Flysystem\UnableToRetrieveMetadata;
|
||||
|
||||
|
@ -152,8 +152,8 @@ final class PodcastEpisodeRepository extends Repository
|
|||
$metadata = $this->metadataManager->read($uploadPath);
|
||||
|
||||
if (!in_array($metadata->getMimeType(), ['audio/x-m4a', 'audio/mpeg'])) {
|
||||
throw new InvalidPodcastMediaFileException(
|
||||
'Invalid Podcast Media mime type: ' . $metadata->getMimeType()
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('Invalid Podcast Media mime type: %s', $metadata->getMimeType())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ final class StationMediaRepository extends Repository
|
|||
{
|
||||
$record = $this->findForStation($id, $station);
|
||||
if (null === $record) {
|
||||
throw new NotFoundException();
|
||||
throw NotFoundException::generic();
|
||||
}
|
||||
return $record;
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ final class StationMediaRepository extends Repository
|
|||
): StationMedia {
|
||||
$record = $this->findByUniqueId($uniqueId, $source);
|
||||
if (null === $record) {
|
||||
throw new NotFoundException();
|
||||
throw NotFoundException::generic();
|
||||
}
|
||||
return $record;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use App\Entity\Api\StationPlaylistQueue;
|
|||
use App\Entity\Station;
|
||||
use App\Entity\StationMedia;
|
||||
use App\Entity\StationRequest;
|
||||
use App\Enums\StationFeatures;
|
||||
use App\Exception;
|
||||
use App\Radio\AutoDJ;
|
||||
use App\Radio\Frontend\Blocklist\BlocklistParser;
|
||||
|
@ -62,27 +63,31 @@ final class StationRequestRepository extends AbstractStationBasedRepository
|
|||
string $userAgent
|
||||
): int {
|
||||
// Verify that the station supports requests.
|
||||
if (!$station->getEnableRequests()) {
|
||||
throw new Exception(__('This station does not accept requests currently.'));
|
||||
}
|
||||
StationFeatures::Requests->assertSupportedForStation($station);
|
||||
|
||||
// Forbid web crawlers from using this feature.
|
||||
$dd = $this->deviceDetector->parse($userAgent);
|
||||
|
||||
if ($dd->isBot) {
|
||||
throw new Exception(__('Search engine crawlers are not permitted to use this feature.'));
|
||||
throw Exception\CannotCompleteActionException::submitRequest(
|
||||
__('Search engine crawlers are not permitted to use this feature.')
|
||||
);
|
||||
}
|
||||
|
||||
// Check frontend blocklist and apply it to requests.
|
||||
if (!$this->blocklistParser->isAllowed($station, $ip, $userAgent)) {
|
||||
throw new Exception(__('You are not permitted to submit requests.'));
|
||||
throw Exception\CannotCompleteActionException::submitRequest(
|
||||
__('You are not permitted to submit requests.')
|
||||
);
|
||||
}
|
||||
|
||||
// Verify that Track ID exists with station.
|
||||
$mediaItem = $this->mediaRepo->requireByUniqueId($trackId, $station);
|
||||
|
||||
if (!$mediaItem->isRequestable()) {
|
||||
throw new Exception(__('The song ID you specified cannot be requested for this station.'));
|
||||
throw Exception\CannotCompleteActionException::submitRequest(
|
||||
__('This track is not requestable.')
|
||||
);
|
||||
}
|
||||
|
||||
// Check if the song is already enqueued as a request.
|
||||
|
@ -112,7 +117,7 @@ final class StationRequestRepository extends AbstractStationBasedRepository
|
|||
->getSingleScalarResult();
|
||||
|
||||
if ($recentRequests > 0) {
|
||||
throw new Exception(
|
||||
throw Exception\CannotCompleteActionException::submitRequest(
|
||||
__('You have submitted a request too recently! Please wait before submitting another one.')
|
||||
);
|
||||
}
|
||||
|
@ -158,7 +163,9 @@ final class StationRequestRepository extends AbstractStationBasedRepository
|
|||
}
|
||||
|
||||
if ($pendingRequest > 0) {
|
||||
throw new Exception(__('Duplicate request: this song was already requested and will play soon.'));
|
||||
throw Exception\CannotCompleteActionException::submitRequest(
|
||||
__('This song was already requested and will play soon.')
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -236,7 +243,7 @@ final class StationRequestRepository extends AbstractStationBasedRepository
|
|||
$isDuplicate = (null === $this->duplicatePrevention->getDistinctTrack([$eligibleTrack], $recentTracks));
|
||||
|
||||
if ($isDuplicate) {
|
||||
throw new Exception(
|
||||
throw Exception\CannotCompleteActionException::submitRequest(
|
||||
__('This song or artist has been played too recently. Wait a while before requesting it again.')
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Enums;
|
||||
|
||||
use App\Entity\Station;
|
||||
use App\Exception\StationUnsupportedException;
|
||||
|
||||
enum StationFeatures
|
||||
{
|
||||
|
@ -17,6 +18,7 @@ enum StationFeatures
|
|||
case Streamers;
|
||||
case Webhooks;
|
||||
case Podcasts;
|
||||
case OnDemand;
|
||||
case Requests;
|
||||
|
||||
public function supportedForStation(Station $station): bool
|
||||
|
@ -30,7 +32,24 @@ enum StationFeatures
|
|||
self::MountPoints => $station->getFrontendType()->supportsMounts(),
|
||||
self::HlsStreams => $backendEnabled && $station->getEnableHls(),
|
||||
self::Requests => $backendEnabled && $station->getEnableRequests(),
|
||||
self::OnDemand => $station->getEnableOnDemand(),
|
||||
self::Webhooks, self::Podcasts, self::RemoteRelays => true,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Station $station
|
||||
* @return void
|
||||
* @throws StationUnsupportedException
|
||||
*/
|
||||
public function assertSupportedForStation(Station $station): void
|
||||
{
|
||||
if (!$this->supportedForStation($station)) {
|
||||
throw match ($this) {
|
||||
self::Requests => StationUnsupportedException::requests(),
|
||||
self::OnDemand => StationUnsupportedException::onDemand(),
|
||||
default => StationUnsupportedException::generic(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,37 +5,28 @@ declare(strict_types=1);
|
|||
namespace App;
|
||||
|
||||
use Exception as PhpException;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
class Exception extends PhpException
|
||||
{
|
||||
/** @var string The logging severity of the exception. */
|
||||
protected string $loggerLevel;
|
||||
|
||||
/** @var array Any additional data that can be displayed in debugging. */
|
||||
protected array $extraData = [];
|
||||
|
||||
/** @var array Additional data supplied to the logger class when handling the exception. */
|
||||
protected array $loggingContext = [];
|
||||
|
||||
/** @var string|null */
|
||||
protected ?string $formattedMessage;
|
||||
|
||||
public function __construct(
|
||||
string $message = '',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::ERROR
|
||||
protected Level $loggerLevel = Level::Error
|
||||
) {
|
||||
parent::__construct($message, $code, $previous);
|
||||
|
||||
$this->loggerLevel = $loggerLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*/
|
||||
public function setMessage(string $message): void
|
||||
{
|
||||
$this->message = $message;
|
||||
|
@ -52,31 +43,22 @@ class Exception extends PhpException
|
|||
|
||||
/**
|
||||
* Set a display-formatted message (if one exists).
|
||||
*
|
||||
* @param string|null $message
|
||||
*/
|
||||
public function setFormattedMessage(?string $message): void
|
||||
{
|
||||
$this->formattedMessage = $message;
|
||||
}
|
||||
|
||||
public function getLoggerLevel(): string
|
||||
public function getLoggerLevel(): Level
|
||||
{
|
||||
return $this->loggerLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $loggerLevel
|
||||
*/
|
||||
public function setLoggerLevel(string $loggerLevel): void
|
||||
public function setLoggerLevel(Level $loggerLevel): void
|
||||
{
|
||||
$this->loggerLevel = $loggerLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $legend
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function addExtraData(int|string $legend, mixed $data): void
|
||||
{
|
||||
if (is_array($data)) {
|
||||
|
@ -92,18 +74,11 @@ class Exception extends PhpException
|
|||
return $this->extraData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $key
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function addLoggingContext(int|string $key, mixed $data): void
|
||||
{
|
||||
$this->loggingContext[$key] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getLoggingContext(): array
|
||||
{
|
||||
return $this->loggingContext;
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class BootstrapException extends Exception
|
||||
|
@ -14,7 +14,7 @@ final class BootstrapException extends Exception
|
|||
string $message = '',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::ALERT
|
||||
Level $loggerLevel = Level::Alert
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class CannotCompleteActionException extends Exception
|
||||
{
|
||||
public function __construct(
|
||||
string $message = 'Cannot complete action.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
||||
public static function submitRequest(string $reason): self
|
||||
{
|
||||
return new self(
|
||||
sprintf(
|
||||
__('Cannot submit request: %s'),
|
||||
$reason
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class CannotProcessMediaException extends Exception
|
||||
|
@ -16,7 +16,7 @@ final class CannotProcessMediaException extends Exception
|
|||
string $message = 'Cannot process media file.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::WARNING
|
||||
Level $loggerLevel = Level::Warning
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class CsrfValidationException extends Exception
|
||||
|
@ -14,7 +14,7 @@ final class CsrfValidationException extends Exception
|
|||
string $message = 'CSRF Validation Error',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Throwable;
|
||||
|
||||
final class InvalidPodcastMediaFileException extends Exception
|
||||
{
|
||||
public function __construct(
|
||||
string $message = 'Invalid Podcast Media mime type.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class InvalidRequestAttribute extends Exception
|
||||
|
@ -14,7 +14,7 @@ final class InvalidRequestAttribute extends Exception
|
|||
string $message = 'Invalid request attribute.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::DEBUG
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class NoFileUploadedException extends Exception
|
||||
|
@ -14,7 +14,7 @@ final class NoFileUploadedException extends Exception
|
|||
string $message = 'No file was uploaded.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class NotFoundException extends Exception
|
||||
|
@ -14,8 +14,28 @@ final class NotFoundException extends Exception
|
|||
string $message = 'Record not found.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::DEBUG
|
||||
Level $loggerLevel = Level::Debug
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
||||
public static function generic(): self
|
||||
{
|
||||
return new self(__('Record not found.'));
|
||||
}
|
||||
|
||||
public static function file(): self
|
||||
{
|
||||
return new self(__('File not found.'));
|
||||
}
|
||||
|
||||
public static function station(): self
|
||||
{
|
||||
return new self(__('Station not found.'));
|
||||
}
|
||||
|
||||
public static function podcast(): self
|
||||
{
|
||||
return new self(__('Podcast not found.'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class NotLoggedInException extends Exception
|
||||
|
@ -14,7 +14,7 @@ final class NotLoggedInException extends Exception
|
|||
string $message = 'Not logged in.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::DEBUG
|
||||
Level $loggerLevel = Level::Debug
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class PermissionDeniedException extends Exception
|
||||
|
@ -14,7 +14,7 @@ final class PermissionDeniedException extends Exception
|
|||
string $message = 'Permission denied.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Throwable;
|
||||
|
||||
final class PodcastNotFoundException extends Exception
|
||||
{
|
||||
public function __construct(
|
||||
string $message = 'Podcast not found.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class RateLimitExceededException extends Exception
|
||||
|
@ -14,7 +14,7 @@ final class RateLimitExceededException extends Exception
|
|||
string $message = 'You have exceeded the rate limit for this application.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Throwable;
|
||||
|
||||
final class StationNotFoundException extends Exception
|
||||
{
|
||||
public function __construct(
|
||||
string $message = 'Station not found.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class StationUnsupportedException extends Exception
|
||||
|
@ -14,8 +14,29 @@ final class StationUnsupportedException extends Exception
|
|||
string $message = 'This feature is not currently supported on this station.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
||||
public static function generic(): self
|
||||
{
|
||||
return new self(
|
||||
__('This station does not currently support this functionality.')
|
||||
);
|
||||
}
|
||||
|
||||
public static function onDemand(): self
|
||||
{
|
||||
return new self(
|
||||
__('This station does not currently support on-demand media.')
|
||||
);
|
||||
}
|
||||
|
||||
public static function requests(): self
|
||||
{
|
||||
return new self(
|
||||
__('This station does not currently accept requests.')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class StorageLocationFullException extends Exception
|
||||
|
@ -14,7 +14,7 @@ final class StorageLocationFullException extends Exception
|
|||
string $message = 'Storage location is full.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception\Supervisor;
|
||||
|
||||
use App\Exception\SupervisorException;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class AlreadyRunningException extends SupervisorException
|
||||
|
@ -14,7 +14,7 @@ final class AlreadyRunningException extends SupervisorException
|
|||
string $message = 'Process was already running.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception\Supervisor;
|
||||
|
||||
use App\Exception\SupervisorException;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Throwable;
|
||||
|
||||
final class NotRunningException extends SupervisorException
|
||||
|
@ -14,7 +14,7 @@ final class NotRunningException extends SupervisorException
|
|||
string $message = 'Process was not running yet.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Exception;
|
||||
|
||||
use App\Exception;
|
||||
use Psr\Log\LogLevel;
|
||||
use Monolog\Level;
|
||||
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||
use Throwable;
|
||||
|
||||
|
@ -17,7 +17,7 @@ final class ValidationException extends Exception
|
|||
string $message = 'Validation error.',
|
||||
int $code = 0,
|
||||
Throwable $previous = null,
|
||||
string $loggerLevel = LogLevel::INFO
|
||||
Level $loggerLevel = Level::Info
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $loggerLevel);
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ use App\Middleware\InjectSession;
|
|||
use App\Session\Flash;
|
||||
use App\View;
|
||||
use Mezzio\Session\Session;
|
||||
use Monolog\Level;
|
||||
use Monolog\Logger;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
use Slim\App;
|
||||
use Slim\Exception\HttpException;
|
||||
use Slim\Handlers\ErrorHandler as SlimErrorHandler;
|
||||
|
@ -33,7 +33,7 @@ final class ErrorHandler extends SlimErrorHandler
|
|||
|
||||
private bool $showDetailed = false;
|
||||
|
||||
private string $loggerLevel = LogLevel::ERROR;
|
||||
private Level $loggerLevel = Level::Error;
|
||||
|
||||
public function __construct(
|
||||
private readonly View $view,
|
||||
|
@ -59,7 +59,7 @@ final class ErrorHandler extends SlimErrorHandler
|
|||
if ($exception instanceof Exception) {
|
||||
$this->loggerLevel = $exception->getLoggerLevel();
|
||||
} elseif ($exception instanceof HttpException) {
|
||||
$this->loggerLevel = LogLevel::INFO;
|
||||
$this->loggerLevel = Level::Info;
|
||||
}
|
||||
|
||||
$this->showDetailed = $this->environment->showDetailedErrors();
|
||||
|
|
|
@ -10,7 +10,7 @@ use App\Entity\Repository\PodcastRepository;
|
|||
use App\Entity\Station;
|
||||
use App\Entity\User;
|
||||
use App\Enums\StationPermissions;
|
||||
use App\Exception\PodcastNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Exception;
|
||||
|
@ -44,7 +44,7 @@ final class RequirePublishedPodcastEpisodeMiddleware extends AbstractMiddleware
|
|||
$podcastId = $this->getPodcastIdFromRequest($request);
|
||||
|
||||
if ($podcastId === null || !$this->checkPodcastHasPublishedEpisodes($station, $podcastId)) {
|
||||
throw new PodcastNotFoundException();
|
||||
throw NotFoundException::podcast();
|
||||
}
|
||||
|
||||
$response = $handler->handle($request);
|
||||
|
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Middleware;
|
||||
|
||||
use App\Exception\StationNotFoundException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\ServerRequest;
|
||||
use Exception;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
@ -20,7 +20,7 @@ final class RequireStation extends AbstractMiddleware
|
|||
try {
|
||||
$request->getStation();
|
||||
} catch (Exception) {
|
||||
throw new StationNotFoundException();
|
||||
throw NotFoundException::station();
|
||||
}
|
||||
|
||||
return $handler->handle($request);
|
||||
|
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
|||
namespace App\Middleware;
|
||||
|
||||
use App\Enums\StationFeatures;
|
||||
use App\Exception;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
@ -19,9 +18,7 @@ final class StationSupportsFeature extends AbstractMiddleware
|
|||
|
||||
public function __invoke(ServerRequest $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
if (!$this->feature->supportedForStation($request->getStation())) {
|
||||
throw new Exception\StationUnsupportedException();
|
||||
}
|
||||
$this->feature->assertSupportedForStation($request->getStation());
|
||||
|
||||
return $handler->handle($request);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use App\Container\ContainerAwareTrait;
|
|||
use App\Entity\Station;
|
||||
use App\Entity\StationRemote;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Exception\StationUnsupportedException;
|
||||
use App\Radio\Backend\Liquidsoap;
|
||||
use App\Radio\Enums\AdapterTypeInterface;
|
||||
use App\Radio\Enums\BackendAdapters;
|
||||
|
@ -30,6 +31,20 @@ final class Adapters
|
|||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws StationUnsupportedException
|
||||
*/
|
||||
public function requireFrontendAdapter(Station $station): Frontend\AbstractFrontend
|
||||
{
|
||||
$frontend = $this->getFrontendAdapter($station);
|
||||
|
||||
if (null === $frontend) {
|
||||
throw StationUnsupportedException::generic();
|
||||
}
|
||||
|
||||
return $frontend;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $checkInstalled
|
||||
* @return mixed[]
|
||||
|
@ -48,6 +63,20 @@ final class Adapters
|
|||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws StationUnsupportedException
|
||||
*/
|
||||
public function requireBackendAdapter(Station $station): Liquidsoap
|
||||
{
|
||||
$backend = $this->getBackendAdapter($station);
|
||||
|
||||
if (null === $backend) {
|
||||
throw StationUnsupportedException::generic();
|
||||
}
|
||||
|
||||
return $backend;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $checkInstalled
|
||||
* @return mixed[]
|
||||
|
@ -64,7 +93,9 @@ final class Adapters
|
|||
return $this->di->get($className);
|
||||
}
|
||||
|
||||
throw new NotFoundException('Adapter not found: ' . $className);
|
||||
throw new NotFoundException(
|
||||
sprintf('Adapter not found: %s', $className)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue