305 lines
9.3 KiB
PHP
305 lines
9.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Entity\Repository;
|
|
|
|
use App\Assets\AlbumArtCustomAsset;
|
|
use App\Doctrine\ReloadableEntityManagerInterface;
|
|
use App\Doctrine\Repository;
|
|
use App\Entity;
|
|
use App\Environment;
|
|
use App\Flysystem\ExtendedFilesystemInterface;
|
|
use App\Flysystem\StationFilesystems;
|
|
use App\Radio\Enums\StreamFormats;
|
|
use App\Service\Flow\UploadedFile;
|
|
use Closure;
|
|
use Psr\Http\Message\UriInterface;
|
|
|
|
/**
|
|
* @extends Repository<Entity\Station>
|
|
*/
|
|
final class StationRepository extends Repository
|
|
{
|
|
public function __construct(
|
|
ReloadableEntityManagerInterface $em,
|
|
private readonly SettingsRepository $settingsRepo,
|
|
private readonly Environment $environment
|
|
) {
|
|
parent::__construct($em);
|
|
}
|
|
|
|
/**
|
|
* @param string $identifier A numeric or string identifier for a station.
|
|
*/
|
|
public function findByIdentifier(string $identifier): ?Entity\Station
|
|
{
|
|
return is_numeric($identifier)
|
|
? $this->repository->find($identifier)
|
|
: $this->repository->findOneBy(['short_name' => $identifier]);
|
|
}
|
|
|
|
public function getActiveCount(): int
|
|
{
|
|
return $this->em->createQuery(
|
|
<<<'DQL'
|
|
SELECT COUNT(s.id) FROM App\Entity\Station s WHERE s.is_enabled = 1
|
|
DQL
|
|
)->getSingleScalarResult();
|
|
}
|
|
|
|
public function fetchAll(): mixed
|
|
{
|
|
return $this->em->createQuery(
|
|
<<<'DQL'
|
|
SELECT s FROM App\Entity\Station s ORDER BY s.name ASC
|
|
DQL
|
|
)->execute();
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function fetchSelect(
|
|
bool|string $add_blank = false,
|
|
Closure $display = null,
|
|
string $pk = 'id',
|
|
string $order_by = 'name'
|
|
): array {
|
|
$select = [];
|
|
|
|
// Specify custom text in the $add_blank parameter to override.
|
|
if ($add_blank !== false) {
|
|
$select[''] = ($add_blank === true) ? 'Select...' : $add_blank;
|
|
}
|
|
|
|
// Build query for records.
|
|
// Assemble select values and, if necessary, call $display callback.
|
|
foreach ($this->fetchArray() as $result) {
|
|
$key = $result[$pk];
|
|
$select[$key] = ($display === null) ? $result['name'] : $display($result);
|
|
}
|
|
|
|
return $select;
|
|
}
|
|
|
|
/**
|
|
* @return iterable<Entity\Station>
|
|
*/
|
|
public function iterateEnabledStations(): iterable
|
|
{
|
|
return $this->em->createQuery(
|
|
<<<DQL
|
|
SELECT s FROM App\Entity\Station s WHERE s.is_enabled = 1
|
|
DQL
|
|
)->toIterable();
|
|
}
|
|
|
|
/**
|
|
* Reset mount points to their adapter defaults (in the event of an adapter change).
|
|
*/
|
|
public function resetMounts(Entity\Station $station): void
|
|
{
|
|
foreach ($station->getMounts() as $mount) {
|
|
$this->em->remove($mount);
|
|
}
|
|
|
|
// Create default mountpoints if station supports them.
|
|
if ($station->getFrontendTypeEnum()->supportsMounts()) {
|
|
$record = new Entity\StationMount($station);
|
|
$record->setName('/radio.mp3');
|
|
$record->setIsDefault(true);
|
|
$record->setEnableAutodj(true);
|
|
$record->setAutodjFormat(StreamFormats::Mp3->value);
|
|
$record->setAutodjBitrate(128);
|
|
$this->em->persist($record);
|
|
}
|
|
|
|
$this->em->flush();
|
|
$this->em->refresh($station);
|
|
}
|
|
|
|
public function resetHls(Entity\Station $station): void
|
|
{
|
|
foreach ($station->getHlsStreams() as $hlsStream) {
|
|
$this->em->remove($hlsStream);
|
|
}
|
|
|
|
if ($station->getEnableHls() && $station->getBackendTypeEnum()->isEnabled()) {
|
|
$streams = [
|
|
'aac_lofi' => 48,
|
|
'aac_midfi' => 96,
|
|
'aac_hifi' => 192,
|
|
];
|
|
|
|
foreach ($streams as $name => $bitrate) {
|
|
$record = new Entity\StationHlsStream($station);
|
|
$record->setName($name);
|
|
$record->setFormat(StreamFormats::Aac->value);
|
|
$record->setBitrate($bitrate);
|
|
$this->em->persist($record);
|
|
}
|
|
}
|
|
|
|
$this->em->flush();
|
|
$this->em->refresh($station);
|
|
}
|
|
|
|
public function flushRelatedMedia(Entity\Station $station): void
|
|
{
|
|
$this->em->createQuery(
|
|
<<<'DQL'
|
|
UPDATE App\Entity\SongHistory sh SET sh.media = null
|
|
WHERE sh.station = :station
|
|
DQL
|
|
)->setParameter('station', $station)
|
|
->execute();
|
|
|
|
$this->em->createQuery(
|
|
<<<'DQL'
|
|
DELETE FROM App\Entity\StationPlaylistMedia spm
|
|
WHERE spm.playlist_id IN (
|
|
SELECT sp.id FROM App\Entity\StationPlaylist sp WHERE sp.station = :station
|
|
)
|
|
DQL
|
|
)->setParameter('station', $station)
|
|
->execute();
|
|
|
|
$this->em->createQuery(
|
|
<<<'DQL'
|
|
DELETE FROM App\Entity\StationQueue sq WHERE sq.station = :station
|
|
DQL
|
|
)->setParameter('station', $station)
|
|
->execute();
|
|
|
|
$this->em->createQuery(
|
|
<<<'DQL'
|
|
DELETE FROM App\Entity\StationRequest sr WHERE sr.station = :station
|
|
DQL
|
|
)->setParameter('station', $station)
|
|
->execute();
|
|
}
|
|
|
|
/**
|
|
* Return the URL to use for songs with no specified album artwork, when artwork is displayed.
|
|
*
|
|
* @param Entity\Station|null $station
|
|
*/
|
|
public function getDefaultAlbumArtUrl(?Entity\Station $station = null): UriInterface
|
|
{
|
|
if (null !== $station) {
|
|
$stationAlbumArt = new AlbumArtCustomAsset($this->environment, $station);
|
|
if ($stationAlbumArt->isUploaded()) {
|
|
return $stationAlbumArt->getUri();
|
|
}
|
|
|
|
$stationCustomUri = $station->getBrandingConfig()->getDefaultAlbumArtUrlAsUri();
|
|
if (null !== $stationCustomUri) {
|
|
return $stationCustomUri;
|
|
}
|
|
}
|
|
|
|
$customUrl = $this->settingsRepo->readSettings()->getDefaultAlbumArtUrlAsUri();
|
|
return $customUrl ?? (new AlbumArtCustomAsset($this->environment))->getUri();
|
|
}
|
|
|
|
public function setFallback(
|
|
Entity\Station $station,
|
|
UploadedFile $file,
|
|
?ExtendedFilesystemInterface $fs = null
|
|
): void {
|
|
$fs ??= (new StationFilesystems($station))->getConfigFilesystem();
|
|
|
|
if (!empty($station->getFallbackPath())) {
|
|
$this->doDeleteFallback($station, $fs);
|
|
$station->setFallbackPath(null);
|
|
}
|
|
|
|
$originalPath = $file->getClientFilename();
|
|
$originalExt = pathinfo($originalPath, PATHINFO_EXTENSION);
|
|
|
|
$fallbackPath = 'fallback.' . $originalExt;
|
|
$fs->uploadAndDeleteOriginal($file->getUploadedPath(), $fallbackPath);
|
|
|
|
$station->setFallbackPath($fallbackPath);
|
|
$this->em->persist($station);
|
|
$this->em->flush();
|
|
}
|
|
|
|
public function doDeleteFallback(
|
|
Entity\Station $station,
|
|
?ExtendedFilesystemInterface $fs = null
|
|
): void {
|
|
$fs ??= (new StationFilesystems($station))->getConfigFilesystem();
|
|
|
|
$fallbackPath = $station->getFallbackPath();
|
|
if (empty($fallbackPath)) {
|
|
return;
|
|
}
|
|
|
|
$fs->delete($fallbackPath);
|
|
}
|
|
|
|
public function clearFallback(
|
|
Entity\Station $station,
|
|
?ExtendedFilesystemInterface $fs = null
|
|
): void {
|
|
$this->doDeleteFallback($station, $fs);
|
|
|
|
$station->setFallbackPath(null);
|
|
$this->em->persist($station);
|
|
$this->em->flush();
|
|
}
|
|
|
|
public function setStereoToolConfiguration(
|
|
Entity\Station $station,
|
|
UploadedFile $file,
|
|
?ExtendedFilesystemInterface $fs = null
|
|
): void {
|
|
$fs ??= (new StationFilesystems($station))->getConfigFilesystem();
|
|
|
|
$backendConfig = $station->getBackendConfig();
|
|
|
|
if (null !== $backendConfig->getStereoToolConfigurationPath()) {
|
|
$this->doDeleteStereoToolConfiguration($station, $fs);
|
|
$backendConfig->setStereoToolConfigurationPath(null);
|
|
}
|
|
|
|
$stereoToolConfigurationPath = 'stereo-tool.sts';
|
|
$fs->uploadAndDeleteOriginal($file->getUploadedPath(), $stereoToolConfigurationPath);
|
|
|
|
$backendConfig->setStereoToolConfigurationPath($stereoToolConfigurationPath);
|
|
$station->setBackendConfig($backendConfig);
|
|
|
|
$this->em->persist($station);
|
|
$this->em->flush();
|
|
}
|
|
|
|
public function doDeleteStereoToolConfiguration(
|
|
Entity\Station $station,
|
|
?ExtendedFilesystemInterface $fs = null
|
|
): void {
|
|
$backendConfig = $station->getBackendConfig();
|
|
if (null === $backendConfig->getStereoToolConfigurationPath()) {
|
|
return;
|
|
}
|
|
|
|
$fs ??= (new StationFilesystems($station))->getConfigFilesystem();
|
|
$fs->delete($backendConfig->getStereoToolConfigurationPath());
|
|
}
|
|
|
|
public function clearStereoToolConfiguration(
|
|
Entity\Station $station,
|
|
?ExtendedFilesystemInterface $fs = null
|
|
): void {
|
|
$this->doDeleteStereoToolConfiguration($station, $fs);
|
|
|
|
$backendConfig = $station->getBackendConfig();
|
|
$backendConfig->setStereoToolConfigurationPath(null);
|
|
$station->setBackendConfig($backendConfig);
|
|
|
|
$this->em->persist($station);
|
|
$this->em->flush();
|
|
}
|
|
}
|