Code fixes and deprecated 8.1 fixes.
This commit is contained in:
parent
42b5db08d8
commit
1c814fc4c2
|
@ -143,10 +143,10 @@ class Acl
|
|||
*/
|
||||
public function userAllowed(
|
||||
?Entity\User $user = null,
|
||||
array|string $action,
|
||||
array|string $action = null,
|
||||
Entity\Station|int $stationId = null
|
||||
): bool {
|
||||
if (null === $user) {
|
||||
if (null === $user || null === $action) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Assets;
|
||||
|
||||
use App\Environment;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class AssetFactory
|
||||
{
|
||||
|
@ -33,7 +34,7 @@ class AssetFactory
|
|||
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.')
|
||||
default => throw new InvalidArgumentException('Invalid type specified.')
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace App\Assets;
|
|||
|
||||
use App\Utilities\File;
|
||||
use Intervention\Image\Image;
|
||||
use RuntimeException;
|
||||
|
||||
class BrowserIconCustomAsset extends AbstractCustomAsset
|
||||
{
|
||||
|
@ -42,7 +43,7 @@ class BrowserIconCustomAsset extends AbstractCustomAsset
|
|||
{
|
||||
$uploadsDir = $this->environment->getUploadsDirectory() . '/browser_icon';
|
||||
if (!mkdir($uploadsDir) && !is_dir($uploadsDir)) {
|
||||
throw new \RuntimeException(sprintf('Directory "%s" was not created', $uploadsDir));
|
||||
throw new RuntimeException(sprintf('Directory "%s" was not created', $uploadsDir));
|
||||
}
|
||||
|
||||
$newImage = clone $image;
|
||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Console;
|
||||
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Output\StreamOutput;
|
||||
|
||||
|
@ -25,7 +26,7 @@ class Application extends \Silly\Edition\PhpDi\Application
|
|||
|
||||
$temp_stream = fopen($outputFile, 'wb+');
|
||||
if (false === $temp_stream) {
|
||||
throw new \RuntimeException(sprintf('Could not open output file: "%s"', $outputFile));
|
||||
throw new RuntimeException(sprintf('Could not open output file: "%s"', $outputFile));
|
||||
}
|
||||
|
||||
$output = new StreamOutput($temp_stream);
|
||||
|
|
|
@ -31,12 +31,12 @@ class GenerateCommand extends CommandAbstract
|
|||
$directory = new RecursiveDirectoryIterator($environment->getBaseDirectory() . '/frontend/vue');
|
||||
$iterator = new RecursiveIteratorIterator($directory);
|
||||
|
||||
$vueRegex = new RegexIterator($iterator, '/^.+\.(vue)$/i', RecursiveRegexIterator::GET_MATCH);
|
||||
$vueRegex = new RegexIterator($iterator, '/^.+\.(vue)$/i', RegexIterator::GET_MATCH);
|
||||
foreach ($vueRegex as $pathMatch) {
|
||||
$translations->addFromVueJsFile($pathMatch[0]);
|
||||
}
|
||||
|
||||
$jsRegex = new RegexIterator($iterator, '/^.+\.(js)$/i', RecursiveRegexIterator::GET_MATCH);
|
||||
$jsRegex = new RegexIterator($iterator, '/^.+\.(js)$/i', RegexIterator::GET_MATCH);
|
||||
foreach ($jsRegex as $pathMatch) {
|
||||
$translations->addFromJsCodeFile($pathMatch[0]);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class GenerateCommand extends CommandAbstract
|
|||
foreach ($translatable_folders as $folder) {
|
||||
$directory = new RecursiveDirectoryIterator($folder);
|
||||
$iterator = new RecursiveIteratorIterator($directory);
|
||||
$regex = new RegexIterator($iterator, '/^.+\.(phtml|php)$/i', RecursiveRegexIterator::GET_MATCH);
|
||||
$regex = new RegexIterator($iterator, '/^.+\.(phtml|php)$/i', RegexIterator::GET_MATCH);
|
||||
|
||||
foreach ($regex as $path_match) {
|
||||
$path = $path_match[0];
|
||||
|
|
|
@ -14,6 +14,9 @@ use App\Utilities;
|
|||
use Doctrine\ORM\Query;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Stringable;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
@ -104,8 +107,8 @@ abstract class AbstractApiCrudController
|
|||
array_merge(
|
||||
$context,
|
||||
[
|
||||
ObjectNormalizer::ENABLE_MAX_DEPTH => true,
|
||||
ObjectNormalizer::MAX_DEPTH_HANDLER => function (
|
||||
AbstractObjectNormalizer::ENABLE_MAX_DEPTH => true,
|
||||
AbstractObjectNormalizer::MAX_DEPTH_HANDLER => function (
|
||||
$innerObject,
|
||||
$outerObject,
|
||||
string $attributeName,
|
||||
|
@ -114,7 +117,7 @@ abstract class AbstractApiCrudController
|
|||
) {
|
||||
return $this->displayShortenedObject($innerObject);
|
||||
},
|
||||
ObjectNormalizer::CIRCULAR_REFERENCE_HANDLER => function (
|
||||
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function (
|
||||
$object,
|
||||
string $format = null,
|
||||
array $context = []
|
||||
|
@ -140,7 +143,7 @@ abstract class AbstractApiCrudController
|
|||
return $object->getIdRequired();
|
||||
}
|
||||
|
||||
if ($object instanceof \Stringable) {
|
||||
if ($object instanceof Stringable) {
|
||||
return (string)$object;
|
||||
}
|
||||
|
||||
|
@ -183,7 +186,7 @@ abstract class AbstractApiCrudController
|
|||
protected function fromArray(array $data, ?object $record = null, array $context = []): object
|
||||
{
|
||||
if (null !== $record) {
|
||||
$context[ObjectNormalizer::OBJECT_TO_POPULATE] = $record;
|
||||
$context[AbstractNormalizer::OBJECT_TO_POPULATE] = $record;
|
||||
}
|
||||
|
||||
return $this->serializer->denormalize($data, $this->entityClass, null, $context);
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace App\Controller\Api\Admin\Backups;
|
|||
use App\Entity;
|
||||
use App\Exception\NotFoundException;
|
||||
use Azura\Files\ExtendedFilesystemInterface;
|
||||
use InvalidArgumentException;
|
||||
use JetBrains\PhpStorm\ArrayShape;
|
||||
|
||||
abstract class AbstractFileAction
|
||||
|
@ -28,7 +29,7 @@ abstract class AbstractFileAction
|
|||
);
|
||||
|
||||
if (!($storageLocation instanceof Entity\StorageLocation)) {
|
||||
throw new \InvalidArgumentException('Invalid storage location.');
|
||||
throw new InvalidArgumentException('Invalid storage location.');
|
||||
}
|
||||
|
||||
$fs = $storageLocation->getFilesystem();
|
||||
|
|
|
@ -7,7 +7,9 @@ namespace App\Controller\Api\Admin;
|
|||
use App\Acl;
|
||||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Entity;
|
||||
use InvalidArgumentException;
|
||||
use OpenApi\Annotations as OA;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
@ -114,12 +116,12 @@ class RolesController extends AbstractAdminApiCrudController
|
|||
protected function deleteRecord(object $record): void
|
||||
{
|
||||
if (!($record instanceof Entity\Role)) {
|
||||
throw new \InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
|
||||
throw new InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
|
||||
}
|
||||
|
||||
$superAdminRole = $this->permissionRepo->ensureSuperAdministratorRole();
|
||||
if ($superAdminRole->getIdRequired() === $record->getIdRequired()) {
|
||||
throw new \RuntimeException('Cannot remove the Super Administrator role.');
|
||||
throw new RuntimeException('Cannot remove the Super Administrator role.');
|
||||
}
|
||||
|
||||
parent::deleteRecord($record);
|
||||
|
|
|
@ -8,6 +8,7 @@ use App\Controller\Frontend\Account\MasqueradeAction;
|
|||
use App\Entity;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use InvalidArgumentException;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
|
@ -84,7 +85,7 @@ class UsersController extends AbstractAdminApiCrudController
|
|||
protected function viewRecord(object $record, ServerRequest $request): mixed
|
||||
{
|
||||
if (!($record instanceof Entity\User)) {
|
||||
throw new \InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
|
||||
throw new InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
|
||||
}
|
||||
|
||||
$return = $this->toArray($record);
|
||||
|
|
|
@ -8,7 +8,9 @@ use App\Controller\Api\Admin\UsersController;
|
|||
use App\Entity;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Throwable;
|
||||
|
||||
class PutPasswordAction extends UsersController
|
||||
{
|
||||
|
@ -19,16 +21,16 @@ class PutPasswordAction extends UsersController
|
|||
|
||||
try {
|
||||
if (empty($body['current_password'])) {
|
||||
throw new \InvalidArgumentException('Current password not provided (current_password).');
|
||||
throw new InvalidArgumentException('Current password not provided (current_password).');
|
||||
}
|
||||
|
||||
$currentPassword = $body['current_password'];
|
||||
if (!$user->verifyPassword($currentPassword)) {
|
||||
throw new \InvalidArgumentException('Invalid current password.');
|
||||
throw new InvalidArgumentException('Invalid current password.');
|
||||
}
|
||||
|
||||
if (empty($body['new_password'])) {
|
||||
throw new \InvalidArgumentException('New password not provided (new_password).');
|
||||
throw new InvalidArgumentException('New password not provided (new_password).');
|
||||
}
|
||||
|
||||
$user = $this->em->refetch($user);
|
||||
|
@ -38,7 +40,7 @@ class PutPasswordAction extends UsersController
|
|||
$this->em->flush();
|
||||
|
||||
return $response->withJson(Entity\Api\Status::updated());
|
||||
} catch (\Throwable $e) {
|
||||
} catch (Throwable $e) {
|
||||
return $response->withStatus(400)->withJson(Entity\Api\Error::fromException($e));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ use App\Entity;
|
|||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use BaconQrCode;
|
||||
use InvalidArgumentException;
|
||||
use OTPHP\TOTP;
|
||||
use ParagonIE\ConstantTime\Base32;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Throwable;
|
||||
|
||||
class PutTwoFactorAction extends UsersController
|
||||
{
|
||||
|
@ -26,7 +28,7 @@ class PutTwoFactorAction extends UsersController
|
|||
if (!empty($params['secret'])) {
|
||||
$secret = $params['secret'];
|
||||
if (64 !== strlen($secret)) {
|
||||
throw new \InvalidArgumentException('Secret is not the correct length.');
|
||||
throw new InvalidArgumentException('Secret is not the correct length.');
|
||||
}
|
||||
} else {
|
||||
// Generate new TOTP secret.
|
||||
|
@ -52,7 +54,7 @@ class PutTwoFactorAction extends UsersController
|
|||
return $response->withJson(Entity\Api\Status::success());
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Could not verify TOTP code.');
|
||||
throw new InvalidArgumentException('Could not verify TOTP code.');
|
||||
}
|
||||
|
||||
// Further customize TOTP code (with metadata that won't be stored in the DB)
|
||||
|
@ -74,7 +76,7 @@ class PutTwoFactorAction extends UsersController
|
|||
'totp_uri' => $totp_uri,
|
||||
'qr_code' => $qrCodeBase64,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
} catch (Throwable $e) {
|
||||
return $response->withStatus(400)->withJson(Entity\Api\Error::fromException($e));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Controller\Api\Stations\Art;
|
||||
|
||||
use App\Entity;
|
||||
use App\Exception\NoFileUploadedException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Service\Flow;
|
||||
|
@ -21,7 +22,7 @@ class PostArtAction
|
|||
* @param int|string $media_id
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws \App\Exception\NoFileUploadedException
|
||||
* @throws NoFileUploadedException
|
||||
*/
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
|
|
|
@ -10,6 +10,7 @@ use App\Http\Response;
|
|||
use App\Http\ServerRequest;
|
||||
use App\Sync\Task\RunAutomatedAssignmentTask;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Throwable;
|
||||
|
||||
class RunAction extends StationsController
|
||||
{
|
||||
|
@ -23,7 +24,7 @@ class RunAction extends StationsController
|
|||
try {
|
||||
$syncTask->runStation($station, true);
|
||||
return $response->withJson(Entity\Api\Status::success());
|
||||
} catch (\Throwable $e) {
|
||||
} catch (Throwable $e) {
|
||||
return $response->withStatus(400)->withJson(Entity\Api\Error::fromException($e));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ use GuzzleHttp\Psr7\Stream;
|
|||
use League\Csv\Writer;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use RuntimeException;
|
||||
|
||||
class ListenersAction
|
||||
{
|
||||
|
@ -240,7 +241,7 @@ class ListenersAction
|
|||
array $listeners,
|
||||
string $filename
|
||||
): ResponseInterface {
|
||||
$tempFile = tmpfile() ?: throw new \RuntimeException('Could not create temp file.');
|
||||
$tempFile = tmpfile() ?: throw new RuntimeException('Could not create temp file.');
|
||||
$csv = Writer::createFromStream($tempFile);
|
||||
|
||||
$tz = $station->getTimezoneObject();
|
||||
|
|
|
@ -82,7 +82,7 @@ class ImportAction extends AbstractPlaylistsAction
|
|||
// Work backwards from the basename to try to find matches.
|
||||
$pathParts = explode('/', $path_raw);
|
||||
$basename = File::sanitizeFileName(array_pop($pathParts));
|
||||
array_push($pathParts, $basename);
|
||||
$pathParts[] = $basename;
|
||||
|
||||
// Attempt full path matching if possible
|
||||
if (count($pathParts) >= 2) {
|
||||
|
@ -98,7 +98,6 @@ class ImportAction extends AbstractPlaylistsAction
|
|||
// Attempt basename-only matching
|
||||
if (isset($basenameLookup[$basename])) {
|
||||
$matches[] = $basenameLookup[$basename];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ use App\Http\ServerRequest;
|
|||
use App\Service\Flow\UploadedFile;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
|
@ -208,7 +209,7 @@ class PodcastEpisodesController extends AbstractApiCrudController
|
|||
|
||||
$podcast = $this->podcastRepository->fetchPodcastForStation($station, $podcast_id);
|
||||
if (null === $podcast) {
|
||||
throw new \RuntimeException('Podcast not found.');
|
||||
throw new RuntimeException('Podcast not found.');
|
||||
}
|
||||
|
||||
$parsedBody = (array)$request->getParsedBody();
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace App\Controller\Api\Stations;
|
|||
|
||||
use App\Entity;
|
||||
use App\Http\ServerRequest;
|
||||
use InvalidArgumentException;
|
||||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
|
@ -103,7 +104,7 @@ class WebhooksController extends AbstractStationApiCrudController
|
|||
protected function viewRecord(object $record, ServerRequest $request): mixed
|
||||
{
|
||||
if (!($record instanceof Entity\StationWebhook)) {
|
||||
throw new \InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
|
||||
throw new InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
|
||||
}
|
||||
|
||||
$return = $this->toArray($record);
|
||||
|
|
|
@ -8,6 +8,7 @@ use App\Exception\NotFoundException;
|
|||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use RuntimeException;
|
||||
|
||||
trait HasLogViewer
|
||||
{
|
||||
|
@ -58,7 +59,7 @@ trait HasLogViewer
|
|||
if ($log_visible_size > 0) {
|
||||
$fp = fopen($log_path, 'rb');
|
||||
if (false === $fp) {
|
||||
throw new \RuntimeException(sprintf('Could not open file at path "%s".', $log_path));
|
||||
throw new RuntimeException(sprintf('Could not open file at path "%s".', $log_path));
|
||||
}
|
||||
|
||||
fseek($fp, -$log_visible_size, SEEK_END);
|
||||
|
|
|
@ -9,6 +9,7 @@ use App\Http\ServerRequest;
|
|||
use App\Radio\AutoDJ\Scheduler;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Carbon\CarbonInterface;
|
||||
use InvalidArgumentException;
|
||||
|
||||
trait HasScheduleDisplay
|
||||
{
|
||||
|
@ -21,7 +22,7 @@ trait HasScheduleDisplay
|
|||
$startDate = CarbonImmutable::createFromFormat('Y-m-d', $startDateStr, $tz);
|
||||
|
||||
if (false === $startDate) {
|
||||
throw new \InvalidArgumentException(sprintf('Could not parse start date: "%s"', $startDateStr));
|
||||
throw new InvalidArgumentException(sprintf('Could not parse start date: "%s"', $startDateStr));
|
||||
}
|
||||
|
||||
$startDate = $startDate->startOf('day');
|
||||
|
@ -30,7 +31,7 @@ trait HasScheduleDisplay
|
|||
$endDate = CarbonImmutable::createFromFormat('Y-m-d', $endDateStr, $tz);
|
||||
|
||||
if (false === $endDate) {
|
||||
throw new \InvalidArgumentException(sprintf('Could not parse end date: "%s"', $endDateStr));
|
||||
throw new InvalidArgumentException(sprintf('Could not parse end date: "%s"', $endDateStr));
|
||||
}
|
||||
|
||||
$endDate = $endDate->endOf('day');
|
||||
|
|
|
@ -9,7 +9,9 @@ use App\Http\Response;
|
|||
use App\Http\ServerRequest;
|
||||
use App\Session\Flash;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Throwable;
|
||||
|
||||
class RecoverAction
|
||||
{
|
||||
|
@ -45,7 +47,7 @@ class RecoverAction
|
|||
$csrf->verify($data['csrf'] ?? null, 'recover');
|
||||
|
||||
if (empty($data['password'])) {
|
||||
throw new \InvalidArgumentException('Password required.');
|
||||
throw new InvalidArgumentException('Password required.');
|
||||
}
|
||||
|
||||
$user = $request->getUser();
|
||||
|
@ -69,7 +71,7 @@ class RecoverAction
|
|||
);
|
||||
|
||||
return $response->withRedirect((string)$request->getRouter()->named('dashboard'));
|
||||
} catch (\Throwable $e) {
|
||||
} catch (Throwable $e) {
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,10 @@ use App\Session\Flash;
|
|||
use App\Version;
|
||||
use App\VueComponent\StationFormComponent;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Throwable;
|
||||
|
||||
class SetupController
|
||||
{
|
||||
|
@ -65,7 +67,7 @@ class SetupController
|
|||
$csrf->verify($data['csrf'] ?? null, 'register');
|
||||
|
||||
if (empty($data['username']) || empty($data['password'])) {
|
||||
throw new \InvalidArgumentException('Username and password required.');
|
||||
throw new InvalidArgumentException('Username and password required.');
|
||||
}
|
||||
|
||||
$role = $permissionRepo->ensureSuperAdministratorRole();
|
||||
|
@ -92,7 +94,7 @@ class SetupController
|
|||
$acl->reload();
|
||||
|
||||
return $response->withRedirect((string)$request->getRouter()->named('setup:index'));
|
||||
} catch (\Throwable $e) {
|
||||
} catch (Throwable $e) {
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use Carbon\CarbonImmutable;
|
|||
use DateTimeInterface;
|
||||
use DateTimeZone;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use RuntimeException;
|
||||
|
||||
#[
|
||||
ORM\Entity(readOnly: true),
|
||||
|
@ -98,7 +99,7 @@ class Analytics implements IdentifiableEntityInterface
|
|||
public function getMomentInStationTimeZone(): CarbonImmutable
|
||||
{
|
||||
if (null === $this->station) {
|
||||
throw new \RuntimeException('Cannot get moment in station timezone; no station associated.');
|
||||
throw new RuntimeException('Cannot get moment in station timezone; no station associated.');
|
||||
}
|
||||
|
||||
$tz = $this->station->getTimezoneObject();
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace App\Entity\Api;
|
|||
|
||||
use App\Exception;
|
||||
use OpenApi\Annotations as OA;
|
||||
use ReflectionClass;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
|
@ -104,7 +105,7 @@ class Error
|
|||
$code = 500;
|
||||
}
|
||||
|
||||
$className = (new \ReflectionClass($e))->getShortName();
|
||||
$className = (new ReflectionClass($e))->getShortName();
|
||||
|
||||
$errorHeader = $className . ' at ' . $e->getFile() . ' L' . $e->getLine();
|
||||
$message = $errorHeader . ': ' . $e->getMessage();
|
||||
|
|
|
@ -96,11 +96,7 @@ class NowPlayingApiGenerator
|
|||
? $current_streamer->getDisplayName()
|
||||
: 'Live DJ';
|
||||
|
||||
$broadcastStart = null;
|
||||
$broadcast = $this->broadcastRepo->getLatestBroadcast($station);
|
||||
if (null !== $broadcast) {
|
||||
$broadcastStart = $broadcast->getTimestampStart();
|
||||
}
|
||||
$broadcastStart = $this->broadcastRepo->getLatestBroadcast($station)?->getTimestampStart();
|
||||
|
||||
$np->live = new Entity\Api\NowPlaying\Live(true, $streamer_name, $broadcastStart);
|
||||
} else {
|
||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace App\Entity\ApiGenerator;
|
||||
|
||||
use App\Entity;
|
||||
use App\Entity\Api\NowPlaying\SongHistory;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
class SongHistoryApiGenerator
|
||||
|
@ -20,8 +21,8 @@ class SongHistoryApiGenerator
|
|||
Entity\SongHistory $record,
|
||||
?UriInterface $baseUri = null,
|
||||
bool $allowRemoteArt = false
|
||||
): Entity\Api\NowPlaying\SongHistory {
|
||||
$response = new Entity\Api\NowPlaying\SongHistory();
|
||||
): SongHistory {
|
||||
$response = new SongHistory();
|
||||
$response->sh_id = $record->getIdRequired();
|
||||
$response->played_at = (0 === $record->getTimestampStart())
|
||||
? 0
|
||||
|
@ -64,7 +65,7 @@ class SongHistoryApiGenerator
|
|||
* @param UriInterface|null $baseUri
|
||||
* @param bool $allowRemoteArt
|
||||
*
|
||||
* @return \App\Entity\Api\NowPlaying\SongHistory[]
|
||||
* @return SongHistory[]
|
||||
*/
|
||||
public function fromArray(
|
||||
array $records,
|
||||
|
|
|
@ -70,7 +70,7 @@ class ListenerRepository extends Repository
|
|||
*/
|
||||
public function update(Entity\Station $station, array $clients): void
|
||||
{
|
||||
$this->em->transactional(
|
||||
$this->em->wrapInTransaction(
|
||||
function () use ($station, $clients): void {
|
||||
$existingClientsRaw = $this->em->createQuery(
|
||||
<<<'DQL'
|
||||
|
@ -102,18 +102,18 @@ class ListenerRepository extends Repository
|
|||
} else {
|
||||
// Create a new record.
|
||||
$record = [
|
||||
'station_id' => $station->getId(),
|
||||
'timestamp_start' => time(),
|
||||
'timestamp_end' => 0,
|
||||
'listener_uid' => (int)$client->uid,
|
||||
'station_id' => $station->getId(),
|
||||
'timestamp_start' => time(),
|
||||
'timestamp_end' => 0,
|
||||
'listener_uid' => (int)$client->uid,
|
||||
'listener_user_agent' => mb_substr(
|
||||
$client->userAgent ?? '',
|
||||
0,
|
||||
255,
|
||||
'UTF-8'
|
||||
),
|
||||
'listener_ip' => $client->ip,
|
||||
'listener_hash' => Entity\Listener::calculateListenerHash($client),
|
||||
'listener_ip' => $client->ip,
|
||||
'listener_hash' => Entity\Listener::calculateListenerHash($client),
|
||||
];
|
||||
|
||||
if (!empty($client->mount)) {
|
||||
|
|
|
@ -66,7 +66,7 @@ class StationMediaRepository extends Repository
|
|||
$media = $this->repository->findOneBy(
|
||||
[
|
||||
'storage_location' => $storageLocation,
|
||||
'id' => $id,
|
||||
'id' => $id,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -86,7 +86,7 @@ class StationMediaRepository extends Repository
|
|||
$media = $this->repository->findOneBy(
|
||||
[
|
||||
'storage_location' => $storageLocation,
|
||||
'path' => $path,
|
||||
'path' => $path,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -120,7 +120,7 @@ class StationMediaRepository extends Repository
|
|||
$media = $this->repository->findOneBy(
|
||||
[
|
||||
'storage_location' => $storageLocation,
|
||||
'unique_id' => $uniqueId,
|
||||
'unique_id' => $uniqueId,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -382,12 +382,8 @@ class StationMediaRepository extends Repository
|
|||
return $fs->withLocalFile(
|
||||
$media->getPath(),
|
||||
function ($path) use ($metadata) {
|
||||
try {
|
||||
$this->metadataManager->write($metadata, $path);
|
||||
return true;
|
||||
} catch (CannotProcessMediaException $e) {
|
||||
throw $e;
|
||||
}
|
||||
$this->metadataManager->write($metadata, $path);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ class StationPlaylistMediaRepository extends Repository
|
|||
DQL
|
||||
)->setParameter('playlist_id', $playlist->getId());
|
||||
|
||||
$this->em->transactional(
|
||||
$this->em->wrapInTransaction(
|
||||
function () use ($update_query, $mapping): void {
|
||||
foreach ($mapping as $id => $weight) {
|
||||
$update_query->setParameter('id', $id)
|
||||
|
|
|
@ -8,8 +8,6 @@ use App\Doctrine\ReloadableEntityManagerInterface;
|
|||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Flysystem\StationFilesystems;
|
||||
use App\Radio\Adapters;
|
||||
use App\Radio\AutoDJ\Scheduler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
@ -104,10 +102,6 @@ class StationStreamerRepository extends Repository
|
|||
|
||||
public function onDisconnect(Entity\Station $station): bool
|
||||
{
|
||||
$fs = new StationFilesystems($station);
|
||||
$fsTemp = $fs->getTempFilesystem();
|
||||
$fsRecordings = $fs->getRecordingsFilesystem();
|
||||
|
||||
foreach ($this->broadcastRepo->getActiveBroadcasts($station) as $broadcast) {
|
||||
$broadcast->setTimestampEnd(time());
|
||||
$this->em->persist($broadcast);
|
||||
|
|
|
@ -14,6 +14,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||
use GuzzleHttp\Psr7\Uri;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use RuntimeException;
|
||||
use Stringable;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
@ -47,7 +48,7 @@ class Settings implements Stringable
|
|||
public function getAppUniqueIdentifier(): string
|
||||
{
|
||||
if (!isset($this->app_unique_identifier)) {
|
||||
throw new \RuntimeException('Application Unique ID not generated yet.');
|
||||
throw new RuntimeException('Application Unique ID not generated yet.');
|
||||
}
|
||||
|
||||
return $this->app_unique_identifier;
|
||||
|
|
|
@ -16,6 +16,7 @@ use DateTimeZone;
|
|||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use InvalidArgumentException;
|
||||
use League\Flysystem\UnixVisibility\PortableVisibilityConverter;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
@ -925,12 +926,12 @@ class Station implements Stringable, IdentifiableEntityInterface
|
|||
{
|
||||
$supportedTypes = self::getStorageLocationTypes();
|
||||
if (!isset($supportedTypes[$type])) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid type: %s', $type));
|
||||
throw new InvalidArgumentException(sprintf('Invalid type: %s', $type));
|
||||
}
|
||||
|
||||
$record = $this->{$supportedTypes[$type]};
|
||||
if (null === $record) {
|
||||
throw new \RuntimeException(sprintf('Storage location for type %s has not been configured yet.', $type));
|
||||
throw new RuntimeException(sprintf('Storage location for type %s has not been configured yet.', $type));
|
||||
}
|
||||
return $record;
|
||||
}
|
||||
|
@ -943,12 +944,12 @@ class Station implements Stringable, IdentifiableEntityInterface
|
|||
}
|
||||
|
||||
if ($type !== $newStorageLocation->getType()) {
|
||||
throw new \InvalidArgumentException(sprintf('Specified location is not of type %s.', $type));
|
||||
throw new InvalidArgumentException(sprintf('Specified location is not of type %s.', $type));
|
||||
}
|
||||
|
||||
$supportedTypes = self::getStorageLocationTypes();
|
||||
if (!isset($supportedTypes[$type])) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid type: %s', $type));
|
||||
throw new InvalidArgumentException(sprintf('Invalid type: %s', $type));
|
||||
}
|
||||
|
||||
$this->{$supportedTypes[$type]} = $newStorageLocation;
|
||||
|
|
|
@ -84,11 +84,11 @@ class StationPlaylistMedia implements JsonSerializable, IdentifiableEntityInterf
|
|||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->playlist->getId(),
|
||||
'name' => $this->playlist->getName(),
|
||||
'id' => $this->playlist->getId(),
|
||||
'name' => $this->playlist->getName(),
|
||||
'weight' => $this->weight,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
|||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use Spatie\Dropbox\Client;
|
||||
use Stringable;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
@ -443,7 +444,7 @@ class StorageLocation implements Stringable, IdentifiableEntityInterface
|
|||
case self::ADAPTER_S3:
|
||||
$bucket = $this->s3Bucket;
|
||||
if (null === $bucket) {
|
||||
throw new \RuntimeException('Amazon S3 bucket is empty.');
|
||||
throw new RuntimeException('Amazon S3 bucket is empty.');
|
||||
}
|
||||
return new AwsS3Adapter($this->getS3Client(), $bucket, $filteredPath);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace App\Entity\Traits;
|
|||
use App\Entity\Interfaces\EntityGroupsInterface;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use OpenApi\Annotations as OA;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
/**
|
||||
|
@ -28,7 +29,7 @@ trait HasAutoIncrementId
|
|||
public function getIdRequired(): int
|
||||
{
|
||||
if (null === $this->id) {
|
||||
throw new \RuntimeException('An ID was not generated for this object.');
|
||||
throw new RuntimeException('An ID was not generated for this object.');
|
||||
}
|
||||
|
||||
return $this->id;
|
||||
|
|
|
@ -8,6 +8,7 @@ use App\Doctrine\Generator\UuidV6Generator;
|
|||
use App\Entity\Interfaces\EntityGroupsInterface;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use OpenApi\Annotations as OA;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
/**
|
||||
|
@ -29,7 +30,7 @@ trait HasUniqueId
|
|||
public function getIdRequired(): string
|
||||
{
|
||||
if (null === $this->id) {
|
||||
throw new \RuntimeException('An ID was not generated for this object.');
|
||||
throw new RuntimeException('An ID was not generated for this object.');
|
||||
}
|
||||
|
||||
return $this->id;
|
||||
|
|
|
@ -23,7 +23,7 @@ final class Response extends \Slim\Http\Response
|
|||
* Send headers that expire the content immediately and prevent caching.
|
||||
* @return static
|
||||
*/
|
||||
public function withNoCache(): static
|
||||
public function withNoCache(): Response
|
||||
{
|
||||
$response = $this->response
|
||||
->withHeader('Pragma', 'no-cache')
|
||||
|
@ -31,7 +31,7 @@ final class Response extends \Slim\Http\Response
|
|||
->withHeader('Cache-Control', 'private, no-cache, no-store')
|
||||
->withHeader('X-Accel-Expires', '0'); // CloudFlare
|
||||
|
||||
return new static($response, $this->streamFactory);
|
||||
return new Response($response, $this->streamFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,7 +41,7 @@ final class Response extends \Slim\Http\Response
|
|||
*
|
||||
* @return static
|
||||
*/
|
||||
public function withCacheLifetime(int $seconds = self::CACHE_ONE_MONTH): static
|
||||
public function withCacheLifetime(int $seconds = self::CACHE_ONE_MONTH): Response
|
||||
{
|
||||
$response = $this->response
|
||||
->withHeader('Pragma', '')
|
||||
|
@ -49,7 +49,7 @@ final class Response extends \Slim\Http\Response
|
|||
->withHeader('Cache-Control', 'public, must-revalidate, max-age=' . $seconds)
|
||||
->withHeader('X-Accel-Expires', (string)$seconds); // CloudFlare
|
||||
|
||||
return new static($response, $this->streamFactory);
|
||||
return new Response($response, $this->streamFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,7 +88,7 @@ final class Response extends \Slim\Http\Response
|
|||
*
|
||||
* @return static
|
||||
*/
|
||||
public function renderFile(string $file_path, $file_name = null): static
|
||||
public function renderFile(string $file_path, $file_name = null): Response
|
||||
{
|
||||
set_time_limit(600);
|
||||
|
||||
|
@ -107,7 +107,7 @@ final class Response extends \Slim\Http\Response
|
|||
->withHeader('Content-Disposition', 'attachment; filename=' . $file_name)
|
||||
->withBody($stream);
|
||||
|
||||
return new static($response, $this->streamFactory);
|
||||
return new Response($response, $this->streamFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,7 +119,7 @@ final class Response extends \Slim\Http\Response
|
|||
*
|
||||
* @return static
|
||||
*/
|
||||
public function renderStringAsFile(string $file_data, string $content_type, ?string $file_name = null): static
|
||||
public function renderStringAsFile(string $file_data, string $content_type, ?string $file_name = null): Response
|
||||
{
|
||||
$response = $this->response
|
||||
->withHeader('Pragma', 'public')
|
||||
|
@ -133,7 +133,7 @@ final class Response extends \Slim\Http\Response
|
|||
|
||||
$response->getBody()->write($file_data);
|
||||
|
||||
return new static($response, $this->streamFactory);
|
||||
return new Response($response, $this->streamFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,7 +149,7 @@ final class Response extends \Slim\Http\Response
|
|||
StreamInterface $fileStream,
|
||||
string $contentType,
|
||||
?string $fileName = null
|
||||
): static {
|
||||
): Response {
|
||||
set_time_limit(600);
|
||||
|
||||
$response = $this->response
|
||||
|
@ -164,7 +164,7 @@ final class Response extends \Slim\Http\Response
|
|||
|
||||
$response = $response->withBody($fileStream);
|
||||
|
||||
return new static($response, $this->streamFactory);
|
||||
return new Response($response, $this->streamFactory);
|
||||
}
|
||||
|
||||
public function streamFilesystemFile(
|
||||
|
|
|
@ -15,6 +15,7 @@ use App\RateLimit;
|
|||
use App\Session;
|
||||
use App\View;
|
||||
use Mezzio\Session\SessionInterface;
|
||||
use RuntimeException;
|
||||
|
||||
final class ServerRequest extends \Slim\Http\ServerRequest
|
||||
{
|
||||
|
@ -170,7 +171,7 @@ final class ServerRequest extends \Slim\Http\ServerRequest
|
|||
?? null;
|
||||
|
||||
if (null === $ip) {
|
||||
throw new \RuntimeException('No IP address attached to this request.');
|
||||
throw new RuntimeException('No IP address attached to this request.');
|
||||
}
|
||||
|
||||
// Handle the IP being separated by commas.
|
||||
|
|
|
@ -14,6 +14,7 @@ use Azura\MetadataManager\Metadata;
|
|||
use Azura\MetadataManager\MetadataInterface;
|
||||
use GuzzleHttp\Client;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Process\PhpExecutableFinder;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
@ -65,7 +66,7 @@ class MetadataManager implements EventSubscriberInterface
|
|||
try {
|
||||
$phpBinaryPath = (new PhpExecutableFinder())->find();
|
||||
if (false === $phpBinaryPath) {
|
||||
throw new \RuntimeException('Could not find PHP executable path.');
|
||||
throw new RuntimeException('Could not find PHP executable path.');
|
||||
}
|
||||
|
||||
$scriptPath = $this->environment->getBaseDirectory() . '/vendor/bin/metadata-manager';
|
||||
|
@ -134,7 +135,7 @@ class MetadataManager implements EventSubscriberInterface
|
|||
// Run remote process.
|
||||
$phpBinaryPath = (new PhpExecutableFinder())->find();
|
||||
if (false === $phpBinaryPath) {
|
||||
throw new \RuntimeException('Could not find PHP executable path.');
|
||||
throw new RuntimeException('Could not find PHP executable path.');
|
||||
}
|
||||
|
||||
$scriptPath = $this->environment->getBaseDirectory() . '/vendor/bin/metadata-manager';
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace App\Message;
|
|||
|
||||
use App\Entity\Api\NowPlaying\NowPlaying;
|
||||
use App\MessageQueue\QueueManager;
|
||||
use App\MessageQueue\QueueManagerInterface;
|
||||
|
||||
class DispatchWebhookMessage extends AbstractUniqueMessage
|
||||
{
|
||||
|
@ -23,6 +24,6 @@ class DispatchWebhookMessage extends AbstractUniqueMessage
|
|||
|
||||
public function getQueue(): string
|
||||
{
|
||||
return QueueManager::QUEUE_HIGH_PRIORITY;
|
||||
return QueueManagerInterface::QUEUE_HIGH_PRIORITY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ class TestQueueManager extends AbstractQueueManager
|
|||
{
|
||||
public function clearQueue(string $queueName): void
|
||||
{
|
||||
return; // Noop
|
||||
// Noop
|
||||
}
|
||||
|
||||
public function getTransport(string $queueName): TransportInterface
|
||||
|
|
|
@ -152,7 +152,7 @@ class AutoDJ
|
|||
);
|
||||
} else {
|
||||
// Prevent the exact same track from being played twice during this loop
|
||||
if (null !== $lastSongId && $lastSongId === $queueRow->getSongId()) {
|
||||
if ($lastSongId === $queueRow->getSongId()) {
|
||||
$this->em->remove($queueRow);
|
||||
continue;
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ class AutoDJ
|
|||
$this->em->persist($queueRow);
|
||||
|
||||
// Prevent the exact same track from being played twice during this loop
|
||||
if (null !== $lastSongId && $lastSongId === $queueRow->getSongId()) {
|
||||
if ($lastSongId === $queueRow->getSongId()) {
|
||||
$this->em->remove($queueRow);
|
||||
} else {
|
||||
$lastSongId = $queueRow->getSongId();
|
||||
|
|
|
@ -50,7 +50,7 @@ class Flow
|
|||
if (null === $tempDir) {
|
||||
$tempDir = sys_get_temp_dir() . '/uploads';
|
||||
if (!mkdir($tempDir) && !is_dir($tempDir)) {
|
||||
throw new \RuntimeException(sprintf('Directory "%s" was not created', $tempDir));
|
||||
throw new RuntimeException(sprintf('Directory "%s" was not created', $tempDir));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ class Flow
|
|||
$fp = fopen($finalPath, 'wb+');
|
||||
|
||||
if (false === $fp) {
|
||||
throw new \RuntimeException(
|
||||
throw new RuntimeException(
|
||||
sprintf(
|
||||
'Could not open final path "%s" for writing.',
|
||||
$finalPath
|
||||
|
@ -206,7 +206,7 @@ class Flow
|
|||
for ($i = 1; $i <= $numChunks; $i++) {
|
||||
$chunkContents = file_get_contents($chunkBaseDir . '/' . $chunkIdentifier . '.part' . $i);
|
||||
if (empty($chunkContents)) {
|
||||
throw new \RuntimeException(
|
||||
throw new RuntimeException(
|
||||
sprintf(
|
||||
'Could not load chunk "%d" for writing.',
|
||||
$i
|
||||
|
@ -248,7 +248,6 @@ class Flow
|
|||
unlink($dir . '/' . $object);
|
||||
}
|
||||
}
|
||||
reset($objects);
|
||||
rmdir($dir);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,14 @@ namespace App\Service\Flow;
|
|||
|
||||
use App\Utilities\File;
|
||||
use GuzzleHttp\Psr7\LazyOpenStream;
|
||||
use InvalidArgumentException;
|
||||
use JsonSerializable;
|
||||
use League\MimeTypeDetection\FinfoMimeTypeDetector;
|
||||
use League\MimeTypeDetection\GeneratedExtensionToMimeTypeMap;
|
||||
use Normalizer;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use RuntimeException;
|
||||
|
||||
final class UploadedFile implements UploadedFileInterface, JsonSerializable
|
||||
{
|
||||
|
@ -29,7 +32,7 @@ final class UploadedFile implements UploadedFileInterface, JsonSerializable
|
|||
$clientFilename ??= tempnam($tempDir, 'upload');
|
||||
|
||||
if (!$clientFilename || !$tempDir) {
|
||||
throw new \RuntimeException('Could not generate original filename.');
|
||||
throw new RuntimeException('Could not generate original filename.');
|
||||
}
|
||||
|
||||
$clientFilename = self::filterOriginalFilename($clientFilename);
|
||||
|
@ -41,14 +44,14 @@ final class UploadedFile implements UploadedFileInterface, JsonSerializable
|
|||
} else {
|
||||
$uploadedPath = realpath($uploadedPath);
|
||||
if (false === $uploadedPath) {
|
||||
throw new \InvalidArgumentException('Could not determine real path of specified path.');
|
||||
throw new InvalidArgumentException('Could not determine real path of specified path.');
|
||||
}
|
||||
if (!str_starts_with($uploadedPath, $tempDir)) {
|
||||
throw new \InvalidArgumentException('Uploaded path is not inside specified temporary directory.');
|
||||
throw new InvalidArgumentException('Uploaded path is not inside specified temporary directory.');
|
||||
}
|
||||
|
||||
if (!is_file($uploadedPath)) {
|
||||
throw new \InvalidArgumentException(sprintf('File does not exist at path: %s', $uploadedPath));
|
||||
throw new InvalidArgumentException(sprintf('File does not exist at path: %s', $uploadedPath));
|
||||
}
|
||||
|
||||
$this->file = $uploadedPath;
|
||||
|
@ -71,7 +74,7 @@ final class UploadedFile implements UploadedFileInterface, JsonSerializable
|
|||
|
||||
$size = filesize($this->file);
|
||||
if (false === $size) {
|
||||
throw new \RuntimeException('Could not get file size of uploaded path.');
|
||||
throw new RuntimeException('Could not get file size of uploaded path.');
|
||||
}
|
||||
|
||||
return $size;
|
||||
|
@ -119,7 +122,7 @@ final class UploadedFile implements UploadedFileInterface, JsonSerializable
|
|||
$this->moved = rename($this->file, $targetPath);
|
||||
|
||||
if (false === $this->moved) {
|
||||
throw new \RuntimeException(
|
||||
throw new RuntimeException(
|
||||
sprintf('Uploaded file could not be moved to %s', $targetPath)
|
||||
);
|
||||
}
|
||||
|
@ -133,7 +136,7 @@ final class UploadedFile implements UploadedFileInterface, JsonSerializable
|
|||
private function validateActive(): void
|
||||
{
|
||||
if ($this->moved) {
|
||||
throw new \RuntimeException('Cannot retrieve stream after it has already been moved');
|
||||
throw new RuntimeException('Cannot retrieve stream after it has already been moved');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +152,7 @@ final class UploadedFile implements UploadedFileInterface, JsonSerializable
|
|||
public static function fromArray(array $input, string $tempDir): self
|
||||
{
|
||||
if (!isset($input['originalFilename'], $input['uploadedPath'])) {
|
||||
throw new \InvalidArgumentException('Uploaded file array is malformed.');
|
||||
throw new InvalidArgumentException('Uploaded file array is malformed.');
|
||||
}
|
||||
|
||||
return new self($input['originalFilename'], $input['uploadedPath'], $tempDir);
|
||||
|
@ -158,7 +161,7 @@ final class UploadedFile implements UploadedFileInterface, JsonSerializable
|
|||
public static function filterOriginalFilename(string $name): string
|
||||
{
|
||||
$name = basename($name);
|
||||
$normalizedName = \Normalizer::normalize($name, \Normalizer::FORM_KD);
|
||||
$normalizedName = Normalizer::normalize($name, Normalizer::FORM_KD);
|
||||
if (false !== $normalizedName) {
|
||||
$name = $normalizedName;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ class CheckFolderPlaylistsTask extends AbstractTask
|
|||
continue;
|
||||
}
|
||||
|
||||
$this->em->transactional(
|
||||
$this->em->wrapInTransaction(
|
||||
function () use ($station, $playlist, $fsMedia, $mediaInPlaylistQuery, $mediaInFolderQuery): void {
|
||||
$this->processPlaylist(
|
||||
$station,
|
||||
|
|
|
@ -12,6 +12,7 @@ use App\MessageQueue\QueueManagerInterface;
|
|||
use App\Radio\Quota;
|
||||
use Azura\Files\Attributes\FileAttributes;
|
||||
use Brick\Math\BigInteger;
|
||||
use Doctrine\ORM\AbstractQuery;
|
||||
use Doctrine\ORM\Query;
|
||||
use League\Flysystem\FilesystemException;
|
||||
use League\Flysystem\StorageAttributes;
|
||||
|
@ -182,7 +183,7 @@ class CheckMediaTask extends AbstractTask
|
|||
DQL
|
||||
)->setParameter('storageLocation', $storageLocation);
|
||||
|
||||
foreach ($existingMediaQuery->toIterable([], Query::HYDRATE_ARRAY) as $mediaRow) {
|
||||
foreach ($existingMediaQuery->toIterable([], AbstractQuery::HYDRATE_ARRAY) as $mediaRow) {
|
||||
// Check if media file still exists.
|
||||
$path = $mediaRow['path'];
|
||||
$pathHash = md5($path);
|
||||
|
@ -236,7 +237,7 @@ class CheckMediaTask extends AbstractTask
|
|||
DQL
|
||||
)->setParameter('storageLocation', $storageLocation);
|
||||
|
||||
$unprocessableRecords = $unprocessableMediaQuery->toIterable([], Query::HYDRATE_ARRAY);
|
||||
$unprocessableRecords = $unprocessableMediaQuery->toIterable([], AbstractQuery::HYDRATE_ARRAY);
|
||||
|
||||
foreach ($unprocessableRecords as $unprocessableRow) {
|
||||
$pathHash = md5($unprocessableRow['path']);
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace App\Sync\Task;
|
|||
|
||||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Entity;
|
||||
use App\Entity\Api\NowPlaying\NowPlaying;
|
||||
use App\Environment;
|
||||
use App\Event\Radio\GenerateRawNowPlaying;
|
||||
use App\Http\RouterInterface;
|
||||
|
@ -75,7 +76,7 @@ class NowPlayingTask extends AbstractTask implements EventSubscriberInterface
|
|||
/**
|
||||
* @param bool $force
|
||||
*
|
||||
* @return Entity\Api\NowPlaying\NowPlaying[]
|
||||
* @return NowPlaying[]
|
||||
*/
|
||||
protected function loadNowPlaying(bool $force = false): array
|
||||
{
|
||||
|
@ -99,7 +100,7 @@ class NowPlayingTask extends AbstractTask implements EventSubscriberInterface
|
|||
Entity\Station $station,
|
||||
bool $standalone = false,
|
||||
bool $force = false
|
||||
): Entity\Api\NowPlaying\NowPlaying {
|
||||
): NowPlaying {
|
||||
$lock = $this->lockFactory->createAndAcquireLock(
|
||||
resource: 'nowplaying_station_' . $station->getId(),
|
||||
ttl: 600,
|
||||
|
@ -294,10 +295,10 @@ class NowPlayingTask extends AbstractTask implements EventSubscriberInterface
|
|||
|
||||
protected function dispatchWebhooks(
|
||||
Entity\Station $station,
|
||||
Entity\Api\NowPlaying\NowPlaying $npOriginal,
|
||||
NowPlaying $npOriginal,
|
||||
bool $isStandalone = true
|
||||
): void {
|
||||
/** @var \App\Entity\Api\NowPlaying\NowPlaying $np */
|
||||
/** @var NowPlaying $np */
|
||||
$np = (new DeepCopy())->copy($npOriginal);
|
||||
$np->resolveUrls($this->router->getBaseUrl());
|
||||
$np->cache = 'event';
|
||||
|
@ -307,7 +308,7 @@ class NowPlayingTask extends AbstractTask implements EventSubscriberInterface
|
|||
Entity\StationWebhook::TRIGGER_ALL,
|
||||
];
|
||||
|
||||
if ($npOld instanceof Entity\Api\NowPlaying\NowPlaying) {
|
||||
if ($npOld instanceof NowPlaying) {
|
||||
if ($npOld->now_playing?->song?->id !== $np->now_playing?->song?->id) {
|
||||
$triggers[] = Entity\StationWebhook::TRIGGER_SONG_CHANGED;
|
||||
}
|
||||
|
@ -341,7 +342,7 @@ class NowPlayingTask extends AbstractTask implements EventSubscriberInterface
|
|||
|
||||
protected function updateCaches(
|
||||
Entity\Station $station,
|
||||
Entity\Api\NowPlaying\NowPlaying $np
|
||||
NowPlaying $np
|
||||
): void {
|
||||
// Replace the relevant station information in the cache and database.
|
||||
$this->logger->debug('Updating NowPlaying cache...');
|
||||
|
@ -351,7 +352,7 @@ class NowPlayingTask extends AbstractTask implements EventSubscriberInterface
|
|||
if ($np_full) {
|
||||
$np_new = [];
|
||||
foreach ($np_full as $np_old) {
|
||||
/** @var \App\Entity\Api\NowPlaying\NowPlaying $np_old */
|
||||
/** @var NowPlaying $np_old */
|
||||
if ($np_old->station->id === $station->getId()) {
|
||||
$np_new[] = $np;
|
||||
} else {
|
||||
|
|
|
@ -61,7 +61,7 @@ class RunAnalyticsTask extends AbstractTask
|
|||
$this->analyticsRepo->cleanup();
|
||||
|
||||
while ($day < $now) {
|
||||
$this->em->transactional(
|
||||
$this->em->wrapInTransaction(
|
||||
function () use ($day, $stations, $withListeners): void {
|
||||
$this->processDay($day, $stations, $withListeners);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use Codeception\Lib\ModuleContainer;
|
|||
use Codeception\TestInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use RuntimeException;
|
||||
use Slim\App;
|
||||
|
||||
class Module extends Framework implements DoctrineProvider
|
||||
|
@ -51,7 +52,7 @@ class Module extends Framework implements DoctrineProvider
|
|||
|
||||
$container = $this->app->getContainer();
|
||||
if (null === $container) {
|
||||
throw new \RuntimeException('Container was not set on App.');
|
||||
throw new RuntimeException('Container was not set on App.');
|
||||
}
|
||||
|
||||
$this->container = $container;
|
||||
|
|
|
@ -4,9 +4,11 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Utilities;
|
||||
|
||||
use FilesystemIterator;
|
||||
use InvalidArgumentException;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use RuntimeException;
|
||||
use SplFileInfo;
|
||||
|
||||
use function stripos;
|
||||
|
@ -41,12 +43,12 @@ class File
|
|||
{
|
||||
$str = mb_ereg_replace("([^\w\s\d\-_~,;\[\]\(\).])", '', $str);
|
||||
if (null === $str || false === $str) {
|
||||
throw new \RuntimeException('Cannot parse input string.');
|
||||
throw new RuntimeException('Cannot parse input string.');
|
||||
}
|
||||
|
||||
$str = mb_ereg_replace("([\.]{2,})", '.', $str);
|
||||
if (null === $str || false === $str) {
|
||||
throw new \RuntimeException('Cannot parse input string.');
|
||||
throw new RuntimeException('Cannot parse input string.');
|
||||
}
|
||||
|
||||
$str = str_replace(' ', '_', $str);
|
||||
|
@ -98,7 +100,7 @@ class File
|
|||
}
|
||||
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
|
||||
new RecursiveDirectoryIterator($source, FilesystemIterator::SKIP_DOTS),
|
||||
RecursiveIteratorIterator::CHILD_FIRST
|
||||
);
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Utilities;
|
||||
|
||||
use JsonException;
|
||||
use RuntimeException;
|
||||
|
||||
class Json
|
||||
{
|
||||
public static function loadFromFile(
|
||||
|
@ -15,9 +18,9 @@ class Json
|
|||
if (false !== $fileContents) {
|
||||
try {
|
||||
return (array)json_decode($fileContents, true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (\JsonException $e) {
|
||||
} catch (JsonException $e) {
|
||||
if ($throwOnError) {
|
||||
throw new \RuntimeException(
|
||||
throw new RuntimeException(
|
||||
sprintf(
|
||||
'Could not parse JSON at "%s": %s',
|
||||
$path,
|
||||
|
@ -27,10 +30,10 @@ class Json
|
|||
}
|
||||
}
|
||||
} elseif ($throwOnError) {
|
||||
throw new \RuntimeException(sprintf('Error reading file: "%s"', $path));
|
||||
throw new RuntimeException(sprintf('Error reading file: "%s"', $path));
|
||||
}
|
||||
} elseif ($throwOnError) {
|
||||
throw new \RuntimeException(sprintf('File not found: "%s"', $path));
|
||||
throw new RuntimeException(sprintf('File not found: "%s"', $path));
|
||||
}
|
||||
|
||||
return [];
|
||||
|
|
Loading…
Reference in New Issue