Bug fixes, Repo and CustomAsset cleanup.
This commit is contained in:
parent
3c1bec857b
commit
b6767e1bc3
|
@ -10,11 +10,6 @@ use Psr\Http\Message\UriInterface;
|
|||
|
||||
abstract class AbstractCustomAsset implements CustomAssetInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected Environment $environment
|
||||
) {
|
||||
}
|
||||
|
||||
abstract protected function getPattern(): string;
|
||||
|
||||
abstract protected function getDefaultUrl(): string;
|
||||
|
@ -22,7 +17,7 @@ abstract class AbstractCustomAsset implements CustomAssetInterface
|
|||
public function getPath(): string
|
||||
{
|
||||
$pattern = sprintf($this->getPattern(), '');
|
||||
return $this->environment->getUploadsDirectory() . '/' . $pattern;
|
||||
return Environment::getInstance()->getUploadsDirectory() . '/' . $pattern;
|
||||
}
|
||||
|
||||
public function getUrl(): string
|
||||
|
@ -32,7 +27,7 @@ abstract class AbstractCustomAsset implements CustomAssetInterface
|
|||
$pattern = $this->getPattern();
|
||||
$mtime = filemtime($path);
|
||||
|
||||
return $this->environment->getAssetUrl() . self::UPLOADS_URL_PREFIX . '/' . sprintf(
|
||||
return Environment::getInstance()->getAssetUrl() . self::UPLOADS_URL_PREFIX . '/' . sprintf(
|
||||
$pattern,
|
||||
'.' . $mtime
|
||||
);
|
||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Assets;
|
||||
|
||||
use App\Environment;
|
||||
use Intervention\Image\Constraint;
|
||||
use Intervention\Image\Image;
|
||||
|
||||
|
@ -16,7 +17,7 @@ class AlbumArtCustomAsset extends AbstractCustomAsset
|
|||
|
||||
protected function getDefaultUrl(): string
|
||||
{
|
||||
return $this->environment->getAssetUrl() . '/img/generic_song.jpg';
|
||||
return Environment::getInstance()->getAssetUrl() . '/img/generic_song.jpg';
|
||||
}
|
||||
|
||||
public function upload(Image $image): void
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Assets;
|
||||
|
||||
use App\Environment;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class AssetFactory
|
||||
{
|
||||
public const TYPE_ALBUM_ART = 'album_art';
|
||||
public const TYPE_BACKGROUND = 'background';
|
||||
public const TYPE_BROWSER_ICON = 'browser_icon';
|
||||
|
||||
public static function createAlbumArt(Environment $environment): AlbumArtCustomAsset
|
||||
{
|
||||
return new AlbumArtCustomAsset($environment);
|
||||
}
|
||||
|
||||
public static function createBackground(Environment $environment): BackgroundCustomAsset
|
||||
{
|
||||
return new BackgroundCustomAsset($environment);
|
||||
}
|
||||
|
||||
public static function createBrowserIcon(Environment $environment): BrowserIconCustomAsset
|
||||
{
|
||||
return new BrowserIconCustomAsset($environment);
|
||||
}
|
||||
|
||||
public static function createForType(Environment $environment, string $type): CustomAssetInterface
|
||||
{
|
||||
return match ($type) {
|
||||
self::TYPE_ALBUM_ART => self::createAlbumArt($environment),
|
||||
self::TYPE_BACKGROUND => self::createBackground($environment),
|
||||
self::TYPE_BROWSER_ICON => self::createBrowserIcon($environment),
|
||||
default => throw new InvalidArgumentException('Invalid type specified.')
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
// phpcs:ignoreFile
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Assets;
|
||||
|
||||
enum AssetTypes: string
|
||||
{
|
||||
case AlbumArt = 'album_art';
|
||||
case Background = 'background';
|
||||
case BrowserIcon = 'browser_icon';
|
||||
|
||||
public function createObject(): CustomAssetInterface
|
||||
{
|
||||
return match ($this) {
|
||||
self::AlbumArt => new AlbumArtCustomAsset(),
|
||||
self::Background => new BackgroundCustomAsset(),
|
||||
self::BrowserIcon => new BrowserIconCustomAsset(),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Assets;
|
||||
|
||||
use App\Environment;
|
||||
use Intervention\Image\Constraint;
|
||||
use Intervention\Image\Image;
|
||||
|
||||
|
@ -16,7 +17,7 @@ class BackgroundCustomAsset extends AbstractCustomAsset
|
|||
|
||||
protected function getDefaultUrl(): string
|
||||
{
|
||||
return $this->environment->getAssetUrl() . '/img/hexbg.png';
|
||||
return Environment::getInstance()->getAssetUrl() . '/img/hexbg.png';
|
||||
}
|
||||
|
||||
public function upload(Image $image): void
|
||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Assets;
|
||||
|
||||
use App\Environment;
|
||||
use Intervention\Image\Image;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
|
@ -34,13 +35,15 @@ class BrowserIconCustomAsset extends AbstractCustomAsset
|
|||
|
||||
protected function getDefaultUrl(): string
|
||||
{
|
||||
$assetUrl = $this->environment->getAssetUrl();
|
||||
return $assetUrl . '/icons/' . $this->environment->getAppEnvironmentEnum()->value . '/original.png';
|
||||
$env = Environment::getInstance();
|
||||
|
||||
$assetUrl = $env->getAssetUrl();
|
||||
return $assetUrl . '/icons/' . $env->getAppEnvironmentEnum()->value . '/original.png';
|
||||
}
|
||||
|
||||
public function upload(Image $image): void
|
||||
{
|
||||
$uploadsDir = $this->environment->getUploadsDirectory() . '/browser_icon';
|
||||
$uploadsDir = Environment::getInstance()->getUploadsDirectory() . '/browser_icon';
|
||||
(new Filesystem())->mkdir($uploadsDir);
|
||||
|
||||
$newImage = clone $image;
|
||||
|
@ -56,15 +59,16 @@ class BrowserIconCustomAsset extends AbstractCustomAsset
|
|||
|
||||
public function delete(): void
|
||||
{
|
||||
$uploadsDir = $this->environment->getUploadsDirectory() . '/browser_icon';
|
||||
$uploadsDir = Environment::getInstance()->getUploadsDirectory() . '/browser_icon';
|
||||
(new Filesystem())->remove($uploadsDir);
|
||||
}
|
||||
|
||||
public function getUrlForSize(int $size): string
|
||||
{
|
||||
$assetUrl = $this->environment->getAssetUrl();
|
||||
$env = Environment::getInstance();
|
||||
$assetUrl = $env->getAssetUrl();
|
||||
|
||||
$uploadsDir = $this->environment->getUploadsDirectory();
|
||||
$uploadsDir = $env->getUploadsDirectory();
|
||||
$iconPath = $uploadsDir . '/browser_icon/' . $size . '.png';
|
||||
|
||||
if (is_file($iconPath)) {
|
||||
|
@ -72,6 +76,6 @@ class BrowserIconCustomAsset extends AbstractCustomAsset
|
|||
return $assetUrl . '/uploads/browser_icon/' . $size . '.' . $mtime . '.png';
|
||||
}
|
||||
|
||||
return $assetUrl . '/icons/' . $this->environment->getAppEnvironmentEnum()->value . '/' . $size . '.png';
|
||||
return $assetUrl . '/icons/' . $env->getAppEnvironmentEnum()->value . '/' . $size . '.png';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Assets\AssetFactory;
|
||||
use App\Assets\AssetTypes;
|
||||
use App\Entity\Settings;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
|
@ -28,13 +28,13 @@ final class BrandingAction
|
|||
'group' => Settings::GROUP_BRANDING,
|
||||
]),
|
||||
'browserIconApiUrl' => (string)$router->named('api:admin:custom_assets', [
|
||||
'type' => AssetFactory::TYPE_BROWSER_ICON,
|
||||
'type' => AssetTypes::BrowserIcon->value,
|
||||
]),
|
||||
'backgroundApiUrl' => (string)$router->named('api:admin:custom_assets', [
|
||||
'type' => AssetFactory::TYPE_BACKGROUND,
|
||||
'type' => AssetTypes::Background->value,
|
||||
]),
|
||||
'albumArtApiUrl' => (string)$router->named('api:admin:custom_assets', [
|
||||
'type' => AssetFactory::TYPE_ALBUM_ART,
|
||||
'type' => AssetTypes::AlbumArt->value,
|
||||
]),
|
||||
],
|
||||
);
|
||||
|
|
|
@ -89,7 +89,7 @@ final class LogsController extends AbstractLogViewerController
|
|||
public function viewAction(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
string|int $station_id,
|
||||
string $station_id,
|
||||
string $log
|
||||
): ResponseInterface {
|
||||
if ('global' === $station_id) {
|
||||
|
|
|
@ -4,27 +4,20 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Admin\CustomAssets;
|
||||
|
||||
use App\Assets\AssetFactory;
|
||||
use App\Assets\AssetTypes;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class DeleteCustomAssetAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Environment $environment,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
string $type
|
||||
): ResponseInterface {
|
||||
$customAsset = AssetFactory::createForType($this->environment, $type);
|
||||
|
||||
$customAsset = AssetTypes::from($type)->createObject();
|
||||
$customAsset->delete();
|
||||
|
||||
return $response->withJson(Entity\Api\Status::success());
|
||||
|
|
|
@ -4,25 +4,19 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Admin\CustomAssets;
|
||||
|
||||
use App\Assets\AssetFactory;
|
||||
use App\Environment;
|
||||
use App\Assets\AssetTypes;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class GetCustomAssetAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Environment $environment,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
string $type
|
||||
): ResponseInterface {
|
||||
$customAsset = AssetFactory::createForType($this->environment, $type);
|
||||
$customAsset = AssetTypes::from($type)->createObject();
|
||||
|
||||
return $response->withJson(
|
||||
[
|
||||
|
|
|
@ -4,9 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Admin\CustomAssets;
|
||||
|
||||
use App\Assets\AssetFactory;
|
||||
use App\Assets\AssetTypes;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Media\AlbumArt;
|
||||
|
@ -15,17 +14,12 @@ use Psr\Http\Message\ResponseInterface;
|
|||
|
||||
final class PostCustomAssetAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Environment $environment
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
string $type
|
||||
): ResponseInterface {
|
||||
$customAsset = AssetFactory::createForType($this->environment, $type);
|
||||
$customAsset = AssetTypes::from($type)->createObject();
|
||||
|
||||
$flowResponse = Flow::process($request, $response);
|
||||
if ($flowResponse instanceof ResponseInterface) {
|
||||
|
|
|
@ -53,12 +53,7 @@ final class DeleteArtAction
|
|||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
|
||||
$media = $this->mediaRepo->findForStation($media_id, $station);
|
||||
if (!($media instanceof Entity\StationMedia)) {
|
||||
return $response->withStatus(404)
|
||||
->withJson(Entity\Api\Error::notFound());
|
||||
}
|
||||
|
||||
$media = $this->mediaRepo->requireForStation($media_id, $station);
|
||||
$this->mediaRepo->removeAlbumArt($media);
|
||||
|
||||
return $response->withJson(Entity\Api\Status::deleted());
|
||||
|
|
|
@ -56,11 +56,7 @@ final class PostArtAction
|
|||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
|
||||
$media = $this->mediaRepo->findForStation($media_id, $station);
|
||||
if (!($media instanceof Entity\StationMedia)) {
|
||||
return $response->withStatus(404)
|
||||
->withJson(Entity\Api\Error::notFound());
|
||||
}
|
||||
$media = $this->mediaRepo->requireForStation($media_id, $station);
|
||||
|
||||
$flowResponse = Flow::process($request, $response, $station->getRadioTempDir());
|
||||
if ($flowResponse instanceof ResponseInterface) {
|
||||
|
|
|
@ -27,12 +27,7 @@ final class PlayAction
|
|||
|
||||
$station = $request->getStation();
|
||||
|
||||
$media = $this->mediaRepo->findForStation($id, $station);
|
||||
|
||||
if (!$media instanceof Entity\StationMedia) {
|
||||
return $response->withStatus(404)
|
||||
->withJson(Entity\Api\Error::notFound());
|
||||
}
|
||||
$media = $this->mediaRepo->requireForStation($id, $station);
|
||||
|
||||
$fsMedia = (new StationFilesystems($station))->getMediaFilesystem();
|
||||
|
||||
|
|
|
@ -47,13 +47,8 @@ final class DeleteIntroAction
|
|||
string $id
|
||||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
$mount = $this->mountRepo->findForStation($id, $station);
|
||||
|
||||
if (null === $mount) {
|
||||
return $response->withStatus(404)
|
||||
->withJson(Entity\Api\Error::notFound());
|
||||
}
|
||||
|
||||
$mount = $this->mountRepo->requireForStation($id, $station);
|
||||
$this->mountRepo->clearIntro($mount);
|
||||
|
||||
return $response->withJson(Entity\Api\Status::deleted());
|
||||
|
|
|
@ -55,12 +55,7 @@ final class PostIntroAction
|
|||
}
|
||||
|
||||
if (null !== $id) {
|
||||
$mount = $this->mountRepo->findForStation($id, $station);
|
||||
if (null === $mount) {
|
||||
return $response->withStatus(404)
|
||||
->withJson(Entity\Api\Error::notFound());
|
||||
}
|
||||
|
||||
$mount = $this->mountRepo->requireForStation($id, $station);
|
||||
$this->mountRepo->setIntro($mount, $flowResponse);
|
||||
|
||||
return $response->withJson(Entity\Api\Status::updated());
|
||||
|
|
|
@ -31,12 +31,7 @@ final class DownloadAction
|
|||
->withJson(new Entity\Api\Error(403, __('This station does not support on-demand streaming.')));
|
||||
}
|
||||
|
||||
$media = $this->mediaRepo->findByUniqueId($media_id, $station);
|
||||
|
||||
if (!($media instanceof Entity\StationMedia)) {
|
||||
return $response->withStatus(404)
|
||||
->withJson(Entity\Api\Error::notFound());
|
||||
}
|
||||
$media = $this->mediaRepo->requireByUniqueId($media_id, $station);
|
||||
|
||||
$fsMedia = (new StationFilesystems($station))->getMediaFilesystem();
|
||||
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Api\Stations\Playlists;
|
||||
|
||||
use App\Entity;
|
||||
use App\Exception\NotFoundException;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
abstract class AbstractPlaylistsAction
|
||||
{
|
||||
public function __construct(
|
||||
protected EntityManagerInterface $em
|
||||
) {
|
||||
}
|
||||
|
||||
protected function requireRecord(Entity\Station $station, int|string $id): Entity\StationPlaylist
|
||||
{
|
||||
$record = $this->em->getRepository(Entity\StationPlaylist::class)->findOneBy(
|
||||
[
|
||||
'station' => $station,
|
||||
'id' => (int)$id,
|
||||
]
|
||||
);
|
||||
|
||||
if (!$record instanceof Entity\StationPlaylist) {
|
||||
throw new NotFoundException(__('Playlist not found.'));
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
}
|
|
@ -4,22 +4,34 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Playlists;
|
||||
|
||||
use App\Entity;
|
||||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Entity\Api\Status;
|
||||
use App\Entity\Repository\StationPlaylistRepository;
|
||||
use App\Entity\StationPlaylist;
|
||||
use App\Entity\StationPlaylistFolder;
|
||||
use App\Entity\StationPlaylistMedia;
|
||||
use App\Entity\StationSchedule;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use DeepCopy;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class CloneAction extends AbstractPlaylistsAction
|
||||
final class CloneAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly StationPlaylistRepository $playlistRepo,
|
||||
private readonly ReloadableEntityManagerInterface $em,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
string $station_id,
|
||||
string $id
|
||||
): ResponseInterface {
|
||||
$record = $this->requireRecord($request->getStation(), $id);
|
||||
$record = $this->playlistRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
$data = (array)$request->getParsedBody();
|
||||
|
||||
|
@ -43,10 +55,10 @@ final class CloneAction extends AbstractPlaylistsAction
|
|||
);
|
||||
$copier->addFilter(
|
||||
new DeepCopy\Filter\KeepFilter(),
|
||||
new DeepCopy\Matcher\PropertyMatcher(Entity\StationPlaylistMedia::class, 'media')
|
||||
new DeepCopy\Matcher\PropertyMatcher(StationPlaylistMedia::class, 'media')
|
||||
);
|
||||
|
||||
/** @var Entity\StationPlaylist $newRecord */
|
||||
/** @var StationPlaylist $newRecord */
|
||||
$newRecord = $copier->copy($record);
|
||||
|
||||
$newRecord->setName($data['name'] ?? ($record->getName() . ' - Copy'));
|
||||
|
@ -57,7 +69,7 @@ final class CloneAction extends AbstractPlaylistsAction
|
|||
|
||||
if (in_array('schedule', $toClone, true)) {
|
||||
foreach ($record->getScheduleItems() as $oldScheduleItem) {
|
||||
/** @var Entity\StationSchedule $newScheduleItem */
|
||||
/** @var StationSchedule $newScheduleItem */
|
||||
$newScheduleItem = $copier->copy($oldScheduleItem);
|
||||
$newScheduleItem->setPlaylist($newRecord);
|
||||
|
||||
|
@ -67,14 +79,14 @@ final class CloneAction extends AbstractPlaylistsAction
|
|||
|
||||
if (in_array('media', $toClone, true)) {
|
||||
foreach ($record->getFolders() as $oldPlaylistFolder) {
|
||||
/** @var Entity\StationPlaylistFolder $newPlaylistFolder */
|
||||
/** @var StationPlaylistFolder $newPlaylistFolder */
|
||||
$newPlaylistFolder = $copier->copy($oldPlaylistFolder);
|
||||
$newPlaylistFolder->setPlaylist($newRecord);
|
||||
$this->em->persist($newPlaylistFolder);
|
||||
}
|
||||
|
||||
foreach ($record->getMediaItems() as $oldMediaItem) {
|
||||
/** @var Entity\StationPlaylistMedia $newMediaItem */
|
||||
/** @var StationPlaylistMedia $newMediaItem */
|
||||
$newMediaItem = $copier->copy($oldMediaItem);
|
||||
|
||||
$newMediaItem->setPlaylist($newRecord);
|
||||
|
@ -84,6 +96,6 @@ final class CloneAction extends AbstractPlaylistsAction
|
|||
|
||||
$this->em->flush();
|
||||
|
||||
return $response->withJson(Entity\Api\Status::created());
|
||||
return $response->withJson(Status::created());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,19 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Playlists;
|
||||
|
||||
use App\Entity;
|
||||
use App\Entity\Api\Status;
|
||||
use App\Entity\Repository\StationPlaylistMediaRepository;
|
||||
use App\Entity\Repository\StationPlaylistRepository;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class DeleteQueueAction extends AbstractPlaylistsAction
|
||||
final class DeleteQueueAction
|
||||
{
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
private readonly Entity\Repository\StationPlaylistMediaRepository $spmRepo,
|
||||
private readonly StationPlaylistRepository $playlistRepo,
|
||||
private readonly StationPlaylistMediaRepository $spmRepo,
|
||||
) {
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
|
@ -25,12 +25,12 @@ final class DeleteQueueAction extends AbstractPlaylistsAction
|
|||
string $station_id,
|
||||
string $id
|
||||
): ResponseInterface {
|
||||
$record = $this->requireRecord($request->getStation(), $id);
|
||||
$record = $this->playlistRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
$this->spmRepo->resetQueue($record);
|
||||
|
||||
return $response->withJson(
|
||||
new Entity\Api\Status(
|
||||
new Status(
|
||||
true,
|
||||
__('Playlist queue cleared.')
|
||||
)
|
||||
|
|
|
@ -4,13 +4,19 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Playlists;
|
||||
|
||||
use App\Entity\Repository\StationPlaylistRepository;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class ExportAction extends AbstractPlaylistsAction
|
||||
final class ExportAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly StationPlaylistRepository $playlistRepo
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
|
@ -18,7 +24,7 @@ final class ExportAction extends AbstractPlaylistsAction
|
|||
string $id,
|
||||
string $format = 'pls'
|
||||
): ResponseInterface {
|
||||
$record = $this->requireRecord($request->getStation(), $id);
|
||||
$record = $this->playlistRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
$exportFileName = 'playlist_' . $record->getShortName() . '.' . $format;
|
||||
$exportLines = [];
|
||||
|
|
|
@ -4,14 +4,23 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Playlists;
|
||||
|
||||
use App\Entity;
|
||||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Entity\Enums\PlaylistOrders;
|
||||
use App\Entity\Enums\PlaylistSources;
|
||||
use App\Entity\Repository\StationPlaylistRepository;
|
||||
use App\Exception;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class GetOrderAction extends AbstractPlaylistsAction
|
||||
final class GetOrderAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly StationPlaylistRepository $playlistRepo,
|
||||
private readonly ReloadableEntityManagerInterface $em,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
|
@ -19,11 +28,11 @@ final class GetOrderAction extends AbstractPlaylistsAction
|
|||
string $id
|
||||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
$record = $this->requireRecord($station, $id);
|
||||
$record = $this->playlistRepo->requireForStation($id, $station);
|
||||
|
||||
if (
|
||||
Entity\Enums\PlaylistSources::Songs !== $record->getSourceEnum()
|
||||
|| Entity\Enums\PlaylistOrders::Sequential !== $record->getOrderEnum()
|
||||
PlaylistSources::Songs !== $record->getSourceEnum()
|
||||
|| PlaylistOrders::Sequential !== $record->getOrderEnum()
|
||||
) {
|
||||
throw new Exception(__('This playlist is not a sequential playlist.'));
|
||||
}
|
||||
|
|
|
@ -4,21 +4,22 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Playlists;
|
||||
|
||||
use App\Entity;
|
||||
use App\Entity\Enums\PlaylistOrders;
|
||||
use App\Entity\Enums\PlaylistSources;
|
||||
use App\Entity\Repository\StationPlaylistMediaRepository;
|
||||
use App\Entity\Repository\StationPlaylistRepository;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Paginator;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class GetQueueAction extends AbstractPlaylistsAction
|
||||
final class GetQueueAction
|
||||
{
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
private readonly Entity\Repository\StationPlaylistMediaRepository $spmRepo
|
||||
private readonly StationPlaylistRepository $playlistRepo,
|
||||
private readonly StationPlaylistMediaRepository $spmRepo
|
||||
) {
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
|
@ -27,13 +28,13 @@ final class GetQueueAction extends AbstractPlaylistsAction
|
|||
string $station_id,
|
||||
string $id
|
||||
): ResponseInterface {
|
||||
$record = $this->requireRecord($request->getStation(), $id);
|
||||
$record = $this->playlistRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
if (Entity\Enums\PlaylistSources::Songs !== $record->getSourceEnum()) {
|
||||
if (PlaylistSources::Songs !== $record->getSourceEnum()) {
|
||||
throw new InvalidArgumentException('This playlist does not have songs as its primary source.');
|
||||
}
|
||||
|
||||
if (Entity\Enums\PlaylistOrders::Random === $record->getOrderEnum()) {
|
||||
if (PlaylistOrders::Random === $record->getOrderEnum()) {
|
||||
throw new InvalidArgumentException('This playlist is always shuffled and has no visible queue.');
|
||||
}
|
||||
|
||||
|
|
|
@ -4,22 +4,26 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Playlists;
|
||||
|
||||
use App\Entity;
|
||||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Entity\Api\Error;
|
||||
use App\Entity\Api\StationPlaylistImportResult;
|
||||
use App\Entity\Repository\StationPlaylistMediaRepository;
|
||||
use App\Entity\Repository\StationPlaylistRepository;
|
||||
use App\Entity\StationMedia;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Radio\PlaylistParser;
|
||||
use App\Utilities\File;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
|
||||
final class ImportAction extends AbstractPlaylistsAction
|
||||
final class ImportAction
|
||||
{
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
private readonly Entity\Repository\StationPlaylistMediaRepository $spmRepo,
|
||||
private readonly StationPlaylistRepository $playlistRepo,
|
||||
private readonly StationPlaylistMediaRepository $spmRepo,
|
||||
private readonly ReloadableEntityManagerInterface $em,
|
||||
) {
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
|
@ -28,13 +32,13 @@ final class ImportAction extends AbstractPlaylistsAction
|
|||
string $station_id,
|
||||
string $id
|
||||
): ResponseInterface {
|
||||
$playlist = $this->requireRecord($request->getStation(), $id);
|
||||
$playlist = $this->playlistRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
$files = $request->getUploadedFiles();
|
||||
|
||||
if (empty($files['playlist_file'])) {
|
||||
return $response->withStatus(500)
|
||||
->withJson(new Entity\Api\Error(500, 'No "playlist_file" provided.'));
|
||||
->withJson(new Error(500, 'No "playlist_file" provided.'));
|
||||
}
|
||||
|
||||
/** @var UploadedFileInterface $file */
|
||||
|
@ -42,7 +46,7 @@ final class ImportAction extends AbstractPlaylistsAction
|
|||
|
||||
if (UPLOAD_ERR_OK !== $file->getError()) {
|
||||
return $response->withStatus(500)
|
||||
->withJson(Entity\Api\Error::fromFileError($file->getError()));
|
||||
->withJson(Error::fromFileError($file->getError()));
|
||||
}
|
||||
|
||||
$playlistFile = $file->getStream()->getContents();
|
||||
|
@ -137,10 +141,10 @@ final class ImportAction extends AbstractPlaylistsAction
|
|||
->setParameter('matched_ids', $matches)
|
||||
->execute();
|
||||
|
||||
/** @var Entity\StationMedia[] $mediaById */
|
||||
/** @var StationMedia[] $mediaById */
|
||||
$mediaById = [];
|
||||
foreach ($matchedMediaRaw as $row) {
|
||||
/** @var Entity\StationMedia $row */
|
||||
/** @var StationMedia $row */
|
||||
$mediaById[$row->getId()] = $row;
|
||||
}
|
||||
|
||||
|
@ -161,7 +165,7 @@ final class ImportAction extends AbstractPlaylistsAction
|
|||
}
|
||||
|
||||
return $response->withJson(
|
||||
new Entity\Api\StationPlaylistImportResult(
|
||||
new StationPlaylistImportResult(
|
||||
true,
|
||||
sprintf(
|
||||
__('Playlist successfully imported; %d of %d files were successfully matched.'),
|
||||
|
|
|
@ -4,20 +4,21 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Playlists;
|
||||
|
||||
use App\Entity;
|
||||
use App\Entity\Enums\PlaylistOrders;
|
||||
use App\Entity\Enums\PlaylistSources;
|
||||
use App\Entity\Repository\StationPlaylistMediaRepository;
|
||||
use App\Entity\Repository\StationPlaylistRepository;
|
||||
use App\Exception;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class PutOrderAction extends AbstractPlaylistsAction
|
||||
final class PutOrderAction
|
||||
{
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
private readonly Entity\Repository\StationPlaylistMediaRepository $spmRepo,
|
||||
private readonly StationPlaylistRepository $playlistRepo,
|
||||
private readonly StationPlaylistMediaRepository $spmRepo
|
||||
) {
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
|
@ -26,11 +27,11 @@ final class PutOrderAction extends AbstractPlaylistsAction
|
|||
string $station_id,
|
||||
string $id
|
||||
): ResponseInterface {
|
||||
$record = $this->requireRecord($request->getStation(), $id);
|
||||
$record = $this->playlistRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
if (
|
||||
Entity\Enums\PlaylistSources::Songs !== $record->getSourceEnum()
|
||||
|| Entity\Enums\PlaylistOrders::Sequential !== $record->getOrderEnum()
|
||||
PlaylistSources::Songs !== $record->getSourceEnum()
|
||||
|| PlaylistOrders::Sequential !== $record->getOrderEnum()
|
||||
) {
|
||||
throw new Exception(__('This playlist is not a sequential playlist.'));
|
||||
}
|
||||
|
|
|
@ -4,19 +4,19 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Playlists;
|
||||
|
||||
use App\Entity;
|
||||
use App\Entity\Api\Status;
|
||||
use App\Entity\Repository\StationPlaylistMediaRepository;
|
||||
use App\Entity\Repository\StationPlaylistRepository;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class ReshuffleAction extends AbstractPlaylistsAction
|
||||
final class ReshuffleAction
|
||||
{
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
private readonly Entity\Repository\StationPlaylistMediaRepository $spmRepo,
|
||||
private readonly StationPlaylistRepository $playlistRepo,
|
||||
private readonly StationPlaylistMediaRepository $spmRepo
|
||||
) {
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
|
@ -25,12 +25,12 @@ final class ReshuffleAction extends AbstractPlaylistsAction
|
|||
string $station_id,
|
||||
string $id
|
||||
): ResponseInterface {
|
||||
$record = $this->requireRecord($request->getStation(), $id);
|
||||
$record = $this->playlistRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
$this->spmRepo->resetQueue($record);
|
||||
|
||||
return $response->withJson(
|
||||
new Entity\Api\Status(
|
||||
new Status(
|
||||
true,
|
||||
__('Playlist reshuffled.')
|
||||
)
|
||||
|
|
|
@ -4,31 +4,38 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Playlists;
|
||||
|
||||
use App\Entity;
|
||||
use App\Entity\Api\Status;
|
||||
use App\Entity\Repository\StationPlaylistRepository;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class ToggleAction extends AbstractPlaylistsAction
|
||||
final class ToggleAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly StationPlaylistRepository $playlistRepo
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
string $station_id,
|
||||
string $id
|
||||
): ResponseInterface {
|
||||
$record = $this->requireRecord($request->getStation(), $id);
|
||||
$record = $this->playlistRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
$new_value = !$record->getIsEnabled();
|
||||
|
||||
$record->setIsEnabled($new_value);
|
||||
$this->em->persist($record);
|
||||
$this->em->flush();
|
||||
|
||||
$em = $this->playlistRepo->getEntityManager();
|
||||
$em->persist($record);
|
||||
$em->flush();
|
||||
|
||||
$flash_message = ($new_value)
|
||||
? __('Playlist enabled.')
|
||||
: __('Playlist disabled.');
|
||||
|
||||
return $response->withJson(new Entity\Api\Status(true, $flash_message));
|
||||
return $response->withJson(new Status(true, $flash_message));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ final class BroadcastsController extends AbstractApiCrudController
|
|||
ServerRequest $request,
|
||||
Response $response,
|
||||
string $station_id,
|
||||
int $broadcast_id
|
||||
string $broadcast_id
|
||||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
$broadcast = $this->getRecord($station, $broadcast_id);
|
||||
|
@ -158,7 +158,7 @@ final class BroadcastsController extends AbstractApiCrudController
|
|||
ServerRequest $request,
|
||||
Response $response,
|
||||
string $station_id,
|
||||
int $broadcast_id
|
||||
string $broadcast_id
|
||||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
$broadcast = $this->getRecord($station, $broadcast_id);
|
||||
|
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Waveform;
|
||||
|
||||
use App\Entity\Api\Error;
|
||||
use App\Entity\Repository\StationMediaRepository;
|
||||
use App\Entity\StationMedia;
|
||||
use App\Flysystem\StationFilesystems;
|
||||
|
@ -41,10 +40,7 @@ final class GetWaveformAction
|
|||
}
|
||||
}
|
||||
|
||||
$media = $this->mediaRepo->findByUniqueId($media_id, $station);
|
||||
if (!($media instanceof StationMedia)) {
|
||||
return $response->withStatus(500)->withJson(new Error(500, 'Media not found.'));
|
||||
}
|
||||
$media = $this->mediaRepo->requireByUniqueId($media_id, $station);
|
||||
|
||||
$waveformPath = StationMedia::getWaveformPath($media->getUniqueId());
|
||||
if (!$fsMedia->fileExists($waveformPath)) {
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Api\Stations\Webhooks;
|
||||
|
||||
use App\Entity;
|
||||
use App\Exception\NotFoundException;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
abstract class AbstractWebhooksAction
|
||||
{
|
||||
public function __construct(
|
||||
protected EntityManagerInterface $em
|
||||
) {
|
||||
}
|
||||
|
||||
protected function requireRecord(Entity\Station $station, int|string $id): Entity\StationWebhook
|
||||
{
|
||||
$record = $this->em->getRepository(Entity\StationWebhook::class)->findOneBy(
|
||||
[
|
||||
'station' => $station,
|
||||
'id' => (int)$id,
|
||||
]
|
||||
);
|
||||
|
||||
if (!$record instanceof Entity\StationWebhook) {
|
||||
throw new NotFoundException(__('Web hook not found.'));
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
}
|
|
@ -4,21 +4,20 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller\Api\Stations\Webhooks;
|
||||
|
||||
use App\Entity\Repository\StationWebhookRepository;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Message\TestWebhookMessage;
|
||||
use App\Utilities\File;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Symfony\Component\Messenger\MessageBus;
|
||||
|
||||
final class TestAction extends AbstractWebhooksAction
|
||||
final class TestAction
|
||||
{
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
private readonly StationWebhookRepository $webhookRepo,
|
||||
private readonly MessageBus $messageBus
|
||||
) {
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
|
@ -27,7 +26,7 @@ final class TestAction extends AbstractWebhooksAction
|
|||
string $station_id,
|
||||
string $id
|
||||
): ResponseInterface {
|
||||
$webhook = $this->requireRecord($request->getStation(), $id);
|
||||
$webhook = $this->webhookRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
$tempFile = File::generateTempPath('webhook_test_' . $id . '.log');
|
||||
touch($tempFile);
|
||||
|
|
|
@ -6,15 +6,21 @@ namespace App\Controller\Api\Stations\Webhooks;
|
|||
|
||||
use App\Controller\Api\Traits\HasLogViewer;
|
||||
use App\Entity;
|
||||
use App\Entity\Repository\StationWebhookRepository;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Utilities\File;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class TestLogAction extends AbstractWebhooksAction
|
||||
final class TestLogAction
|
||||
{
|
||||
use HasLogViewer;
|
||||
|
||||
public function __construct(
|
||||
private readonly StationWebhookRepository $webhookRepo
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
|
@ -22,7 +28,7 @@ final class TestLogAction extends AbstractWebhooksAction
|
|||
string $id,
|
||||
string $path
|
||||
): ResponseInterface {
|
||||
$this->requireRecord($request->getStation(), $id);
|
||||
$this->webhookRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
$logPathPortion = 'webhook_test_' . $id;
|
||||
if (!str_contains($path, $logPathPortion)) {
|
||||
|
|
|
@ -5,25 +5,32 @@ declare(strict_types=1);
|
|||
namespace App\Controller\Api\Stations\Webhooks;
|
||||
|
||||
use App\Entity;
|
||||
use App\Entity\Repository\StationWebhookRepository;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class ToggleAction extends AbstractWebhooksAction
|
||||
final class ToggleAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly StationWebhookRepository $webhookRepo
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
string $station_id,
|
||||
string $id
|
||||
): ResponseInterface {
|
||||
$record = $this->requireRecord($request->getStation(), $id);
|
||||
$record = $this->webhookRepo->requireForStation($id, $request->getStation());
|
||||
|
||||
$newValue = !$record->getIsEnabled();
|
||||
$record->setIsEnabled($newValue);
|
||||
|
||||
$this->em->persist($record);
|
||||
$this->em->flush();
|
||||
$em = $this->webhookRepo->getEntityManager();
|
||||
$em->persist($record);
|
||||
$em->flush();
|
||||
|
||||
$flash_message = ($newValue)
|
||||
? __('Web hook enabled.')
|
||||
|
|
|
@ -4,7 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace App;
|
||||
|
||||
use App\Assets\AssetFactory;
|
||||
use App\Assets\BackgroundCustomAsset;
|
||||
use App\Assets\BrowserIconCustomAsset;
|
||||
use App\Entity;
|
||||
use App\Enums\SupportedLocales;
|
||||
use App\Enums\SupportedThemes;
|
||||
|
@ -108,7 +109,7 @@ class Customization
|
|||
{
|
||||
$publicCss = $this->settings->getPublicCustomCss() ?? '';
|
||||
|
||||
$background = AssetFactory::createBackground($this->environment);
|
||||
$background = new BackgroundCustomAsset();
|
||||
if ($background->isUploaded()) {
|
||||
$backgroundUrl = $background->getUrl();
|
||||
|
||||
|
@ -140,7 +141,7 @@ class Customization
|
|||
|
||||
public function getBrowserIconUrl(int $size = 256): string
|
||||
{
|
||||
return AssetFactory::createBrowserIcon($this->environment)->getUrlForSize($size);
|
||||
return (new BrowserIconCustomAsset())->getUrlForSize($size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,14 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Doctrine;
|
||||
|
||||
use App\Environment;
|
||||
use App\Exception\NotFoundException;
|
||||
use Azura\Normalizer\DoctrineEntityNormalizer;
|
||||
use Closure;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @template TEntity as object
|
||||
|
@ -25,10 +20,7 @@ class Repository
|
|||
protected ObjectRepository $repository;
|
||||
|
||||
public function __construct(
|
||||
protected ReloadableEntityManagerInterface $em,
|
||||
protected Serializer $serializer,
|
||||
protected Environment $environment,
|
||||
protected LoggerInterface $logger
|
||||
protected ReloadableEntityManagerInterface $em
|
||||
) {
|
||||
if (!isset($this->entityClass)) {
|
||||
/** @var class-string<TEntity> $defaultClass */
|
||||
|
@ -135,42 +127,4 @@ class Repository
|
|||
|
||||
return $select;
|
||||
}
|
||||
|
||||
/**
|
||||
* FromArray (A Doctrine 1 Classic)
|
||||
*
|
||||
* @param object $entity
|
||||
* @param array $source
|
||||
*/
|
||||
public function fromArray(object $entity, array $source): object
|
||||
{
|
||||
return $this->serializer->denormalize(
|
||||
$source,
|
||||
get_class($entity),
|
||||
null,
|
||||
[
|
||||
AbstractNormalizer::OBJECT_TO_POPULATE => $entity,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* ToArray (A Doctrine 1 Classic)
|
||||
*
|
||||
* @param object $entity
|
||||
* @param bool $deep Iterate through collections associated with this item.
|
||||
* @param bool $form_mode Return values in a format suitable for ZendForm setDefault function.
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function toArray(object $entity, bool $deep = false, bool $form_mode = false): array
|
||||
{
|
||||
return (array)$this->serializer->normalize(
|
||||
$entity,
|
||||
null,
|
||||
[
|
||||
DoctrineEntityNormalizer::NORMALIZE_TO_IDENTIFIERS => $form_mode,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use DateTimeInterface;
|
|||
/**
|
||||
* @extends Repository<Entity\Analytics>
|
||||
*/
|
||||
class AnalyticsRepository extends Repository
|
||||
final class AnalyticsRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* @return mixed[]
|
||||
|
|
|
@ -9,6 +9,6 @@ use App\Entity;
|
|||
/**
|
||||
* @extends AbstractSplitTokenRepository<Entity\ApiKey>
|
||||
*/
|
||||
class ApiKeyRepository extends AbstractSplitTokenRepository
|
||||
final class ApiKeyRepository extends AbstractSplitTokenRepository
|
||||
{
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use App\Entity;
|
|||
/**
|
||||
* @extends Repository<Entity\CustomField>
|
||||
*/
|
||||
class CustomFieldRepository extends Repository
|
||||
final class CustomFieldRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* @return Entity\CustomField[]
|
||||
|
|
|
@ -7,37 +7,32 @@ namespace App\Entity\Repository;
|
|||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Service\DeviceDetector;
|
||||
use App\Service\IpGeolocation;
|
||||
use Carbon\CarbonImmutable;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Monolog\Registry;
|
||||
use NowPlaying\Result\Client;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* @extends Repository<Entity\Listener>
|
||||
*/
|
||||
class ListenerRepository extends Repository
|
||||
final class ListenerRepository extends Repository
|
||||
{
|
||||
use Entity\Traits\TruncateStrings;
|
||||
|
||||
protected string $tableName;
|
||||
private string $tableName;
|
||||
|
||||
protected Connection $conn;
|
||||
private Connection $conn;
|
||||
|
||||
public function __construct(
|
||||
protected DeviceDetector $deviceDetector,
|
||||
protected IpGeolocation $ipGeolocation,
|
||||
ReloadableEntityManagerInterface $em,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger
|
||||
private readonly DeviceDetector $deviceDetector,
|
||||
private readonly IpGeolocation $ipGeolocation
|
||||
) {
|
||||
parent::__construct($em, $serializer, $environment, $logger);
|
||||
parent::__construct($em);
|
||||
|
||||
$this->tableName = $this->em->getClassMetadata(Entity\Listener::class)->getTableName();
|
||||
$this->conn = $this->em->getConnection();
|
||||
|
@ -190,7 +185,7 @@ class ListenerRepository extends Repository
|
|||
$record['device_browser_family'] = $this->truncateNullableString($browserResult->browserFamily, 150);
|
||||
$record['device_os_family'] = $this->truncateNullableString($browserResult->osFamily, 150);
|
||||
} catch (Throwable $e) {
|
||||
$this->logger->error('Device Detector error: ' . $e->getMessage(), [
|
||||
Registry::getInstance('app')->error('Device Detector error: ' . $e->getMessage(), [
|
||||
'user_agent' => $userAgent,
|
||||
'exception' => $e,
|
||||
]);
|
||||
|
@ -213,7 +208,7 @@ class ListenerRepository extends Repository
|
|||
$record['location_lat'] = $ipInfo->lat;
|
||||
$record['location_lon'] = $ipInfo->lon;
|
||||
} catch (Throwable $e) {
|
||||
$this->logger->error('IP Geolocation error: ' . $e->getMessage(), [
|
||||
Registry::getInstance('app')->error('IP Geolocation error: ' . $e->getMessage(), [
|
||||
'ip' => $ip,
|
||||
'exception' => $e,
|
||||
]);
|
||||
|
|
|
@ -7,7 +7,6 @@ namespace App\Entity\Repository;
|
|||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Exception\InvalidPodcastMediaFileException;
|
||||
use App\Exception\StorageLocationFullException;
|
||||
use App\Media\AlbumArt;
|
||||
|
@ -15,22 +14,17 @@ use App\Media\MetadataManager;
|
|||
use Azura\Files\ExtendedFilesystemInterface;
|
||||
use League\Flysystem\UnableToDeleteFile;
|
||||
use League\Flysystem\UnableToRetrieveMetadata;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @extends Repository<Entity\PodcastEpisode>
|
||||
*/
|
||||
class PodcastEpisodeRepository extends Repository
|
||||
final class PodcastEpisodeRepository extends Repository
|
||||
{
|
||||
public function __construct(
|
||||
protected MetadataManager $metadataManager,
|
||||
ReloadableEntityManagerInterface $entityManager,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger
|
||||
private readonly MetadataManager $metadataManager
|
||||
) {
|
||||
parent::__construct($entityManager, $serializer, $environment, $logger);
|
||||
parent::__construct($entityManager);
|
||||
}
|
||||
|
||||
public function fetchEpisodeForStation(Entity\Station $station, string $episodeId): ?Entity\PodcastEpisode
|
||||
|
|
|
@ -7,28 +7,22 @@ namespace App\Entity\Repository;
|
|||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Exception\StorageLocationFullException;
|
||||
use App\Media\AlbumArt;
|
||||
use Azura\Files\ExtendedFilesystemInterface;
|
||||
use League\Flysystem\UnableToDeleteFile;
|
||||
use League\Flysystem\UnableToRetrieveMetadata;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @extends Repository<Entity\Podcast>
|
||||
*/
|
||||
class PodcastRepository extends Repository
|
||||
final class PodcastRepository extends Repository
|
||||
{
|
||||
public function __construct(
|
||||
ReloadableEntityManagerInterface $entityManager,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger,
|
||||
protected PodcastEpisodeRepository $podcastEpisodeRepo,
|
||||
private readonly PodcastEpisodeRepository $podcastEpisodeRepo,
|
||||
) {
|
||||
parent::__construct($entityManager, $serializer, $environment, $logger);
|
||||
parent::__construct($entityManager);
|
||||
}
|
||||
|
||||
public function fetchPodcastForStation(Entity\Station $station, string $podcastId): ?Entity\Podcast
|
||||
|
|
|
@ -11,7 +11,7 @@ use App\Enums\GlobalPermissions;
|
|||
/**
|
||||
* @extends Repository<Entity\RolePermission>
|
||||
*/
|
||||
class RolePermissionRepository extends Repository
|
||||
final class RolePermissionRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* @param Entity\Role $role
|
||||
|
|
|
@ -10,6 +10,6 @@ use App\Entity;
|
|||
/**
|
||||
* @extends Repository<Entity\Role>
|
||||
*/
|
||||
class RoleRepository extends Repository
|
||||
final class RoleRepository extends Repository
|
||||
{
|
||||
}
|
||||
|
|
|
@ -7,31 +7,24 @@ namespace App\Entity\Repository;
|
|||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Exception\ValidationException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @extends Repository<Entity\Settings>
|
||||
*/
|
||||
class SettingsRepository extends Repository
|
||||
final class SettingsRepository extends Repository
|
||||
{
|
||||
protected ValidatorInterface $validator;
|
||||
|
||||
protected string $entityClass = Entity\Settings::class;
|
||||
|
||||
public function __construct(
|
||||
ReloadableEntityManagerInterface $em,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger,
|
||||
ValidatorInterface $validator
|
||||
private readonly Serializer $serializer,
|
||||
private readonly ValidatorInterface $validator
|
||||
) {
|
||||
parent::__construct($em, $serializer, $environment, $logger);
|
||||
|
||||
$this->validator = $validator;
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
public function readSettings(): Entity\Settings
|
||||
|
@ -78,4 +71,23 @@ class SettingsRepository extends Repository
|
|||
$this->em->persist($settings);
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
public function fromArray(Entity\Settings $entity, array $source): Entity\Settings
|
||||
{
|
||||
return $this->serializer->denormalize(
|
||||
$source,
|
||||
Entity\Settings::class,
|
||||
null,
|
||||
[
|
||||
AbstractNormalizer::OBJECT_TO_POPULATE => $entity,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function toArray(Entity\Settings $entity): array
|
||||
{
|
||||
return (array)$this->serializer->normalize(
|
||||
$entity
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,28 +6,22 @@ namespace App\Entity\Repository;
|
|||
|
||||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Radio\Backend\Liquidsoap\Command\FeedbackCommand;
|
||||
use App\Radio\Enums\BackendAdapters;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @extends AbstractStationBasedRepository<Entity\SongHistory>
|
||||
*/
|
||||
class SongHistoryRepository extends AbstractStationBasedRepository
|
||||
final class SongHistoryRepository extends AbstractStationBasedRepository
|
||||
{
|
||||
public function __construct(
|
||||
ReloadableEntityManagerInterface $em,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger,
|
||||
protected ListenerRepository $listenerRepository,
|
||||
protected StationQueueRepository $stationQueueRepository,
|
||||
protected FeedbackCommand $liquidsoapFeedback,
|
||||
private readonly ListenerRepository $listenerRepository,
|
||||
private readonly StationQueueRepository $stationQueueRepository,
|
||||
private readonly FeedbackCommand $liquidsoapFeedback,
|
||||
) {
|
||||
parent::__construct($em, $serializer, $environment, $logger);
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,8 +7,8 @@ namespace App\Entity\Repository;
|
|||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Exception\CannotProcessMediaException;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Media\AlbumArt;
|
||||
use App\Media\MetadataManager;
|
||||
use App\Media\RemoteAlbumArt;
|
||||
|
@ -17,8 +17,7 @@ use Azura\Files\ExtendedFilesystemInterface;
|
|||
use Exception;
|
||||
use Generator;
|
||||
use League\Flysystem\FilesystemException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Monolog\Registry;
|
||||
|
||||
use const JSON_PRETTY_PRINT;
|
||||
use const JSON_THROW_ON_ERROR;
|
||||
|
@ -27,21 +26,17 @@ use const JSON_UNESCAPED_SLASHES;
|
|||
/**
|
||||
* @extends Repository<Entity\StationMedia>
|
||||
*/
|
||||
class StationMediaRepository extends Repository
|
||||
final class StationMediaRepository extends Repository
|
||||
{
|
||||
public function __construct(
|
||||
ReloadableEntityManagerInterface $em,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger,
|
||||
protected MetadataManager $metadataManager,
|
||||
protected RemoteAlbumArt $remoteAlbumArt,
|
||||
protected CustomFieldRepository $customFieldRepo,
|
||||
protected StationPlaylistMediaRepository $spmRepo,
|
||||
protected StorageLocationRepository $storageLocationRepo,
|
||||
protected UnprocessableMediaRepository $unprocessableMediaRepo
|
||||
private readonly MetadataManager $metadataManager,
|
||||
private readonly RemoteAlbumArt $remoteAlbumArt,
|
||||
private readonly CustomFieldRepository $customFieldRepo,
|
||||
private readonly StationPlaylistMediaRepository $spmRepo,
|
||||
private readonly UnprocessableMediaRepository $unprocessableMediaRepo
|
||||
) {
|
||||
parent::__construct($em, $serializer, $environment, $logger);
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
public function findForStation(int|string $id, Entity\Station $station): ?Entity\StationMedia
|
||||
|
@ -66,6 +61,15 @@ class StationMediaRepository extends Repository
|
|||
return $media;
|
||||
}
|
||||
|
||||
public function requireForStation(int|string $id, Entity\Station $station): Entity\StationMedia
|
||||
{
|
||||
$record = $this->findForStation($id, $station);
|
||||
if (null === $record) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param Entity\Station|Entity\StorageLocation $source
|
||||
|
@ -120,6 +124,17 @@ class StationMediaRepository extends Repository
|
|||
return $media;
|
||||
}
|
||||
|
||||
public function requireByUniqueId(
|
||||
string $uniqueId,
|
||||
Entity\Station|Entity\StorageLocation $source
|
||||
): Entity\StationMedia {
|
||||
$record = $this->findByUniqueId($uniqueId, $source);
|
||||
if (null === $record) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return $record;
|
||||
}
|
||||
|
||||
protected function getStorageLocation(Entity\Station|Entity\StorageLocation $source): Entity\StorageLocation
|
||||
{
|
||||
if ($source instanceof Entity\Station) {
|
||||
|
@ -277,7 +292,7 @@ class StationMediaRepository extends Repository
|
|||
try {
|
||||
$this->writeAlbumArt($media, $artwork, $fs);
|
||||
} catch (Exception $exception) {
|
||||
$this->logger->error(
|
||||
Registry::getInstance('app')->error(
|
||||
sprintf(
|
||||
'Album Artwork for "%s" could not be processed: "%s"',
|
||||
$filePath,
|
||||
|
|
|
@ -12,7 +12,7 @@ use Azura\Files\ExtendedFilesystemInterface;
|
|||
/**
|
||||
* @extends AbstractStationBasedRepository<Entity\StationMount>
|
||||
*/
|
||||
class StationMountRepository extends AbstractStationBasedRepository
|
||||
final class StationMountRepository extends AbstractStationBasedRepository
|
||||
{
|
||||
public function setIntro(
|
||||
Entity\StationMount $mount,
|
||||
|
|
|
@ -9,7 +9,7 @@ use App\Entity;
|
|||
/**
|
||||
* @extends AbstractStationBasedRepository<Entity\StationPlaylistFolder>
|
||||
*/
|
||||
class StationPlaylistFolderRepository extends AbstractStationBasedRepository
|
||||
final class StationPlaylistFolderRepository extends AbstractStationBasedRepository
|
||||
{
|
||||
/**
|
||||
* @param Entity\Station $station
|
||||
|
|
|
@ -7,33 +7,23 @@ namespace App\Entity\Repository;
|
|||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Carbon\CarbonInterface;
|
||||
use Doctrine\ORM\NoResultException;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @extends Repository<Entity\StationPlaylistMedia>
|
||||
*/
|
||||
class StationPlaylistMediaRepository extends Repository
|
||||
final class StationPlaylistMediaRepository extends Repository
|
||||
{
|
||||
protected StationQueueRepository $queueRepo;
|
||||
|
||||
public function __construct(
|
||||
ReloadableEntityManagerInterface $em,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger,
|
||||
StationQueueRepository $queueRepo
|
||||
private readonly StationQueueRepository $queueRepo
|
||||
) {
|
||||
parent::__construct($em, $serializer, $environment, $logger);
|
||||
|
||||
$this->queueRepo = $queueRepo;
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,7 +9,7 @@ use App\Entity;
|
|||
/**
|
||||
* @extends AbstractStationBasedRepository<Entity\StationPlaylist>
|
||||
*/
|
||||
class StationPlaylistRepository extends AbstractStationBasedRepository
|
||||
final class StationPlaylistRepository extends AbstractStationBasedRepository
|
||||
{
|
||||
/**
|
||||
* @return Entity\StationPlaylist[]
|
||||
|
|
|
@ -13,7 +13,7 @@ use Doctrine\ORM\QueryBuilder;
|
|||
/**
|
||||
* @extends AbstractStationBasedRepository<Entity\StationQueue>
|
||||
*/
|
||||
class StationQueueRepository extends AbstractStationBasedRepository
|
||||
final class StationQueueRepository extends AbstractStationBasedRepository
|
||||
{
|
||||
public function clearForMediaAndPlaylist(Entity\StationMedia $media, Entity\StationPlaylist $playlist): void
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ use App\Entity;
|
|||
/**
|
||||
* @extends AbstractStationBasedRepository<Entity\StationRemote>
|
||||
*/
|
||||
class StationRemoteRepository extends AbstractStationBasedRepository
|
||||
final class StationRemoteRepository extends AbstractStationBasedRepository
|
||||
{
|
||||
/**
|
||||
* @param Entity\Station $station
|
||||
|
|
|
@ -4,33 +4,27 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity\Repository;
|
||||
|
||||
use App\Assets\AssetFactory;
|
||||
use App\Assets\AlbumArtCustomAsset;
|
||||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Flysystem\StationFilesystems;
|
||||
use App\Radio\Frontend\AbstractFrontend;
|
||||
use App\Service\Flow\UploadedFile;
|
||||
use Azura\Files\ExtendedFilesystemInterface;
|
||||
use Closure;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @extends Repository<Entity\Station>
|
||||
*/
|
||||
class StationRepository extends Repository
|
||||
final class StationRepository extends Repository
|
||||
{
|
||||
public function __construct(
|
||||
protected SettingsRepository $settingsRepo,
|
||||
ReloadableEntityManagerInterface $em,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger
|
||||
private readonly SettingsRepository $settingsRepo
|
||||
) {
|
||||
parent::__construct($em, $serializer, $environment, $logger);
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,11 +97,8 @@ class StationRepository extends Repository
|
|||
// Create default mountpoints if station supports them.
|
||||
if ($frontend_adapter->supportsMounts()) {
|
||||
// Create default mount points.
|
||||
foreach ($frontend_adapter->getDefaultMounts() as $mount_point) {
|
||||
$mount_record = new Entity\StationMount($station);
|
||||
$this->fromArray($mount_record, $mount_point);
|
||||
|
||||
$this->em->persist($mount_record);
|
||||
foreach ($frontend_adapter->getDefaultMounts($station) as $mount) {
|
||||
$this->em->persist($mount);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +156,7 @@ class StationRepository extends Repository
|
|||
}
|
||||
|
||||
$customUrl = $this->settingsRepo->readSettings()->getDefaultAlbumArtUrlAsUri();
|
||||
return $customUrl ?? AssetFactory::createAlbumArt($this->environment)->getUri();
|
||||
return $customUrl ?? (new AlbumArtCustomAsset())->getUri();
|
||||
}
|
||||
|
||||
public function setFallback(
|
||||
|
|
|
@ -6,32 +6,26 @@ namespace App\Entity\Repository;
|
|||
|
||||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Exception;
|
||||
use App\Radio\AutoDJ;
|
||||
use App\Radio\Frontend\Blocklist\BlocklistParser;
|
||||
use App\Service\DeviceDetector;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Carbon\CarbonInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @extends AbstractStationBasedRepository<Entity\StationRequest>
|
||||
*/
|
||||
class StationRequestRepository extends AbstractStationBasedRepository
|
||||
final class StationRequestRepository extends AbstractStationBasedRepository
|
||||
{
|
||||
public function __construct(
|
||||
ReloadableEntityManagerInterface $em,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger,
|
||||
protected StationMediaRepository $mediaRepo,
|
||||
protected DeviceDetector $deviceDetector,
|
||||
protected BlocklistParser $blocklistParser,
|
||||
protected AutoDJ\DuplicatePrevention $duplicatePrevention,
|
||||
private readonly StationMediaRepository $mediaRepo,
|
||||
private readonly DeviceDetector $deviceDetector,
|
||||
private readonly BlocklistParser $blocklistParser,
|
||||
private readonly AutoDJ\DuplicatePrevention $duplicatePrevention,
|
||||
) {
|
||||
parent::__construct($em, $serializer, $environment, $logger);
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
public function getPendingRequest(int|string $id, Entity\Station $station): ?Entity\StationRequest
|
||||
|
|
|
@ -7,27 +7,21 @@ namespace App\Entity\Repository;
|
|||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Radio\AutoDJ\Scheduler;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Carbon\CarbonInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @extends Repository<Entity\StationSchedule>
|
||||
*/
|
||||
class StationScheduleRepository extends Repository
|
||||
final class StationScheduleRepository extends Repository
|
||||
{
|
||||
public function __construct(
|
||||
ReloadableEntityManagerInterface $em,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger,
|
||||
protected Scheduler $scheduler,
|
||||
protected Entity\ApiGenerator\ScheduleApiGenerator $scheduleApiGenerator
|
||||
private readonly Scheduler $scheduler,
|
||||
private readonly Entity\ApiGenerator\ScheduleApiGenerator $scheduleApiGenerator
|
||||
) {
|
||||
parent::__construct($em, $serializer, $environment, $logger);
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,7 +11,7 @@ use Carbon\CarbonImmutable;
|
|||
/**
|
||||
* @extends Repository<Entity\StationStreamerBroadcast>
|
||||
*/
|
||||
class StationStreamerBroadcastRepository extends Repository
|
||||
final class StationStreamerBroadcastRepository extends Repository
|
||||
{
|
||||
public function getLatestBroadcast(Entity\Station $station): ?Entity\StationStreamerBroadcast
|
||||
{
|
||||
|
@ -58,7 +58,7 @@ class StationStreamerBroadcastRepository extends Repository
|
|||
public function getActiveBroadcasts(Entity\Station $station): array
|
||||
{
|
||||
return $this->repository->findBy([
|
||||
'station' => $station,
|
||||
'station' => $station,
|
||||
'timestampEnd' => 0,
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -6,34 +6,21 @@ namespace App\Entity\Repository;
|
|||
|
||||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Flysystem\StationFilesystems;
|
||||
use App\Media\AlbumArt;
|
||||
use App\Radio\AutoDJ\Scheduler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @extends AbstractStationBasedRepository<Entity\StationStreamer>
|
||||
*/
|
||||
class StationStreamerRepository extends AbstractStationBasedRepository
|
||||
final class StationStreamerRepository extends AbstractStationBasedRepository
|
||||
{
|
||||
protected Scheduler $scheduler;
|
||||
|
||||
protected StationStreamerBroadcastRepository $broadcastRepo;
|
||||
|
||||
public function __construct(
|
||||
ReloadableEntityManagerInterface $em,
|
||||
Serializer $serializer,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger,
|
||||
Scheduler $scheduler,
|
||||
StationStreamerBroadcastRepository $broadcastRepo
|
||||
private readonly Scheduler $scheduler,
|
||||
private readonly StationStreamerBroadcastRepository $broadcastRepo
|
||||
) {
|
||||
parent::__construct($em, $serializer, $environment, $logger);
|
||||
|
||||
$this->scheduler = $scheduler;
|
||||
$this->broadcastRepo = $broadcastRepo;
|
||||
parent::__construct($em);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity\Repository;
|
||||
|
||||
use App\Entity;
|
||||
|
||||
/**
|
||||
* @extends AbstractStationBasedRepository<Entity\StationWebhook>
|
||||
*/
|
||||
final class StationWebhookRepository extends AbstractStationBasedRepository
|
||||
{
|
||||
}
|
|
@ -11,7 +11,7 @@ use Brick\Math\BigInteger;
|
|||
/**
|
||||
* @extends Repository<Entity\StorageLocation>
|
||||
*/
|
||||
class StorageLocationRepository extends Repository
|
||||
final class StorageLocationRepository extends Repository
|
||||
{
|
||||
public function findByType(
|
||||
string|Entity\Enums\StorageLocationTypes $type,
|
||||
|
@ -24,7 +24,7 @@ class StorageLocationRepository extends Repository
|
|||
return $this->repository->findOneBy(
|
||||
[
|
||||
'type' => $type,
|
||||
'id' => $id,
|
||||
'id' => $id,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use Generator;
|
|||
/**
|
||||
* @extends Repository<Entity\UnprocessableMedia>
|
||||
*/
|
||||
class UnprocessableMediaRepository extends Repository
|
||||
final class UnprocessableMediaRepository extends Repository
|
||||
{
|
||||
public function findByPath(string $path, Entity\StorageLocation $storageLocation): ?Entity\UnprocessableMedia
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@ use App\Security\SplitToken;
|
|||
/**
|
||||
* @extends AbstractSplitTokenRepository<Entity\UserLoginToken>
|
||||
*/
|
||||
class UserLoginTokenRepository extends AbstractSplitTokenRepository
|
||||
final class UserLoginTokenRepository extends AbstractSplitTokenRepository
|
||||
{
|
||||
public function createToken(Entity\User $user): SplitToken
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@ use App\Entity;
|
|||
/**
|
||||
* @extends Repository<Entity\User>
|
||||
*/
|
||||
class UserRepository extends Repository
|
||||
final class UserRepository extends Repository
|
||||
{
|
||||
public function findByEmail(string $email): ?Entity\User
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@ use App\Entity;
|
|||
use App\Environment;
|
||||
use App\Http\Router;
|
||||
use App\Radio\AbstractAdapter;
|
||||
use App\Radio\Enums\StreamFormats;
|
||||
use App\Xml\Reader;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Exception;
|
||||
|
@ -50,19 +51,18 @@ abstract class AbstractFrontend extends AbstractAdapter
|
|||
/**
|
||||
* Get the default mounts when resetting or initializing a station.
|
||||
*
|
||||
* @return mixed[]
|
||||
* @return Entity\StationMount[]
|
||||
*/
|
||||
public function getDefaultMounts(): array
|
||||
public function getDefaultMounts(Entity\Station $station): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'name' => '/radio.mp3',
|
||||
'is_default' => 1,
|
||||
'enable_autodj' => 1,
|
||||
'autodj_format' => 'mp3',
|
||||
'autodj_bitrate' => 128,
|
||||
],
|
||||
];
|
||||
$record = new Entity\StationMount($station);
|
||||
$record->setName('/radio.mp3');
|
||||
$record->setIsDefault(true);
|
||||
$record->setEnableAutodj(true);
|
||||
$record->setAutodjFormat(StreamFormats::Mp3->value);
|
||||
$record->setAutodjBitrate(128);
|
||||
|
||||
return [$record];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue